6307603: [X11] Use RENDER extension for complex operations done in software
authorceisserer
Fri, 28 May 2010 11:37:44 -0700
changeset 5579 1a5e995a710b
parent 5578 c25ebb5bc2d6
child 5580 629274e4c99f
6307603: [X11] Use RENDER extension for complex operations done in software Reviewed-by: bae, igor, prr
jdk/make/common/Defs-solaris.gmk
jdk/make/sun/awt/mapfile-mawt-vers
jdk/make/sun/awt/mapfile-vers-linux
jdk/make/sun/headless/mapfile-vers
jdk/make/sun/jawt/Makefile
jdk/make/sun/xawt/FILES_c_unix.gmk
jdk/make/sun/xawt/Makefile
jdk/make/sun/xawt/mapfile-vers
jdk/src/share/classes/sun/font/GlyphDisposedListener.java
jdk/src/share/classes/sun/font/StrikeCache.java
jdk/src/share/classes/sun/java2d/pipe/BufferedPaints.java
jdk/src/share/classes/sun/java2d/pipe/RenderBuffer.java
jdk/src/share/classes/sun/java2d/pisces/META-INF/services/sun.java2d.pipe.RenderingEngine
jdk/src/share/native/sun/font/AccelGlyphCache.c
jdk/src/share/native/sun/font/fontscalerdefs.h
jdk/src/share/native/sun/font/freetypeScaler.c
jdk/src/share/native/sun/font/sunFont.c
jdk/src/share/native/sun/java2d/opengl/OGLTextRenderer.c
jdk/src/solaris/classes/sun/awt/X11GraphicsDevice.java
jdk/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java
jdk/src/solaris/classes/sun/font/XRGlyphCache.java
jdk/src/solaris/classes/sun/font/XRGlyphCacheEntry.java
jdk/src/solaris/classes/sun/font/XRTextRenderer.java
jdk/src/solaris/classes/sun/java2d/UnixSurfaceManagerFactory.java
jdk/src/solaris/classes/sun/java2d/jules/IdleTileCache.java
jdk/src/solaris/classes/sun/java2d/jules/JulesAATileGenerator.java
jdk/src/solaris/classes/sun/java2d/jules/JulesPathBuf.java
jdk/src/solaris/classes/sun/java2d/jules/JulesRenderingEngine.java
jdk/src/solaris/classes/sun/java2d/jules/JulesShapePipe.java
jdk/src/solaris/classes/sun/java2d/jules/JulesTile.java
jdk/src/solaris/classes/sun/java2d/jules/TileWorker.java
jdk/src/solaris/classes/sun/java2d/jules/TrapezoidList.java
jdk/src/solaris/classes/sun/java2d/x11/X11SurfaceData.java
jdk/src/solaris/classes/sun/java2d/x11/XSurfaceData.java
jdk/src/solaris/classes/sun/java2d/xr/DirtyRegion.java
jdk/src/solaris/classes/sun/java2d/xr/GrowableByteArray.java
jdk/src/solaris/classes/sun/java2d/xr/GrowableEltArray.java
jdk/src/solaris/classes/sun/java2d/xr/GrowableIntArray.java
jdk/src/solaris/classes/sun/java2d/xr/GrowablePointArray.java
jdk/src/solaris/classes/sun/java2d/xr/GrowableRectArray.java
jdk/src/solaris/classes/sun/java2d/xr/MaskTile.java
jdk/src/solaris/classes/sun/java2d/xr/MaskTileManager.java
jdk/src/solaris/classes/sun/java2d/xr/MutableInteger.java
jdk/src/solaris/classes/sun/java2d/xr/XIDGenerator.java
jdk/src/solaris/classes/sun/java2d/xr/XRBackend.java
jdk/src/solaris/classes/sun/java2d/xr/XRBackendNative.java
jdk/src/solaris/classes/sun/java2d/xr/XRColor.java
jdk/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java
jdk/src/solaris/classes/sun/java2d/xr/XRDrawImage.java
jdk/src/solaris/classes/sun/java2d/xr/XRGraphicsConfig.java
jdk/src/solaris/classes/sun/java2d/xr/XRMaskBlit.java
jdk/src/solaris/classes/sun/java2d/xr/XRMaskFill.java
jdk/src/solaris/classes/sun/java2d/xr/XRMaskImage.java
jdk/src/solaris/classes/sun/java2d/xr/XRPMBlitLoops.java
jdk/src/solaris/classes/sun/java2d/xr/XRPaints.java
jdk/src/solaris/classes/sun/java2d/xr/XRRenderer.java
jdk/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java
jdk/src/solaris/classes/sun/java2d/xr/XRSurfaceDataProxy.java
jdk/src/solaris/classes/sun/java2d/xr/XRUtils.java
jdk/src/solaris/classes/sun/java2d/xr/XRVolatileSurfaceManager.java
jdk/src/solaris/classes/sun/java2d/xr/XcbRequestCounter.java
jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c
jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.h
jdk/src/solaris/native/sun/java2d/x11/XRBackendNative.c
jdk/src/solaris/native/sun/java2d/x11/XRSurfaceData.c
--- a/jdk/make/common/Defs-solaris.gmk	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/make/common/Defs-solaris.gmk	Fri May 28 11:37:44 2010 -0700
@@ -639,21 +639,8 @@
 #    in general this is ok to continue to do.
 LIBCXX = /usr/lib$(ISA_DIR)/libCrun.so.1
 
-# Math Library (libm.so), do not use -lm.
-#    There might be two versions of libm.so on the build system:
-#    libm.so.1 and libm.so.2, and we want libm.so.1.
-#    Depending on the Solaris release being used to build with,
-#    /usr/lib/libm.so could point at a libm.so.2, so we are
-#    explicit here so that the libjvm.so you have built will work on an
-#    older Solaris release that might not have libm.so.2.
-#    This is a critical factor in allowing builds on Solaris 10 or newer
-#    to run on Solaris 8 or 9.
-#
-#    Note: Historically there was also a problem picking up a static version
-#          of libm.a from the compiler area, but that problem has gone away
-#          with the newer compilers. Use of libm.a would cause .so bloat.
-#
-LIBM = /usr/lib$(ISA_DIR)/libm.so.1
+# JDK now requires Solaris 10, so pick up libm.so.2
+LIBM = /usr/lib$(ISA_DIR)/libm.so.2
 
 # Socket library
 LIBSOCKET = -lsocket
--- a/jdk/make/sun/awt/mapfile-mawt-vers	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/make/sun/awt/mapfile-mawt-vers	Fri May 28 11:37:44 2010 -0700
@@ -312,6 +312,7 @@
                 Java_sun_awt_X11GraphicsEnvironment_initGLX;
 		Java_sun_awt_X11GraphicsEnvironment_pRunningXinerama;
 		Java_sun_awt_X11GraphicsEnvironment_getXineramaCenterPoint;
+		Java_sun_awt_X11GraphicsEnvironment_initXRender;
                 #Java_sun_awt_motif_MEmbedCanvasPeer_initXEmbedServer;
                 #Java_sun_awt_motif_MEmbedCanvasPeer_destroyXEmbedServer;
                 #Java_sun_awt_motif_MEmbedCanvasPeer_isXEmbedActive;
@@ -406,18 +407,53 @@
 		Java_sun_java2d_x11_X11SurfaceData_initIDs;
 		Java_sun_java2d_x11_X11SurfaceData_initOps;
 		Java_sun_java2d_x11_X11SurfaceData_initSurface;
-		Java_sun_java2d_x11_X11SurfaceData_isDrawableValid;
 		Java_sun_java2d_x11_X11SurfaceData_isDgaAvailable;
 		Java_sun_java2d_x11_X11SurfaceData_isShmPMAvailable;
-		Java_sun_java2d_x11_X11SurfaceData_setInvalid;
-		Java_sun_java2d_x11_X11SurfaceData_flushNativeSurface;
-                Java_sun_java2d_x11_X11SurfaceData_XCreateGC;
-                Java_sun_java2d_x11_X11SurfaceData_XResetClip;
-                Java_sun_java2d_x11_X11SurfaceData_XSetClip;
                 Java_sun_java2d_x11_X11SurfaceData_XSetCopyMode;
                 Java_sun_java2d_x11_X11SurfaceData_XSetXorMode;
                 Java_sun_java2d_x11_X11SurfaceData_XSetForeground;
-                Java_sun_java2d_x11_X11SurfaceData_XSetGraphicsExposures;
+
+		Java_sun_java2d_x11_XSurfaceData_initOps;
+		Java_sun_java2d_x11_XSurfaceData_XCreateGC;
+		Java_sun_java2d_x11_XSurfaceData_XResetClip;
+		Java_sun_java2d_x11_XSurfaceData_XSetClip;
+		Java_sun_java2d_x11_XSurfaceData_flushNativeSurface;
+		Java_sun_java2d_x11_XSurfaceData_isDrawableValid;
+		Java_sun_java2d_x11_XSurfaceData_setInvalid;
+		Java_sun_java2d_x11_XSurfaceData_XSetGraphicsExposures;
+		Java_sun_java2d_xr_XRSurfaceData_initXRPicture;
+		Java_sun_java2d_xr_XRSurfaceData_initIDs;
+		Java_sun_java2d_xr_XRSurfaceData_XRInitSurface;
+		Java_sun_java2d_xr_XRBackendNative_initIDs;
+		Java_sun_java2d_xr_XIDGenerator_bufferXIDs;
+		Java_sun_java2d_xr_XRBackendNative_freeGC;
+		Java_sun_java2d_xr_XRBackendNative_createGC;
+		Java_sun_java2d_xr_XRBackendNative_createPixmap;
+		Java_sun_java2d_xr_XRBackendNative_createPictureNative;
+		Java_sun_java2d_xr_XRBackendNative_freePicture;
+		Java_sun_java2d_xr_XRBackendNative_freePixmap;
+		Java_sun_java2d_xr_XRBackendNative_setPictureRepeat;
+		Java_sun_java2d_xr_XRBackendNative_setGCExposures;
+		Java_sun_java2d_xr_XRBackendNative_setGCForeground;
+		Java_sun_java2d_xr_XRBackendNative_copyArea;
+		Java_sun_java2d_xr_XRBackendNative_renderComposite;
+		Java_sun_java2d_xr_XRBackendNative_renderRectangle;
+		Java_sun_java2d_xr_XRBackendNative_XRenderRectanglesNative;
+		Java_sun_java2d_xr_XRBackendNative_XRSetTransformNative;
+		Java_sun_java2d_xr_XRBackendNative_XRCreateLinearGradientPaintNative;
+		Java_sun_java2d_xr_XRBackendNative_XRCreateRadialGradientPaintNative;
+		Java_sun_java2d_xr_XRBackendNative_setFilter;
+		Java_sun_java2d_xr_XRBackendNative_XRSetClipNative;
+		Java_sun_java2d_xr_XRBackendNative_putMaskNative;
+		Java_sun_java2d_xr_XRBackendNative_XRAddGlyphsNative;
+		Java_sun_java2d_xr_XRBackendNative_XRFreeGlyphsNative;
+		Java_sun_java2d_xr_XRBackendNative_XRenderCreateGlyphSetNative;
+		Java_sun_java2d_xr_XRBackendNative_XRenderCompositeTextNative;
+		Java_sun_java2d_xr_XRBackendNative_setGCMode;
+		Java_sun_java2d_xr_XRBackendNative_GCRectanglesNative;
+		Java_sun_java2d_xr_XRUtils_initFormatPtrs;
+		Java_sun_java2d_xr_XRBackendNative_renderCompositeTrapezoidsNative;
+		XRT_DrawGlyphList;
 
                 Java_sun_java2d_opengl_OGLContext_getOGLIdString;
                 Java_sun_java2d_opengl_OGLMaskFill_maskFill;
--- a/jdk/make/sun/awt/mapfile-vers-linux	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/make/sun/awt/mapfile-vers-linux	Fri May 28 11:37:44 2010 -0700
@@ -425,6 +425,7 @@
 		Java_sun_awt_X11GraphicsEnvironment_initDisplay;
 		Java_sun_awt_X11GraphicsEnvironment_pRunningXinerama;
 		Java_sun_awt_X11GraphicsEnvironment_getXineramaCenterPoint;
+		Java_sun_awt_X11GraphicsEnvironment_initXRender;
         
         
 
--- a/jdk/make/sun/headless/mapfile-vers	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/make/sun/headless/mapfile-vers	Fri May 28 11:37:44 2010 -0700
@@ -46,17 +46,20 @@
 		Java_sun_java2d_x11_X11Renderer_XFillRoundRect;
 		Java_sun_java2d_x11_X11Renderer_devCopyArea;
 		Java_sun_java2d_x11_X11SurfaceData_initIDs;
-		Java_sun_java2d_x11_X11SurfaceData_initOps;
-		Java_sun_java2d_x11_X11SurfaceData_isDrawableValid;
 		Java_sun_java2d_x11_X11SurfaceData_initSurface;
-		Java_sun_java2d_x11_X11SurfaceData_setInvalid;
-                Java_sun_java2d_x11_X11SurfaceData_XCreateGC;
-                Java_sun_java2d_x11_X11SurfaceData_XResetClip;
-                Java_sun_java2d_x11_X11SurfaceData_XSetClip;
                 Java_sun_java2d_x11_X11SurfaceData_XSetCopyMode;
                 Java_sun_java2d_x11_X11SurfaceData_XSetXorMode;
                 Java_sun_java2d_x11_X11SurfaceData_XSetForeground;
 
+		Java_sun_java2d_x11_XSurfaceData_initOps;
+                Java_sun_java2d_x11_XSurfaceData_XCreateGC;
+                Java_sun_java2d_x11_XSurfaceData_XResetClip;
+                Java_sun_java2d_x11_XSurfaceData_XSetClip;
+                Java_sun_java2d_x11_XSurfaceData_flushNativeSurface;
+		Java_sun_java2d_x11_XSurfaceData_isDrawableValid;
+		Java_sun_java2d_x11_XSurfaceData_setInvalid;
+		Java_sun_java2d_x11_XSurfaceData_XSetGraphicsExposures;
+
 		X11SurfaceData_GetOps;
 		Java_java_awt_Font_initIDs;
                 Java_sun_font_FontConfigManager_getFontConfig;
--- a/jdk/make/sun/jawt/Makefile	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/make/sun/jawt/Makefile	Fri May 28 11:37:44 2010 -0700
@@ -113,7 +113,7 @@
 # Libraries to link in.
 #
 ifeq ($(PLATFORM), solaris)
-OTHER_LDLIBS = -L$(LIBDIR)/$(LIBARCH) -L$(OPENWIN_LIB) -L$(LIBDIR)/$(LIBARCH)/xawt -lmawt
+OTHER_LDLIBS = -L$(LIBDIR)/$(LIBARCH) -L$(OPENWIN_LIB) -L$(LIBDIR)/$(LIBARCH)/xawt -lmawt -L/usr/openwin/sfw/lib$(ISA_DIR) -lXrender
 endif # PLATFORM
 
 ifeq ($(PLATFORM), linux)
--- a/jdk/make/sun/xawt/FILES_c_unix.gmk	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/make/sun/xawt/FILES_c_unix.gmk	Fri May 28 11:37:44 2010 -0700
@@ -80,4 +80,6 @@
         swing_GTKEngine.c \
         swing_GTKStyle.c \
         rect.c \
-	sun_awt_X11_GtkFileDialogPeer.c
+	sun_awt_X11_GtkFileDialogPeer.c \
+	XRSurfaceData.c \
+	XRBackendNative.c
--- a/jdk/make/sun/xawt/Makefile	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/make/sun/xawt/Makefile	Fri May 28 11:37:44 2010 -0700
@@ -49,6 +49,11 @@
 
 LDFLAGS += -L$(OPENWIN_LIB)
 
+# For Xrender extension.
+ifeq ($(PLATFORM), solaris)
+LDFLAGS += -L/usr/openwin/sfw/lib$(ISA_DIR) -R/usr/openwin/sfw/lib$(ISA_DIR)
+endif
+
 ifeq ($(PLATFORM), linux)
 LDFLAGS += -lpthread
 dummy := $(shell $(MKDIR) -p $(LIB_LOCATION))
@@ -88,7 +93,7 @@
 vpath %.c   $(PLATFORM_SRC)/native/sun/java2d/opengl
 vpath %.c   $(PLATFORM_SRC)/native/sun/java2d/x11
 
-OTHER_LDLIBS = $(LIBM) -lawt -lXext -lX11 -ldl \
+OTHER_LDLIBS = $(LIBM) -lawt -lXext -lX11 -lXrender -ldl \
                    $(LDFLAGS_COMMON) $(AWT_RUNPATH) $(OTHER_LDFLAGS) -lXtst -lXi
 
 ifeq  ($(PLATFORM), solaris)
@@ -122,7 +127,7 @@
 	-I$(PLATFORM_SRC)/native/sun/awt/medialib \
         -I$(PLATFORM_SRC)/native/sun/font \
         -I$(SHARE_SRC)/native/sun/awt \
-        -I$(PLATFORM_SRC)/native/sun/awt 
+        -I$(PLATFORM_SRC)/native/sun/awt
 
 ifeq ($(PLATFORM), linux)
 # Allows for builds on Debian GNU Linux, X11 is in a different place 
--- a/jdk/make/sun/xawt/mapfile-vers	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/make/sun/xawt/mapfile-vers	Fri May 28 11:37:44 2010 -0700
@@ -192,6 +192,7 @@
 	Java_sun_font_X11FontManager_setNativeFontPath;
         Java_sun_awt_X11GraphicsEnvironment_initDisplay;
         Java_sun_awt_X11GraphicsEnvironment_initGLX;
+	Java_sun_awt_X11GraphicsEnvironment_initXRender;
         Java_sun_awt_X11GraphicsEnvironment_checkShmExt;
         Java_sun_awt_X11GraphicsEnvironment_getNumScreens;
         Java_sun_awt_X11GraphicsEnvironment_getDefaultScreenNum;
@@ -355,21 +356,52 @@
 	Java_sun_java2d_x11_X11Renderer_XFillRect;
 	Java_sun_java2d_x11_X11Renderer_XFillRoundRect;
         Java_sun_java2d_x11_X11Renderer_devCopyArea;
-        Java_sun_java2d_x11_X11SurfaceData_setInvalid;
         Java_sun_java2d_x11_X11SurfaceData_initIDs;
-	Java_sun_java2d_x11_X11SurfaceData_isDrawableValid;
         Java_sun_java2d_x11_X11SurfaceData_isDgaAvailable;
 	Java_sun_java2d_x11_X11SurfaceData_isShmPMAvailable;
-        Java_sun_java2d_x11_X11SurfaceData_initOps;
         Java_sun_java2d_x11_X11SurfaceData_initSurface;
-        Java_sun_java2d_x11_X11SurfaceData_flushNativeSurface;
-        Java_sun_java2d_x11_X11SurfaceData_XCreateGC;
-        Java_sun_java2d_x11_X11SurfaceData_XResetClip;
-        Java_sun_java2d_x11_X11SurfaceData_XSetClip;
         Java_sun_java2d_x11_X11SurfaceData_XSetCopyMode;
         Java_sun_java2d_x11_X11SurfaceData_XSetXorMode;
         Java_sun_java2d_x11_X11SurfaceData_XSetForeground;
-        Java_sun_java2d_x11_X11SurfaceData_XSetGraphicsExposures;
+
+        Java_sun_java2d_x11_XSurfaceData_initOps;
+        Java_sun_java2d_x11_XSurfaceData_XCreateGC;
+        Java_sun_java2d_x11_XSurfaceData_XResetClip;
+        Java_sun_java2d_x11_XSurfaceData_XSetClip;
+        Java_sun_java2d_x11_XSurfaceData_flushNativeSurface;
+	Java_sun_java2d_x11_XSurfaceData_isDrawableValid;
+        Java_sun_java2d_x11_XSurfaceData_setInvalid;
+        Java_sun_java2d_x11_XSurfaceData_XSetGraphicsExposures;
+        Java_sun_java2d_xr_XRSurfaceData_initXRPicture;
+        Java_sun_java2d_xr_XRSurfaceData_initIDs;
+        Java_sun_java2d_xr_XRSurfaceData_XRInitSurface;
+	Java_sun_java2d_xr_XRBackendNative_initIDs;
+	Java_sun_java2d_xr_XRBackendNative_freeGC;
+	Java_sun_java2d_xr_XRBackendNative_createGC;
+	Java_sun_java2d_xr_XRBackendNative_createPixmap;
+	Java_sun_java2d_xr_XRBackendNative_createPictureNative;
+	Java_sun_java2d_xr_XRBackendNative_freePicture;
+	Java_sun_java2d_xr_XRBackendNative_freePixmap;
+	Java_sun_java2d_xr_XRBackendNative_setPictureRepeat;
+	Java_sun_java2d_xr_XRBackendNative_setGCExposures;
+	Java_sun_java2d_xr_XRBackendNative_setGCForeground;
+	Java_sun_java2d_xr_XRBackendNative_copyArea;
+	Java_sun_java2d_xr_XRBackendNative_renderComposite;
+	Java_sun_java2d_xr_XRBackendNative_renderRectangle;
+	Java_sun_java2d_xr_XRBackendNative_XRenderRectanglesNative;
+	Java_sun_java2d_xr_XRBackendNative_XRSetTransformNative;
+	Java_sun_java2d_xr_XRBackendNative_XRCreateLinearGradientPaintNative;
+	Java_sun_java2d_xr_XRBackendNative_XRCreateRadialGradientPaintNative;
+	Java_sun_java2d_xr_XRBackendNative_setFilter;
+	Java_sun_java2d_xr_XRBackendNative_XRSetClipNative;
+	Java_sun_java2d_xr_XRBackendNative_putMaskNative;
+	Java_sun_java2d_xr_XRBackendNative_XRAddGlyphsNative;
+	Java_sun_java2d_xr_XRBackendNative_XRFreeGlyphsNative;
+	Java_sun_java2d_xr_XRBackendNative_XRenderCreateGlyphSetNative;
+	Java_sun_java2d_xr_XRBackendNative_XRenderCompositeTextNative;
+	Java_sun_java2d_xr_XRBackendNative_setGCMode;
+	Java_sun_java2d_xr_XRBackendNative_GCRectanglesNative;
+	Java_sun_java2d_xr_XRBackendNative_renderCompositeTrapezoidsNative;
 
         Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1arrow;
         Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1box;
@@ -397,8 +429,8 @@
         Java_com_sun_java_swing_plaf_gtk_GTKStyle_nativeGetClassValue;
         Java_com_sun_java_swing_plaf_gtk_GTKStyle_nativeGetPangoFontName;
 
-	Java_sun_awt_X11_GtkFileDialogPeer_run;
-	Java_sun_awt_X11_GtkFileDialogPeer_quit;
+        Java_sun_awt_X11_GtkFileDialogPeer_run;
+        Java_sun_awt_X11_GtkFileDialogPeer_quit;
 
 	Java_sun_print_CUPSPrinter_initIDs;
 	Java_sun_print_CUPSPrinter_getCupsServer;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/font/GlyphDisposedListener.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.font;
+
+import java.util.*;
+
+public interface GlyphDisposedListener {
+    public void glyphDisposed(ArrayList<Long> glyphs);
+}
--- a/jdk/src/share/classes/sun/font/StrikeCache.java	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/src/share/classes/sun/font/StrikeCache.java	Fri May 28 11:37:44 2010 -0700
@@ -31,6 +31,7 @@
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.SoftReference;
 import java.lang.ref.WeakReference;
+import java.util.*;
 
 import sun.java2d.Disposer;
 import sun.java2d.pipe.BufferedContext;
@@ -66,6 +67,9 @@
 
     static ReferenceQueue refQueue = Disposer.getQueue();
 
+    static ArrayList<GlyphDisposedListener> disposeListeners = new ArrayList<GlyphDisposedListener>(1);
+
+
     /* Reference objects may have their referents cleared when GC chooses.
      * During application client start-up there is typically at least one
      * GC which causes the hotspot VM to clear soft (not just weak) references
@@ -108,6 +112,8 @@
     static int topLeftXOffset;
     static int topLeftYOffset;
     static int pixelDataOffset;
+    static int cacheCellOffset;
+    static int managedOffset;
     static long invisibleGlyphPtr;
 
     /* Native method used to return information used for unsafe
@@ -129,7 +135,7 @@
 
     static {
 
-        long[] nativeInfo = new long[11];
+        long[] nativeInfo = new long[13];
         getGlyphCacheDescription(nativeInfo);
         //Can also get address size from Unsafe class :-
         //nativeAddressSize = unsafe.addressSize();
@@ -144,6 +150,9 @@
         topLeftYOffset    = (int)nativeInfo[8];
         pixelDataOffset   = (int)nativeInfo[9];
         invisibleGlyphPtr = nativeInfo[10];
+        cacheCellOffset = (int) nativeInfo[11];
+        managedOffset = (int) nativeInfo[12];
+
         if (nativeAddressSize < 4) {
             throw new InternalError("Unexpected address size for font data: " +
                                     nativeAddressSize);
@@ -195,10 +204,10 @@
 
     private static final void doDispose(FontStrikeDisposer disposer) {
         if (disposer.intGlyphImages != null) {
-            freeIntMemory(disposer.intGlyphImages,
+            freeCachedIntMemory(disposer.intGlyphImages,
                     disposer.pScalerContext);
         } else if (disposer.longGlyphImages != null) {
-            freeLongMemory(disposer.longGlyphImages,
+            freeCachedLongMemory(disposer.longGlyphImages,
                     disposer.pScalerContext);
         } else if (disposer.segIntGlyphImages != null) {
             /* NB Now making multiple JNI calls in this case.
@@ -207,7 +216,7 @@
              */
             for (int i=0; i<disposer.segIntGlyphImages.length; i++) {
                 if (disposer.segIntGlyphImages[i] != null) {
-                    freeIntMemory(disposer.segIntGlyphImages[i],
+                    freeCachedIntMemory(disposer.segIntGlyphImages[i],
                             disposer.pScalerContext);
                     /* native will only free the scaler context once */
                     disposer.pScalerContext = 0L;
@@ -218,19 +227,19 @@
              * for a strike that never was asked to rasterise a glyph.
              */
             if (disposer.pScalerContext != 0L) {
-                freeIntMemory(new int[0], disposer.pScalerContext);
+                freeCachedIntMemory(new int[0], disposer.pScalerContext);
             }
         } else if (disposer.segLongGlyphImages != null) {
             for (int i=0; i<disposer.segLongGlyphImages.length; i++) {
                 if (disposer.segLongGlyphImages[i] != null) {
-                    freeLongMemory(disposer.segLongGlyphImages[i],
+                    freeCachedLongMemory(disposer.segLongGlyphImages[i],
                             disposer.pScalerContext);
                     disposer.pScalerContext = 0L;
                     disposer.segLongGlyphImages[i] = null;
                 }
             }
             if (disposer.pScalerContext != 0L) {
-                freeLongMemory(new long[0], disposer.pScalerContext);
+                freeCachedLongMemory(new long[0], disposer.pScalerContext);
             }
         } else if (disposer.pScalerContext != 0L) {
             /* Rarely a strike may have been created that never cached
@@ -238,9 +247,9 @@
              * context.
              */
             if (longAddresses()) {
-                freeLongMemory(new long[0], disposer.pScalerContext);
+                freeCachedLongMemory(new long[0], disposer.pScalerContext);
             } else {
-                freeIntMemory(new int[0], disposer.pScalerContext);
+                freeCachedIntMemory(new int[0], disposer.pScalerContext);
             }
         }
     }
@@ -304,6 +313,68 @@
     private static native void freeIntMemory(int[] glyphPtrs, long pContext);
     private static native void freeLongMemory(long[] glyphPtrs, long pContext);
 
+    private static void freeCachedIntMemory(int[] glyphPtrs, long pContext) {
+        synchronized(disposeListeners) {
+            if (disposeListeners.size() > 0) {
+                ArrayList<Long> gids = null;
+
+                for (int i = 0; i < glyphPtrs.length; i++) {
+                    if (glyphPtrs[i] != 0 && unsafe.getByte(glyphPtrs[i] + managedOffset) == 0
+                            && unsafe.getInt(glyphPtrs[i] + cacheCellOffset) != 0) {
+
+                        if (gids == null) {
+                            gids = new ArrayList<Long>();
+                        }
+                        gids.add((long) glyphPtrs[i]);
+                    }
+                }
+
+                if (gids != null) {
+                    notifyDisposeListeners(gids);
+                }
+            }
+        }
+
+        freeIntMemory(glyphPtrs, pContext);
+    }
+
+    private static void  freeCachedLongMemory(long[] glyphPtrs, long pContext) {
+        synchronized(disposeListeners) {
+        if (disposeListeners.size() > 0)  {
+                ArrayList<Long> gids = null;
+
+                for (int i=0; i < glyphPtrs.length; i++) {
+                    if (glyphPtrs[i] != 0
+                            && unsafe.getByte(glyphPtrs[i] + managedOffset) == 0
+                            && unsafe.getInt(glyphPtrs[i] + cacheCellOffset) != 0) {
+
+                        if (gids == null) {
+                            gids = new ArrayList<Long>();
+                        }
+                        gids.add((long) glyphPtrs[i]);
+                    }
+                }
+
+                if (gids != null) {
+                    notifyDisposeListeners(gids);
+                }
+        }
+        }
+
+        freeLongMemory(glyphPtrs, pContext);
+    }
+
+    public static void addGlyphDisposedListener(GlyphDisposedListener listener) {
+        synchronized(disposeListeners) {
+            disposeListeners.add(listener);
+        }
+    }
+
+    private static void notifyDisposeListeners(ArrayList<Long> glyphs) {
+        for (GlyphDisposedListener listener : disposeListeners) {
+            listener.glyphDisposed(glyphs);
+        }
+    }
 
     public static Reference getStrikeRef(FontStrike strike) {
         return getStrikeRef(strike, cacheRefTypeWeak);
--- a/jdk/src/share/classes/sun/java2d/pipe/BufferedPaints.java	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/src/share/classes/sun/java2d/pipe/BufferedPaints.java	Fri May 28 11:37:44 2010 -0700
@@ -307,7 +307,7 @@
      * linear RGB space.  Copied directly from the
      * MultipleGradientPaintContext class.
      */
-    private static int convertSRGBtoLinearRGB(int color) {
+    public static int convertSRGBtoLinearRGB(int color) {
         float input, output;
 
         input = color / 255.0f;
--- a/jdk/src/share/classes/sun/java2d/pipe/RenderBuffer.java	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/src/share/classes/sun/java2d/pipe/RenderBuffer.java	Fri May 28 11:37:44 2010 -0700
@@ -117,6 +117,11 @@
         curAddress = baseAddress;
     }
 
+    public final RenderBuffer skip(long numBytes) {
+        curAddress += numBytes;
+        return this;
+    }
+
     /**
      * putByte() methods...
      */
--- a/jdk/src/share/classes/sun/java2d/pisces/META-INF/services/sun.java2d.pipe.RenderingEngine	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/src/share/classes/sun/java2d/pisces/META-INF/services/sun.java2d.pipe.RenderingEngine	Fri May 28 11:37:44 2010 -0700
@@ -1,2 +1,5 @@
+# Jules Rendering Engine module
+sun.java2d.jules.JulesRenderingEngine
+
 #  Pisces Rendering Engine module
-sun.java2d.pisces.PiscesRenderingEngine
+sun.java2d.pisces.PiscesRenderingEngine
\ No newline at end of file
--- a/jdk/src/share/native/sun/font/AccelGlyphCache.c	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/src/share/native/sun/font/AccelGlyphCache.c	Fri May 28 11:37:44 2010 -0700
@@ -325,6 +325,7 @@
     cellInfo->glyphInfo = glyph;
     cellInfo->nextGCI = glyph->cellInfo;
     glyph->cellInfo = cellInfo;
+    glyph->managed = MANAGED_GLYPH;
 }
 
 /**
--- a/jdk/src/share/native/sun/font/fontscalerdefs.h	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/src/share/native/sun/font/fontscalerdefs.h	Fri May 28 11:37:44 2010 -0700
@@ -84,15 +84,26 @@
 
 #define t2kScalarAverage(a, b) (((a) + (b)) / (t2kScalar)(2))
 
+  /* managed: 1 means the glyph has a hardware cached
+   * copy, and its freeing is managed by the the usual
+   * 2D disposer code.
+   * A value of 0 means its either unaccelerated (and so has no cellInfos)
+   * or we want to free this in a different way.
+   * The field uses previously unused padding, so doesn't enlarge
+   * the structure.
+   */
+#define UNMANAGED_GLYPH 0
+#define MANAGED_GLYPH   1
 typedef struct GlyphInfo {
     float        advanceX;
     float        advanceY;
     UInt16       width;
     UInt16       height;
     UInt16       rowBytes;
+    UInt8         managed;
     float        topLeftX;
     float        topLeftY;
-    struct _CacheCellInfo *cellInfo;
+    void         *cellInfo;
     UInt8        *image;
 } GlyphInfo;
 
--- a/jdk/src/share/native/sun/font/freetypeScaler.c	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/src/share/native/sun/font/freetypeScaler.c	Fri May 28 11:37:44 2010 -0700
@@ -782,6 +782,7 @@
         return ptr_to_jlong(glyphInfo);
     }
     glyphInfo->cellInfo  = NULL;
+    glyphInfo->managed   = UNMANAGED_GLYPH;
     glyphInfo->rowBytes  = width;
     glyphInfo->width     = width;
     glyphInfo->height    = height;
@@ -1130,7 +1131,7 @@
                     current_type = SEG_LINETO;
                 }
             } else if (FT_CURVE_TAG(outline->tags[i]) == FT_CURVE_TAG_CUBIC) {
-                /* Bit 1 is meaningful for ‘off’ points only.
+                /* Bit 1 is meaningful for 'off' points only.
                    If set, it indicates a third-order Bezier arc control
                    point; and a second-order control point if unset.  */
                 current_type = SEG_CUBICTO;
--- a/jdk/src/share/native/sun/font/sunFont.c	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/src/share/native/sun/font/sunFont.c	Fri May 28 11:37:44 2010 -0700
@@ -233,7 +233,8 @@
         for (i=0; i< len; i++) {
             if (ptrs[i] != 0) {
                 GlyphInfo *ginfo = (GlyphInfo *)ptrs[i];
-                if (ginfo->cellInfo != NULL) {
+                if (ginfo->cellInfo != NULL &&
+                    ginfo->managed == MANAGED_GLYPH) {
                     // invalidate this glyph's accelerated cache cell
                     AccelGlyphCache_RemoveAllCellInfos(ginfo);
                 }
@@ -264,7 +265,8 @@
         for (i=0; i< len; i++) {
             if (ptrs[i] != 0L) {
                 GlyphInfo *ginfo = (GlyphInfo *) jlong_to_ptr(ptrs[i]);
-                if (ginfo->cellInfo != NULL) {
+                if (ginfo->cellInfo != NULL &&
+                    ginfo->managed == MANAGED_GLYPH) {
                     AccelGlyphCache_RemoveAllCellInfos(ginfo);
                 }
                 free((void*)ginfo);
@@ -285,7 +287,7 @@
     GlyphInfo *info;
     size_t baseAddr;
 
-    if ((*env)->GetArrayLength(env, results) < 10) {
+    if ((*env)->GetArrayLength(env, results) < 13) {
         return;
     }
 
@@ -310,6 +312,9 @@
     nresults[8] = (size_t)&(info->topLeftY)-baseAddr;
     nresults[9] = (size_t)&(info->image)-baseAddr;
     nresults[10] = (jlong)(uintptr_t)info; /* invisible glyph */
+    nresults[11] = (size_t)&(info->cellInfo)-baseAddr;
+    nresults[12] = (size_t)&(info->managed)-baseAddr;
+
     (*env)->ReleasePrimitiveArrayCritical(env, results, nresults, 0);
 }
 
--- a/jdk/src/share/native/sun/java2d/opengl/OGLTextRenderer.c	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/src/share/native/sun/java2d/opengl/OGLTextRenderer.c	Fri May 28 11:37:44 2010 -0700
@@ -244,6 +244,7 @@
 OGLTR_AddToGlyphCache(GlyphInfo *glyph, jboolean rgbOrder)
 {
     GLenum pixelFormat;
+    CacheCellInfo *ccinfo;
 
     J2dTraceLn(J2D_TRACE_INFO, "OGLTR_AddToGlyphCache");
 
@@ -258,11 +259,12 @@
     }
 
     AccelGlyphCache_AddGlyph(glyphCache, glyph);
+    ccinfo = (CacheCellInfo *) glyph->cellInfo;
 
-    if (glyph->cellInfo != NULL) {
+    if (ccinfo != NULL) {
         // store glyph image in texture cell
         j2d_glTexSubImage2D(GL_TEXTURE_2D, 0,
-                            glyph->cellInfo->x, glyph->cellInfo->y,
+                            ccinfo->x, ccinfo->y,
                             glyph->width, glyph->height,
                             pixelFormat, GL_UNSIGNED_BYTE, glyph->image);
     }
@@ -668,7 +670,7 @@
         }
     }
 
-    cell = ginfo->cellInfo;
+    cell = (CacheCellInfo *) (ginfo->cellInfo);
     cell->timesRendered++;
 
     x1 = (jfloat)x;
@@ -871,7 +873,7 @@
         }
     }
 
-    cell = ginfo->cellInfo;
+    cell = (CacheCellInfo *) (ginfo->cellInfo);
     cell->timesRendered++;
 
     // location of the glyph in the destination's coordinate space
--- a/jdk/src/solaris/classes/sun/awt/X11GraphicsDevice.java	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11GraphicsDevice.java	Fri May 28 11:37:44 2010 -0700
@@ -39,6 +39,7 @@
 import java.util.HashMap;
 
 import sun.java2d.opengl.GLXGraphicsConfig;
+import sun.java2d.xr.XRGraphicsConfig;
 import sun.java2d.loops.SurfaceType;
 
 /**
@@ -152,6 +153,8 @@
             }
 
             boolean glxSupported = X11GraphicsEnvironment.isGLXAvailable();
+            boolean xrenderSupported = X11GraphicsEnvironment.isXRenderAvailable();
+
             boolean dbeSupported = isDBESupported();
             if (dbeSupported && doubleBufferVisuals == null) {
                 doubleBufferVisuals = new HashSet();
@@ -167,9 +170,15 @@
                     boolean doubleBuffer =
                         (dbeSupported &&
                          doubleBufferVisuals.contains(Integer.valueOf(visNum)));
-                    ret[i] = X11GraphicsConfig.getConfig(this, visNum, depth,
-                            getConfigColormap(i, screen),
-                            doubleBuffer);
+
+                    if (xrenderSupported) {
+                        ret[i] = XRGraphicsConfig.getConfig(this, visNum, depth,                                getConfigColormap(i, screen),
+                                doubleBuffer);
+                    } else {
+                       ret[i] = X11GraphicsConfig.getConfig(this, visNum, depth,
+                              getConfigColormap(i, screen),
+                              doubleBuffer);
+                    }
                 }
             }
             configs = ret;
@@ -243,9 +252,19 @@
                     doubleBuffer =
                         doubleBufferVisuals.contains(Integer.valueOf(visNum));
                 }
-                defaultConfig = X11GraphicsConfig.getConfig(this, visNum,
-                                                            depth, getConfigColormap(0, screen),
-                                                            doubleBuffer);
+
+                if (X11GraphicsEnvironment.isXRenderAvailable()) {
+                    if (X11GraphicsEnvironment.isXRenderVerbose()) {
+                        System.out.println("XRender pipeline enabled");
+                    }
+                    defaultConfig = XRGraphicsConfig.getConfig(this, visNum,
+                            depth, getConfigColormap(0, screen),
+                            doubleBuffer);
+                } else {
+                    defaultConfig = X11GraphicsConfig.getConfig(this, visNum,
+                                        depth, getConfigColormap(0, screen),
+                                        doubleBuffer);
+                }
             }
         }
     }
--- a/jdk/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java	Fri May 28 11:37:44 2010 -0700
@@ -26,6 +26,7 @@
 package sun.awt;
 
 import java.awt.GraphicsDevice;
+
 import java.awt.Point;
 import java.awt.Rectangle;
 import java.io.BufferedReader;
@@ -51,6 +52,7 @@
 import sun.java2d.SurfaceManagerFactory;
 import sun.java2d.UnixSurfaceManagerFactory;
 import sun.util.logging.PlatformLogger;
+import sun.java2d.xr.XRSurfaceData;
 
 /**
  * This is an implementation of a GraphicsEnvironment object for the
@@ -92,6 +94,18 @@
                         }
                     }
 
+                    // Now check for XRender system property
+                    boolean xRenderRequested = false;
+                    String xProp = System.getProperty("sun.java2d.xrender");
+                        if (xProp != null) {
+                        if (xProp.equals("true") || xProp.equals("t")) {
+                            xRenderRequested = true;
+                        } else if (xProp.equals("True") || xProp.equals("T")) {
+                            xRenderRequested = true;
+                            xRenderVerbose = true;
+                        }
+                    }
+
                     // initialize the X11 display connection
                     initDisplay(glxRequested);
 
@@ -104,6 +118,19 @@
                                 "pipeline (GLX 1.3 not available)");
                         }
                     }
+
+                    // only attempt to initialize Xrender if it was requested
+                    if (xRenderRequested) {
+                        xRenderAvailable = initXRender();
+                        if (xRenderVerbose && !xRenderAvailable) {
+                            System.out.println(
+                                         "Could not enable XRender pipeline");
+                        }
+                    }
+
+                    if (xRenderAvailable) {
+                        XRSurfaceData.initXRSurfaceData();
+                    }
                 }
 
                 return null;
@@ -115,6 +142,7 @@
 
     }
 
+
     private static boolean glxAvailable;
     private static boolean glxVerbose;
 
@@ -128,6 +156,18 @@
         return glxVerbose;
     }
 
+    private static boolean xRenderVerbose;
+    private static boolean xRenderAvailable;
+
+    private static native boolean initXRender();
+    public static boolean isXRenderAvailable() {
+        return xRenderAvailable;
+    }
+
+    public static boolean isXRenderVerbose() {
+        return xRenderVerbose;
+    }
+
     /**
      * Checks if Shared Memory extension can be used.
      * Returns:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/font/XRGlyphCache.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,301 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.font;
+
+import java.io.*;
+import java.util.*;
+
+import sun.awt.*;
+import sun.java2d.xr.*;
+
+/**
+ * Glyph cache used by the XRender pipeline.
+ *
+ * @author Clemens Eisserer
+ */
+
+public class XRGlyphCache implements GlyphDisposedListener {
+    XRBackend con;
+    XRCompositeManager maskBuffer;
+    HashMap<MutableInteger, XRGlyphCacheEntry> cacheMap = new HashMap<MutableInteger, XRGlyphCacheEntry>(256);
+
+    int nextID = 1;
+    MutableInteger tmp = new MutableInteger(0);
+
+    int grayGlyphSet;
+    int lcdGlyphSet;
+
+    int time = 0;
+    int cachedPixels = 0;
+    static final int MAX_CACHED_PIXELS = 100000;
+
+    ArrayList<Integer> freeGlyphIDs = new ArrayList<Integer>(255);
+
+    static final boolean batchGlyphUpload = true; // Boolean.parseBoolean(System.getProperty("sun.java2d.xrender.batchGlyphUpload"));
+
+    public XRGlyphCache(XRCompositeManager maskBuf) {
+        this.con = maskBuf.getBackend();
+        this.maskBuffer = maskBuf;
+
+        grayGlyphSet = con.XRenderCreateGlyphSet(XRUtils.PictStandardA8);
+        lcdGlyphSet = con.XRenderCreateGlyphSet(XRUtils.PictStandardARGB32);
+
+        StrikeCache.addGlyphDisposedListener(this);
+    }
+
+    public void glyphDisposed(ArrayList<Long> glyphPtrList) {
+        try {
+            SunToolkit.awtLock();
+
+            ArrayList<Integer> glyphIDList = new ArrayList<Integer>(glyphPtrList.size());
+            for (long glyphPtr : glyphPtrList) {
+                glyphIDList.add(XRGlyphCacheEntry.getGlyphID(glyphPtr));
+            }
+            freeGlyphs(glyphIDList);
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+
+    protected int getFreeGlyphID() {
+        if (freeGlyphIDs.size() > 0) {
+            int newID = freeGlyphIDs.remove(freeGlyphIDs.size() - 1);
+            ;
+            return newID;
+        }
+        return nextID++;
+    }
+
+    protected XRGlyphCacheEntry getEntryForPointer(long imgPtr) {
+        int id = XRGlyphCacheEntry.getGlyphID(imgPtr);
+
+        if (id == 0) {
+            return null;
+        }
+
+        tmp.setValue(id);
+        return cacheMap.get(tmp);
+    }
+
+    public XRGlyphCacheEntry[] cacheGlyphs(GlyphList glyphList) {
+        time++;
+
+        XRGlyphCacheEntry[] entries = new XRGlyphCacheEntry[glyphList.getNumGlyphs()];
+        long[] imgPtrs = glyphList.getImages();
+        ArrayList<XRGlyphCacheEntry> uncachedGlyphs = null;
+
+        for (int i = 0; i < glyphList.getNumGlyphs(); i++) {
+            XRGlyphCacheEntry glyph;
+
+            // Find uncached glyphs and queue them for upload
+            if ((glyph = getEntryForPointer(imgPtrs[i])) == null) {
+                glyph = new XRGlyphCacheEntry(imgPtrs[i], glyphList);
+                glyph.setGlyphID(getFreeGlyphID());
+                cacheMap.put(new MutableInteger(glyph.getGlyphID()), glyph);
+
+                if (uncachedGlyphs == null) {
+                    uncachedGlyphs = new ArrayList<XRGlyphCacheEntry>();
+                }
+                uncachedGlyphs.add(glyph);
+            }
+            glyph.setLastUsed(time);
+            entries[i] = glyph;
+        }
+
+        // Add glyphs to cache
+        if (uncachedGlyphs != null) {
+            uploadGlyphs(entries, uncachedGlyphs, glyphList, null);
+        }
+
+        return entries;
+    }
+
+    protected void uploadGlyphs(XRGlyphCacheEntry[] glyphs, ArrayList<XRGlyphCacheEntry> uncachedGlyphs, GlyphList gl, int[] glIndices) {
+        for (XRGlyphCacheEntry glyph : uncachedGlyphs) {
+            cachedPixels += glyph.getPixelCnt();
+        }
+
+        if (cachedPixels > MAX_CACHED_PIXELS) {
+            clearCache(glyphs);
+        }
+
+        boolean containsLCDGlyphs = containsLCDGlyphs(uncachedGlyphs);
+        List<XRGlyphCacheEntry>[] seperatedGlyphList = seperateGlyphTypes(uncachedGlyphs, containsLCDGlyphs);
+        List<XRGlyphCacheEntry> grayGlyphList = seperatedGlyphList[0];
+        List<XRGlyphCacheEntry> lcdGlyphList = seperatedGlyphList[1];
+
+        /*
+         * Some XServers crash when uploading multiple glyphs at once. TODO:
+         * Implement build-switch in local case for distributors who know their
+         * XServer is fixed
+         */
+        if (batchGlyphUpload) {
+            if (grayGlyphList != null && grayGlyphList.size() > 0) {
+                con.XRenderAddGlyphs(grayGlyphSet, gl, grayGlyphList, generateGlyphImageStream(grayGlyphList));
+            }
+            if (lcdGlyphList != null && lcdGlyphList.size() > 0) {
+                con.XRenderAddGlyphs(lcdGlyphSet, gl, lcdGlyphList, generateGlyphImageStream(lcdGlyphList));
+            }
+        } else {
+            ArrayList<XRGlyphCacheEntry> tmpList = new ArrayList<XRGlyphCacheEntry>(1);
+            tmpList.add(null);
+
+            for (XRGlyphCacheEntry entry : uncachedGlyphs) {
+                tmpList.set(0, entry);
+
+                if (entry.getGlyphSet() == grayGlyphSet) {
+                    con.XRenderAddGlyphs(grayGlyphSet, gl, tmpList, generateGlyphImageStream(tmpList));
+                } else {
+                    con.XRenderAddGlyphs(lcdGlyphSet, gl, tmpList, generateGlyphImageStream(tmpList));
+                }
+            }
+        }
+    }
+
+    /**
+     * Seperates lcd and grayscale glyphs queued for upload, and sets the
+     * appropriate glyphset for the cache entries.
+     */
+    protected List<XRGlyphCacheEntry>[] seperateGlyphTypes(List<XRGlyphCacheEntry> glyphList, boolean containsLCDGlyphs) {
+        ArrayList<XRGlyphCacheEntry> lcdGlyphs = null;
+        ArrayList<XRGlyphCacheEntry> grayGlyphs = null;
+
+        for (XRGlyphCacheEntry cacheEntry : glyphList) {
+            if (cacheEntry.isGrayscale(containsLCDGlyphs)) {
+                if (grayGlyphs == null) {
+                    grayGlyphs = new ArrayList<XRGlyphCacheEntry>(glyphList.size());
+                }
+                cacheEntry.setGlyphSet(grayGlyphSet);
+                grayGlyphs.add(cacheEntry);
+            } else {
+                if (lcdGlyphs == null) {
+                    lcdGlyphs = new ArrayList<XRGlyphCacheEntry>(glyphList.size());
+                }
+                cacheEntry.setGlyphSet(lcdGlyphSet);
+                lcdGlyphs.add(cacheEntry);
+            }
+        }
+
+        return new List[] { grayGlyphs, lcdGlyphs };
+    }
+
+    /**
+     * Copies the glyph-images into a continous buffer, required for uploading.
+     */
+    protected byte[] generateGlyphImageStream(List<XRGlyphCacheEntry> glyphList) {
+        boolean isLCDGlyph = glyphList.get(0).getGlyphSet() == lcdGlyphSet;
+
+        ByteArrayOutputStream stream = new ByteArrayOutputStream((isLCDGlyph ? 4 : 1) * 48 * glyphList.size());
+        for (XRGlyphCacheEntry cacheEntry : glyphList) {
+            cacheEntry.writePixelData(stream, isLCDGlyph);
+        }
+
+        return stream.toByteArray();
+    }
+
+    protected boolean containsLCDGlyphs(List<XRGlyphCacheEntry> entries) {
+        boolean containsLCDGlyphs = false;
+
+        for (XRGlyphCacheEntry entry : entries) {
+            containsLCDGlyphs = !(entry.getSourceRowBytes() == entry.getWidth());
+
+            if (containsLCDGlyphs) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    protected void clearCache(XRGlyphCacheEntry[] glyps) {
+        /*
+         * Glyph uploading is so slow anyway, we can afford some inefficiency
+         * here, as the cache should usually be quite small. TODO: Implement
+         * something not that stupid ;)
+         */
+        ArrayList<XRGlyphCacheEntry> cacheList = new ArrayList<XRGlyphCacheEntry>(cacheMap.values());
+        Collections.sort(cacheList, new Comparator<XRGlyphCacheEntry>() {
+            public int compare(XRGlyphCacheEntry e1, XRGlyphCacheEntry e2) {
+                return e2.getLastUsed() - e1.getLastUsed();
+            }
+        });
+
+        for (XRGlyphCacheEntry glyph : glyps) {
+            glyph.setPinned();
+        }
+
+        ArrayList<Integer> deleteGlyphList = new ArrayList<Integer>();
+        int pixelsToRelease = cachedPixels - MAX_CACHED_PIXELS;
+
+        for (int i = cacheList.size() - 1; i >= 0 && pixelsToRelease > 0; i--) {
+            XRGlyphCacheEntry entry = cacheList.get(i);
+
+            if (!entry.isPinned()) {
+                pixelsToRelease -= entry.getPixelCnt();
+                deleteGlyphList.add(new Integer(entry.getGlyphID()));
+            }
+        }
+
+        for (XRGlyphCacheEntry glyph : glyps) {
+            glyph.setUnpinned();
+        }
+
+        freeGlyphs(deleteGlyphList);
+    }
+
+    private void freeGlyphs(List<Integer> glyphIdList) {
+
+        freeGlyphIDs.addAll(glyphIdList);
+
+        GrowableIntArray removedLCDGlyphs = new GrowableIntArray(1, 1);
+        GrowableIntArray removedGrayscaleGlyphs = new GrowableIntArray(1, 1);
+
+        for (Integer glyphId : glyphIdList) {
+            tmp.setValue(glyphId.intValue());
+            XRGlyphCacheEntry entry = cacheMap.get(tmp);
+            cachedPixels -= entry.getPixelCnt();
+
+            int removedGlyphID = entry.getGlyphID();
+            tmp.setValue(removedGlyphID);
+            cacheMap.remove(tmp);
+
+            if (entry.getGlyphSet() == grayGlyphSet) {
+                removedGrayscaleGlyphs.addInt(removedGlyphID);
+            } else {
+                removedLCDGlyphs.addInt(removedGlyphID);
+            }
+
+            entry.setGlyphID(0);
+        }
+
+        if (removedGrayscaleGlyphs.getSize() > 0) {
+            con.XRenderFreeGlyphs(grayGlyphSet, removedGrayscaleGlyphs.getSizedArray());
+        }
+
+        if (removedLCDGlyphs.getSize() > 0) {
+            con.XRenderFreeGlyphs(lcdGlyphSet, removedLCDGlyphs.getSizedArray());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/font/XRGlyphCacheEntry.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.font;
+
+import java.io.*;
+
+/**
+ * Stores glyph-related data, used in the pure-java glyphcache.
+ *
+ * @author Clemens Eisserer
+ */
+
+public class XRGlyphCacheEntry {
+    long glyphInfoPtr;
+
+    int lastUsed;
+    boolean pinned;
+
+    int xOff;
+    int yOff;
+
+    int glyphSet;
+
+    public XRGlyphCacheEntry(long glyphInfoPtr, GlyphList gl) {
+        this.glyphInfoPtr = glyphInfoPtr;
+
+        /* TODO: Does it make sence to cache results? */
+        xOff = (int) Math.round(getXAdvance());
+        yOff = (int) Math.round(getYAdvance());
+    }
+
+    public int getXOff() {
+        return xOff;
+    }
+
+    public int getYOff() {
+        return yOff;
+    }
+
+    public void setGlyphSet(int glyphSet) {
+        this.glyphSet = glyphSet;
+    }
+
+    public int getGlyphSet() {
+        return glyphSet;
+    }
+
+    public static int getGlyphID(long glyphInfoPtr) {
+        return (int) StrikeCache.unsafe.getInt(glyphInfoPtr + StrikeCache.cacheCellOffset);
+    }
+
+    public static void setGlyphID(long glyphInfoPtr, int id) {
+        StrikeCache.unsafe.putInt(glyphInfoPtr + StrikeCache.cacheCellOffset, id);
+    }
+
+    public int getGlyphID() {
+        return getGlyphID(glyphInfoPtr);
+    }
+
+    public void setGlyphID(int id) {
+        setGlyphID(glyphInfoPtr, id);
+    }
+
+    public float getXAdvance() {
+        return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.xAdvanceOffset);
+    }
+
+    public float getYAdvance() {
+        return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.yAdvanceOffset);
+    }
+
+    public int getSourceRowBytes() {
+        return StrikeCache.unsafe.getShort(glyphInfoPtr + StrikeCache.rowBytesOffset);
+    }
+
+    public int getWidth() {
+        return StrikeCache.unsafe.getShort(glyphInfoPtr + StrikeCache.widthOffset);
+    }
+
+    public int getHeight() {
+        return StrikeCache.unsafe.getShort(glyphInfoPtr + StrikeCache.heightOffset);
+    }
+
+    public void writePixelData(ByteArrayOutputStream os, boolean uploadAsLCD) {
+        long pixelDataAddress;
+        if (StrikeCache.nativeAddressSize == 4) {
+            pixelDataAddress = 0xffffffff & StrikeCache.unsafe.getInt(glyphInfoPtr + StrikeCache.pixelDataOffset);
+        } else {
+            pixelDataAddress = StrikeCache.unsafe.getLong(glyphInfoPtr + StrikeCache.pixelDataOffset);
+        }
+        if (pixelDataAddress == 0L) {
+            return;
+        }
+
+        int width = getWidth();
+        int height = getHeight();
+        int rowBytes = getSourceRowBytes();
+        int paddedWidth = getPaddedWidth(uploadAsLCD);
+
+        if (!uploadAsLCD) {
+            for (int line = 0; line < height; line++) {
+                for(int x = 0; x < paddedWidth; x++) {
+                    if(x < width) {
+                        os.write(StrikeCache.unsafe.getByte(pixelDataAddress + (line * rowBytes + x)));
+                    }else {
+                         /*pad to multiple of 4 bytes per line*/
+                         os.write(0);
+                    }
+                }
+            }
+        } else {
+            for (int line = 0; line < height; line++) {
+                int rowStart = line * rowBytes;
+                int rowBytesWidth = width * 3;
+                int srcpix = 0;
+                while (srcpix < rowBytesWidth) {
+                    os.write(StrikeCache.unsafe.getByte
+                          (pixelDataAddress + (rowStart + srcpix + 2)));
+                    os.write(StrikeCache.unsafe.getByte
+                          (pixelDataAddress + (rowStart + srcpix + 1)));
+                    os.write(StrikeCache.unsafe.getByte
+                          (pixelDataAddress + (rowStart + srcpix + 0)));
+                    os.write(255);
+                    srcpix += 3;
+                }
+            }
+        }
+    }
+
+    public float getTopLeftXOffset() {
+        return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.topLeftXOffset);
+    }
+
+    public float getTopLeftYOffset() {
+        return StrikeCache.unsafe.getFloat(glyphInfoPtr + StrikeCache.topLeftYOffset);
+    }
+
+    public long getGlyphInfoPtr() {
+        return glyphInfoPtr;
+    }
+
+    public boolean isGrayscale(boolean listContainsLCDGlyphs) {
+        return getSourceRowBytes() == getWidth() && !(getWidth() == 0 && getHeight() == 0 && listContainsLCDGlyphs);
+    }
+
+    public int getPaddedWidth(boolean listContainsLCDGlyphs) {
+        int width = getWidth();
+        return isGrayscale(listContainsLCDGlyphs) ? (int) Math.ceil(width / 4.0) * 4 : width;
+    }
+
+    public int getDestinationRowBytes(boolean listContainsLCDGlyphs) {
+        boolean grayscale = isGrayscale(listContainsLCDGlyphs);
+        return grayscale ? getPaddedWidth(grayscale) : getWidth() * 4;
+    }
+
+    public int getGlyphDataLenth(boolean listContainsLCDGlyphs) {
+        return getDestinationRowBytes(listContainsLCDGlyphs) * getHeight();
+    }
+
+    public void setPinned() {
+        pinned = true;
+    }
+
+    public void setUnpinned() {
+        pinned = false;
+    }
+
+    public int getLastUsed() {
+        return lastUsed;
+    }
+
+    public void setLastUsed(int lastUsed) {
+        this.lastUsed = lastUsed;
+    }
+
+    public int getPixelCnt() {
+        return getWidth() * getHeight();
+    }
+
+    public boolean isPinned() {
+        return pinned;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/font/XRTextRenderer.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.font;
+
+import sun.awt.*;
+import sun.java2d.SunGraphics2D;
+import sun.java2d.pipe.GlyphListPipe;
+import sun.java2d.xr.*;
+
+/**
+ * A delegate pipe of SG2D for drawing any text to a XRender surface
+ *
+ * @author Clemens Eisserer
+ */
+public class XRTextRenderer extends GlyphListPipe {
+
+    XRGlyphCache glyphCache;
+    XRCompositeManager maskBuffer;
+    XRBackend backend;
+
+    GrowableEltArray eltList;
+
+    public XRTextRenderer(XRCompositeManager buffer) {
+        glyphCache = new XRGlyphCache(buffer);
+        maskBuffer = buffer;
+        backend = buffer.getBackend();
+        eltList = new GrowableEltArray(64);
+    }
+
+    protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) {
+        if (gl.getNumGlyphs() == 0) {
+            return;
+        }
+
+        try {
+            SunToolkit.awtLock();
+
+            XRSurfaceData x11sd = (XRSurfaceData) sg2d.surfaceData;
+            x11sd.validateAsDestination(null, sg2d.getCompClip());
+            x11sd.maskBuffer.validateCompositeState(sg2d.composite, sg2d.transform, sg2d.paint, sg2d);
+
+            float advX = gl.getX();
+            float advY = gl.getY();
+            int oldPosX = 0, oldPosY = 0;
+
+            if (gl.isSubPixPos()) {
+                advX += 0.1666667f;
+                advY += 0.1666667f;
+            } else {
+                advX += 0.5f;
+                advY += 0.5f;
+            }
+
+            XRGlyphCacheEntry[] cachedGlyphs = glyphCache.cacheGlyphs(gl);
+            boolean containsLCDGlyphs = false;
+            int activeGlyphSet = cachedGlyphs[0].getGlyphSet();
+
+            int eltIndex = -1;
+            gl.getBounds();
+            float[] positions = gl.getPositions();
+            for (int i = 0; i < gl.getNumGlyphs(); i++) {
+                gl.setGlyphIndex(i);
+                XRGlyphCacheEntry cacheEntry = cachedGlyphs[i];
+
+                eltList.getGlyphs().addInt(cacheEntry.getGlyphID());
+                int glyphSet = cacheEntry.getGlyphSet();
+
+                containsLCDGlyphs |= (glyphSet == glyphCache.lcdGlyphSet);
+
+                int posX = 0, posY = 0;
+                if (gl.usePositions()
+                        || (cacheEntry.getXAdvance() != ((float) cacheEntry.getXOff()) || cacheEntry.getYAdvance() != ((float) cacheEntry.getYOff()))
+                        || eltIndex < 0 || glyphSet != activeGlyphSet) {
+
+                    eltIndex = eltList.getNextIndex();
+                    eltList.setCharCnt(eltIndex, 1);
+                    activeGlyphSet = glyphSet;
+                    eltList.setGlyphSet(eltIndex, glyphSet);
+
+                    if (gl.usePositions()) {
+                        // /*In this case advX only stores rounding errors*/
+                        float x = positions[i * 2] + advX;
+                        float y = positions[i * 2 + 1] + advY;
+                        posX = (int) Math.floor(x);
+                        posY = (int) Math.floor(y);
+                        advX -= cacheEntry.getXOff();
+                        advY -= cacheEntry.getYOff();
+                    } else {
+                        /*
+                         * Calculate next glyph's position in the case of
+                         * relative positioning. In XRender we can only position
+                         * glyphs using integer coordinates, therefor we sum all
+                         * the advances up as float, and convert them to integer
+                         * later. This way rounding-error can be corrected, and
+                         * is required to be consistent with the software loops.
+                         */
+                        posX = (int) Math.floor(advX);
+                        posY = (int) Math.floor(advY);
+
+                        // Advance of ELT = difference between stored
+                        // relative
+                        // positioning information and required float.
+                        advX += (cacheEntry.getXAdvance() - cacheEntry.getXOff());
+                        advY += (cacheEntry.getYAdvance() - cacheEntry.getYOff());
+                    }
+                    /*
+                     * Offset of the current glyph is the difference to the last
+                     * glyph and this one
+                     */
+                    eltList.setXOff(eltIndex, (posX - oldPosX));
+                    eltList.setYOff(eltIndex, (posY - oldPosY));
+
+                    oldPosX = posX;
+                    oldPosY = posY;
+
+                } else {
+                    eltList.setCharCnt(eltIndex, eltList.getCharCnt(eltIndex) + 1);
+                }
+            }
+
+            int maskFormat = containsLCDGlyphs ? XRUtils.PictStandardARGB32 : XRUtils.PictStandardA8;
+            maskBuffer.compositeText(x11sd.picture, 0, maskFormat, eltList);
+
+            eltList.clear();
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+}
--- a/jdk/src/solaris/classes/sun/java2d/UnixSurfaceManagerFactory.java	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/src/solaris/classes/sun/java2d/UnixSurfaceManagerFactory.java	Fri May 28 11:37:44 2010 -0700
@@ -33,6 +33,7 @@
 import sun.java2d.opengl.GLXGraphicsConfig;
 import sun.java2d.opengl.GLXVolatileSurfaceManager;
 import sun.java2d.x11.X11VolatileSurfaceManager;
+import sun.java2d.xr.*;
 
 /**
  * The SurfaceManagerFactory that creates VolatileSurfaceManager
@@ -54,9 +55,12 @@
                                                         Object context)
     {
         GraphicsConfiguration gc = vImg.getGraphicsConfig();
+
         if (gc instanceof GLXGraphicsConfig) {
             return new GLXVolatileSurfaceManager(vImg, context);
-        } else {
+        } else if(gc instanceof XRGraphicsConfig) {
+            return new XRVolatileSurfaceManager(vImg, context);
+        }else {
             return new X11VolatileSurfaceManager(vImg, context);
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/jules/IdleTileCache.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.jules;
+
+import java.util.*;
+
+public class IdleTileCache {
+    final static int IDLE_TILE_SYNC_GRANULARITY = 16;
+    final static ArrayList<JulesTile> idleBuffers = new ArrayList<JulesTile>();
+
+    ArrayList<JulesTile> idleTileWorkerCacheList = new ArrayList<JulesTile>();
+    ArrayList<JulesTile> idleTileConsumerCacheList =
+              new ArrayList<JulesTile>(IDLE_TILE_SYNC_GRANULARITY);
+
+    /**
+     * Return a cached Tile, if possible from cache.
+     * Allowed caller: Rasterizer/Producer-Thread
+     *
+     * @param: maxCache - Specify the maximum amount of tiles needed
+     */
+    public JulesTile getIdleTileWorker(int maxCache) {
+        /* Try to fetch idle tiles from the global cache list */
+        if (idleTileWorkerCacheList.size() == 0) {
+            idleTileWorkerCacheList.ensureCapacity(maxCache);
+
+            synchronized (idleBuffers) {
+                for (int i = 0; i < maxCache && idleBuffers.size() > 0; i++) {
+                    idleTileWorkerCacheList.add(
+                            idleBuffers.remove(idleBuffers.size() - 1));
+                }
+            }
+        }
+
+        if (idleTileWorkerCacheList.size() > 0) {
+            return idleTileWorkerCacheList.remove(idleTileWorkerCacheList.size() - 1);
+        }
+
+        return new JulesTile();
+    }
+
+    /**
+     * Release tile and allow it to be re-used by another thread. Allowed
+     *  Allowed caller: MaskBlit/Consumer-Thread
+     */
+    public void releaseTile(JulesTile tile) {
+        if (tile != null && tile.hasBuffer()) {
+            idleTileConsumerCacheList.add(tile);
+
+            if (idleTileConsumerCacheList.size() > IDLE_TILE_SYNC_GRANULARITY) {
+                synchronized (idleBuffers) {
+                    idleBuffers.addAll(idleTileConsumerCacheList);
+                }
+                idleTileConsumerCacheList.clear();
+            }
+        }
+    }
+
+    /**
+     * Releases thread-local tiles cached for use by the rasterizing thread.
+     * Allowed caller: Rasterizer/Producer-Thread
+     */
+    public void disposeRasterizerResources() {
+        releaseTiles(idleTileWorkerCacheList);
+    }
+
+    /**
+     * Releases thread-local tiles cached for performance reasons. Allowed
+     * Allowed caller: MaskBlit/Consumer-Thread
+     */
+    public void disposeConsumerResources() {
+        releaseTiles(idleTileConsumerCacheList);
+    }
+
+    /**
+     * Release a list of tiles and allow it to be re-used by another thread.
+     * Thread safe.
+     */
+    public void releaseTiles(List<JulesTile> tileList) {
+        if (tileList.size() > 0) {
+            synchronized (idleBuffers) {
+                idleBuffers.addAll(tileList);
+            }
+            tileList.clear();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/jules/JulesAATileGenerator.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,349 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.jules;
+
+import java.awt.*;
+import java.awt.geom.*;
+import java.util.concurrent.*;
+import sun.java2d.pipe.*;
+import sun.java2d.xr.*;
+
+public class JulesAATileGenerator implements AATileGenerator {
+    /* Threading stuff */
+    final static ExecutorService rasterThreadPool =
+                                          Executors.newCachedThreadPool();
+    final static int CPU_CNT = Runtime.getRuntime().availableProcessors();
+
+    final static boolean ENABLE_THREADING = false;
+    final static int THREAD_MIN = 16;
+    final static int THREAD_BEGIN = 16;
+
+    IdleTileCache tileCache;
+    TileWorker worker;
+    boolean threaded = false;
+    int rasterTileCnt;
+
+    /* Tiling */
+    final static int TILE_SIZE = 32;
+    final static int TILE_SIZE_FP = 32 << 16;
+    int left, right, top, bottom, width, height;
+    int leftFP, topFP;
+    int tileCnt, tilesX, tilesY;
+    int currTilePos = 0;
+    TrapezoidList traps;
+    TileTrapContainer[] tiledTrapArray;
+    JulesTile mainTile;
+
+    public JulesAATileGenerator(Shape s, AffineTransform at, Region clip,
+                                BasicStroke bs, boolean thin,
+                                boolean normalize, int[] bbox) {
+        JulesPathBuf buf = new JulesPathBuf();
+
+        if (bs == null) {
+            traps = buf.tesselateFill(s, at, clip);
+        } else {
+            traps = buf.tesselateStroke(s, bs, thin, false, true, at, clip);
+        }
+
+        calculateArea(bbox);
+        bucketSortTraps();
+        calculateTypicalAlpha();
+
+        threaded = ENABLE_THREADING &&
+                   rasterTileCnt >= THREAD_MIN && CPU_CNT >= 2;
+        if (threaded) {
+            tileCache = new IdleTileCache();
+            worker = new TileWorker(this, THREAD_BEGIN, tileCache);
+            rasterThreadPool.execute(worker);
+        }
+
+        mainTile = new JulesTile();
+    }
+
+    private static native long
+        rasterizeTrapezoidsNative(long pixmanImagePtr, int[] traps,
+                                  int[] trapPos, int trapCnt,
+                                  byte[] buffer, int xOff, int yOff);
+
+    private static native void freePixmanImgPtr(long pixmanImgPtr);
+
+    private void calculateArea(int[] bbox) {
+        tilesX = 0;
+        tilesY = 0;
+        tileCnt = 0;
+        bbox[0] = 0;
+        bbox[1] = 0;
+        bbox[2] = 0;
+        bbox[3] = 0;
+
+        if (traps.getSize() > 0) {
+            left = traps.getLeft();
+            right = traps.getRight();
+            top = traps.getTop();
+            bottom = traps.getBottom();
+            leftFP = left << 16;
+            topFP = top << 16;
+
+            bbox[0] = left;
+            bbox[1] = top;
+            bbox[2] = right;
+            bbox[3] = bottom;
+
+            width = right - left;
+            height = bottom - top;
+
+            if (width > 0 && height > 0) {
+                tilesX = (int) Math.ceil(((double) width) / TILE_SIZE);
+                tilesY = (int) Math.ceil(((double) height) / TILE_SIZE);
+                tileCnt = tilesY * tilesX;
+                tiledTrapArray = new TileTrapContainer[tileCnt];
+            } else {
+                // If there is no area touched by the traps, don't
+                // render them.
+                traps.setSize(0);
+            }
+        }
+    }
+
+
+    private void bucketSortTraps() {
+
+        for (int i = 0; i < traps.getSize(); i++) {
+            int top = traps.getTop(i) - XRUtils.XDoubleToFixed(this.top);
+            int bottom = traps.getBottom(i) - topFP;
+            int p1xLeft = traps.getP1XLeft(i) - leftFP;
+            int p2xLeft = traps.getP2XLeft(i) - leftFP;
+            int p1xRight = traps.getP1XRight(i) - leftFP;
+            int p2xRight = traps.getP2XRight(i) - leftFP;
+
+            int minLeft = Math.min(p1xLeft, p2xLeft);
+            int maxRight = Math.max(p1xRight, p2xRight);
+
+            maxRight = maxRight > 0 ? maxRight - 1 : maxRight;
+            bottom = bottom > 0 ? bottom - 1 : bottom;
+
+            int startTileY = top / TILE_SIZE_FP;
+            int endTileY = bottom / TILE_SIZE_FP;
+            int startTileX = minLeft / TILE_SIZE_FP;
+            int endTileX = maxRight / TILE_SIZE_FP;
+
+            for (int n = startTileY; n <= endTileY; n++) {
+
+                for (int m = startTileX; m <= endTileX; m++) {
+                    int trapArrayPos = n * tilesX + m;
+                    TileTrapContainer trapTileList = tiledTrapArray[trapArrayPos];
+                    if (trapTileList == null) {
+                        trapTileList = new TileTrapContainer(new GrowableIntArray(1, 16));
+                        tiledTrapArray[trapArrayPos] = trapTileList;
+                    }
+
+                    trapTileList.getTraps().addInt(i);
+                }
+            }
+        }
+    }
+
+    public void getAlpha(byte[] tileBuffer, int offset, int rowstride) {
+        JulesTile tile = null;
+
+        if (threaded) {
+            tile = worker.getPreRasterizedTile(currTilePos);
+        }
+
+        if (tile != null) {
+            System.arraycopy(tile.getImgBuffer(), 0,
+                             tileBuffer, 0, tileBuffer.length);
+            tileCache.releaseTile(tile);
+        } else {
+            mainTile.setImgBuffer(tileBuffer);
+            rasterizeTile(currTilePos, mainTile);
+        }
+
+        nextTile();
+    }
+
+    public void calculateTypicalAlpha() {
+        rasterTileCnt = 0;
+
+        for (int index = 0; index < tileCnt; index++) {
+
+            TileTrapContainer trapCont = tiledTrapArray[index];
+            if (trapCont != null) {
+                GrowableIntArray trapList = trapCont.getTraps();
+
+                int tileAlpha = 127;
+                if (trapList == null || trapList.getSize() == 0) {
+                    tileAlpha = 0;
+                } else if (doTrapsCoverTile(trapList, index)) {
+                    tileAlpha = 0xff;
+                }
+
+                if (tileAlpha == 127 || tileAlpha == 0xff) {
+                    rasterTileCnt++;
+                }
+
+                trapCont.setTileAlpha(tileAlpha);
+            }
+        }
+    }
+
+    /*
+     * Optimization for large fills. Foutunatly cairo does generate an y-sorted
+     * list of trapezoids. This makes it quite simple to check wether a tile is
+     * fully covered by traps by: - Checking wether the tile is fully covered by
+     * traps vertically (trap 2 starts where trap 1 ended) - Checking wether all
+     * traps cover the tile horizontally This also works, when a single tile
+     * coveres the whole tile.
+     */
+    protected boolean doTrapsCoverTile(GrowableIntArray trapList, int tileIndex) {
+
+        // Don't bother optimizing tiles with lots of traps, usually it won't
+        // succeed anyway.
+        if (trapList.getSize() > TILE_SIZE) {
+            return false;
+        }
+
+        int tileStartX = getXPos(tileIndex) * TILE_SIZE_FP + leftFP;
+        int tileStartY = getYPos(tileIndex) * TILE_SIZE_FP + topFP;
+        int tileEndX = tileStartX + TILE_SIZE_FP;
+        int tileEndY = tileStartY + TILE_SIZE_FP;
+
+        // Check wether first tile covers the beginning of the tile vertically
+        int firstTop = traps.getTop(trapList.getInt(0));
+        int firstBottom = traps.getBottom(trapList.getInt(0));
+        if (firstTop > tileStartY || firstBottom < tileStartY) {
+            return false;
+        }
+
+        // Initialize lastBottom with top, in order to pass the checks for the
+        // first iteration
+        int lastBottom = firstTop;
+
+        for (int i = 0; i < trapList.getSize(); i++) {
+            int trapPos = trapList.getInt(i);
+            if (traps.getP1XLeft(trapPos) > tileStartX ||
+                traps.getP2XLeft(trapPos) > tileStartX ||
+                traps.getP1XRight(trapPos) < tileEndX  ||
+                traps.getP2XRight(trapPos) < tileEndX  ||
+                 traps.getTop(trapPos) != lastBottom)
+            {
+                return false;
+            }
+            lastBottom = traps.getBottom(trapPos);
+        }
+
+        // When the last trap covered the tileEnd vertically, the tile is fully
+        // covered
+        return lastBottom >= tileEndY;
+    }
+
+    public int getTypicalAlpha() {
+        if (tiledTrapArray[currTilePos] == null) {
+            return 0;
+        } else {
+            return tiledTrapArray[currTilePos].getTileAlpha();
+        }
+    }
+
+    public void dispose() {
+        freePixmanImgPtr(mainTile.getPixmanImgPtr());
+
+        if (threaded) {
+            tileCache.disposeConsumerResources();
+            worker.disposeConsumerResources();
+        }
+    }
+
+    protected JulesTile rasterizeTile(int tileIndex, JulesTile tile) {
+        int tileOffsetX = left + getXPos(tileIndex) * TILE_SIZE;
+        int tileOffsetY = top + getYPos(tileIndex) * TILE_SIZE;
+        TileTrapContainer trapCont = tiledTrapArray[tileIndex];
+        GrowableIntArray trapList = trapCont.getTraps();
+
+        if (trapCont.getTileAlpha() == 127) {
+            long pixmanImgPtr =
+                 rasterizeTrapezoidsNative(tile.getPixmanImgPtr(),
+                                           traps.getTrapArray(),
+                                           trapList.getArray(),
+                                           trapList.getSize(),
+                                           tile.getImgBuffer(),
+                                           tileOffsetX, tileOffsetY);
+            tile.setPixmanImgPtr(pixmanImgPtr);
+        }
+
+        tile.setTilePos(tileIndex);
+        return tile;
+    }
+
+    protected int getXPos(int arrayPos) {
+        return arrayPos % tilesX;
+    }
+
+    protected int getYPos(int arrayPos) {
+        return arrayPos / tilesX;
+    }
+
+    public void nextTile() {
+        currTilePos++;
+    }
+
+    public int getTileHeight() {
+        return TILE_SIZE;
+    }
+
+    public int getTileWidth() {
+        return TILE_SIZE;
+    }
+
+    public int getTileCount() {
+        return tileCnt;
+    }
+
+    public TileTrapContainer getTrapContainer(int index) {
+        return tiledTrapArray[index];
+    }
+}
+
+class TileTrapContainer {
+    int tileAlpha;
+    GrowableIntArray traps;
+
+    public TileTrapContainer(GrowableIntArray traps) {
+        this.traps = traps;
+    }
+
+    public void setTileAlpha(int tileAlpha) {
+        this.tileAlpha = tileAlpha;
+    }
+
+    public int getTileAlpha() {
+        return tileAlpha;
+    }
+
+    public GrowableIntArray getTraps() {
+        return traps;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/jules/JulesPathBuf.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.jules;
+
+import java.awt.*;
+import java.awt.geom.*;
+import sun.awt.X11GraphicsEnvironment;
+import sun.java2d.pipe.*;
+import sun.java2d.xr.*;
+
+public class JulesPathBuf {
+    static final double[] emptyDash = new double[0];
+
+    private static final byte CAIRO_PATH_OP_MOVE_TO = 0;
+    private static final byte CAIRO_PATH_OP_LINE_TO = 1;
+    private static final byte CAIRO_PATH_OP_CURVE_TO = 2;
+    private static final byte CAIRO_PATH_OP_CLOSE_PATH = 3;
+
+    private static final int  CAIRO_FILL_RULE_WINDING = 0;
+    private static final int CAIRO_FILL_RULE_EVEN_ODD = 1;
+
+    GrowablePointArray points = new GrowablePointArray(128);
+    GrowableByteArray ops = new GrowableByteArray(1, 128);
+    int[] xTrapArray = new int[512];
+
+    private static final boolean isCairoAvailable;
+
+    static {
+        isCairoAvailable =
+           java.security.AccessController.doPrivileged(
+                          new java.security.PrivilegedAction<Boolean>() {
+            public Boolean run() {
+                boolean loadSuccess = false;
+                if (X11GraphicsEnvironment.isXRenderAvailable()) {
+                    try {
+                        System.loadLibrary("jules");
+                        loadSuccess = true;
+                        if (X11GraphicsEnvironment.isXRenderVerbose()) {
+                            System.out.println(
+                                       "Xrender: INFO: Jules library loaded");
+                        }
+                    } catch (UnsatisfiedLinkError ex) {
+                        loadSuccess = false;
+                        if (X11GraphicsEnvironment.isXRenderVerbose()) {
+                            System.out.println(
+                                "Xrender: INFO: Jules library not installed.");
+                        }
+                    }
+                }
+                return Boolean.valueOf(loadSuccess);
+            }
+        });
+    }
+
+    public static boolean isCairoAvailable() {
+        return isCairoAvailable;
+    }
+
+    public TrapezoidList tesselateFill(Shape s, AffineTransform at, Region clip) {
+        int windingRule = convertPathData(s, at);
+        xTrapArray[0] = 0;
+
+        xTrapArray = tesselateFillNative(points.getArray(), ops.getArray(),
+                                         points.getSize(), ops.getSize(),
+                                         xTrapArray, xTrapArray.length,
+                                         getCairoWindingRule(windingRule),
+                                         clip.getLoX(), clip.getLoY(),
+                                         clip.getHiX(), clip.getHiY());
+
+        return new TrapezoidList(xTrapArray);
+    }
+
+    public TrapezoidList tesselateStroke(Shape s, BasicStroke bs, boolean thin,
+                                         boolean adjust, boolean antialias,
+                                         AffineTransform at, Region clip) {
+
+        float lw;
+        if (thin) {
+            if (antialias) {
+                lw = 0.5f;
+            } else {
+                lw = 1.0f;
+            }
+        } else {
+            lw = bs.getLineWidth();
+        }
+
+        convertPathData(s, at);
+
+        double[] dashArray = floatToDoubleArray(bs.getDashArray());
+        xTrapArray[0] = 0;
+
+        xTrapArray =
+             tesselateStrokeNative(points.getArray(), ops.getArray(),
+                                   points.getSize(), ops.getSize(),
+                                   xTrapArray, xTrapArray.length, lw,
+                                   bs.getEndCap(), bs.getLineJoin(),
+                                   bs.getMiterLimit(), dashArray,
+                                   dashArray.length, bs.getDashPhase(),
+                                   1, 0, 0, 0, 1, 0,
+                                   clip.getLoX(), clip.getLoY(),
+                                   clip.getHiX(), clip.getHiY());
+
+        return new TrapezoidList(xTrapArray);
+    }
+
+    protected double[] floatToDoubleArray(float[] dashArrayFloat) {
+        double[] dashArrayDouble = emptyDash;
+        if (dashArrayFloat != null) {
+            dashArrayDouble = new double[dashArrayFloat.length];
+
+            for (int i = 0; i < dashArrayFloat.length; i++) {
+                dashArrayDouble[i] = dashArrayFloat[i];
+            }
+        }
+
+        return dashArrayDouble;
+    }
+
+    protected int convertPathData(Shape s, AffineTransform at) {
+        PathIterator pi = s.getPathIterator(at);
+
+        double[] coords = new double[6];
+        double currX = 0;
+        double currY = 0;
+
+        while (!pi.isDone()) {
+            int curOp = pi.currentSegment(coords);
+
+            int pointIndex;
+            switch (curOp) {
+
+            case PathIterator.SEG_MOVETO:
+                ops.addByte(CAIRO_PATH_OP_MOVE_TO);
+                pointIndex = points.getNextIndex();
+                points.setX(pointIndex, DoubleToCairoFixed(coords[0]));
+                points.setY(pointIndex, DoubleToCairoFixed(coords[1]));
+                currX = coords[0];
+                currY = coords[1];
+                break;
+
+            case PathIterator.SEG_LINETO:
+                ops.addByte(CAIRO_PATH_OP_LINE_TO);
+                pointIndex = points.getNextIndex();
+                points.setX(pointIndex, DoubleToCairoFixed(coords[0]));
+                points.setY(pointIndex, DoubleToCairoFixed(coords[1]));
+                currX = coords[0];
+                currY = coords[1];
+                break;
+
+                /**
+                 *    q0 = p0
+                 *    q1 = (p0+2*p1)/3
+                 *    q2 = (p2+2*p1)/3
+                 *    q3 = p2
+                 */
+            case PathIterator.SEG_QUADTO:
+                double x1 = coords[0];
+                double y1 = coords[1];
+                double x2, y2;
+                double x3 = coords[2];
+                double y3 = coords[3];
+
+                x2 = x1 + (x3 - x1) / 3;
+                y2 = y1 + (y3 - y1) / 3;
+                x1 = currX + 2 * (x1 - currX) / 3;
+                y1 =currY + 2 * (y1 - currY) / 3;
+
+                ops.addByte(CAIRO_PATH_OP_CURVE_TO);
+                pointIndex = points.getNextIndex();
+                points.setX(pointIndex, DoubleToCairoFixed(x1));
+                points.setY(pointIndex, DoubleToCairoFixed(y1));
+                pointIndex = points.getNextIndex();
+                points.setX(pointIndex, DoubleToCairoFixed(x2));
+                points.setY(pointIndex, DoubleToCairoFixed(y2));
+                pointIndex = points.getNextIndex();
+                points.setX(pointIndex, DoubleToCairoFixed(x3));
+                points.setY(pointIndex, DoubleToCairoFixed(y3));
+                currX = x3;
+                currY = y3;
+                break;
+
+            case PathIterator.SEG_CUBICTO:
+                ops.addByte(CAIRO_PATH_OP_CURVE_TO);
+                pointIndex = points.getNextIndex();
+                points.setX(pointIndex, DoubleToCairoFixed(coords[0]));
+                points.setY(pointIndex, DoubleToCairoFixed(coords[1]));
+                pointIndex = points.getNextIndex();
+                points.setX(pointIndex, DoubleToCairoFixed(coords[2]));
+                points.setY(pointIndex, DoubleToCairoFixed(coords[3]));
+                pointIndex = points.getNextIndex();
+                points.setX(pointIndex, DoubleToCairoFixed(coords[4]));
+                points.setY(pointIndex, DoubleToCairoFixed(coords[5]));
+                currX = coords[4];
+                currY = coords[5];
+                break;
+
+            case PathIterator.SEG_CLOSE:
+                ops.addByte(CAIRO_PATH_OP_CLOSE_PATH);
+                break;
+            }
+
+            pi.next();
+        }
+
+        return pi.getWindingRule();
+    }
+
+    private static native int[]
+         tesselateStrokeNative(int[] pointArray, byte[] ops,
+                               int pointCnt, int opCnt,
+                               int[] xTrapArray, int xTrapArrayLength,
+                               double lineWidth, int lineCap, int lineJoin,
+                               double miterLimit, double[] dashArray,
+                               int dashCnt, double offset,
+                               double m00, double m01, double m02,
+                               double m10, double m11, double m12,
+                               int clipLowX, int clipLowY,
+                               int clipWidth, int clipHeight);
+
+    private static native int[]
+        tesselateFillNative(int[] pointArray, byte[] ops, int pointCnt,
+                            int opCnt, int[] xTrapArray, int xTrapArrayLength,
+                            int windingRule, int clipLowX, int clipLowY,                                    int clipWidth, int clipHeight);
+
+    public void clear() {
+        points.clear();
+        ops.clear();
+        xTrapArray[0] = 0;
+    }
+
+    private static int DoubleToCairoFixed(double dbl) {
+        return (int) (dbl * 256);
+    }
+
+    private static int getCairoWindingRule(int j2dWindingRule) {
+        switch(j2dWindingRule) {
+        case PathIterator.WIND_EVEN_ODD:
+            return CAIRO_FILL_RULE_EVEN_ODD;
+
+        case PathIterator.WIND_NON_ZERO:
+            return CAIRO_FILL_RULE_WINDING;
+
+            default:
+                throw new IllegalArgumentException("Illegal Java2D winding rule specified");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/jules/JulesRenderingEngine.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.jules;
+
+import java.awt.*;
+
+import java.awt.geom.*;
+import sun.java2d.pipe.*;
+import sun.java2d.pisces.*;
+
+public class JulesRenderingEngine extends PiscesRenderingEngine {
+
+    @Override
+    public AATileGenerator
+         getAATileGenerator(Shape s, AffineTransform at, Region clip,
+                            BasicStroke bs, boolean thin,
+                            boolean normalize, int[] bbox) {
+
+        if (JulesPathBuf.isCairoAvailable()) {
+            return new JulesAATileGenerator(s, at, clip, bs, thin,
+                                            normalize, bbox);
+        } else {
+            return super.getAATileGenerator(s, at, clip, bs, thin,
+                                            normalize, bbox);
+        }
+    }
+
+    public float getMinimumAAPenSize() {
+        return 0.5f;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/jules/JulesShapePipe.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.jules;
+
+import java.awt.*;
+import sun.awt.*;
+import sun.java2d.*;
+import sun.java2d.pipe.*;
+import sun.java2d.xr.*;
+
+public class JulesShapePipe implements ShapeDrawPipe {
+
+    XRCompositeManager compMan;
+    JulesPathBuf buf = new JulesPathBuf();
+
+    public JulesShapePipe(XRCompositeManager compMan) {
+        this.compMan = compMan;
+    }
+
+    /**
+     * Common validate method, used by all XRRender functions to validate the
+     * destination context.
+     */
+    private final void validateSurface(SunGraphics2D sg2d) {
+        XRSurfaceData xrsd = (XRSurfaceData) sg2d.surfaceData;
+        xrsd.validateAsDestination(sg2d, sg2d.getCompClip());
+        xrsd.maskBuffer.validateCompositeState(sg2d.composite, sg2d.transform,
+                                               sg2d.paint, sg2d);
+    }
+
+    public void draw(SunGraphics2D sg2d, Shape s) {
+        try {
+            SunToolkit.awtLock();
+            validateSurface(sg2d);
+            XRSurfaceData xrsd = (XRSurfaceData) sg2d.surfaceData;
+
+            BasicStroke bs;
+
+            if (sg2d.stroke instanceof BasicStroke) {
+                bs = (BasicStroke) sg2d.stroke;
+            } else { //TODO: What happens in the case of a !BasicStroke??
+                s = sg2d.stroke.createStrokedShape(s);
+                bs = null;
+            }
+
+            boolean adjust =
+                (bs != null && sg2d.strokeHint != SunHints.INTVAL_STROKE_PURE);
+            boolean thin = (sg2d.strokeState <= SunGraphics2D.STROKE_THINDASHED);
+
+            TrapezoidList traps =
+                 buf.tesselateStroke(s, bs, thin, adjust, true,
+                                     sg2d.transform, sg2d.getCompClip());
+            compMan.XRCompositeTraps(xrsd.picture,
+                                     sg2d.transX, sg2d.transY, traps);
+
+            buf.clear();
+
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+
+    public void fill(SunGraphics2D sg2d, Shape s) {
+        try {
+            SunToolkit.awtLock();
+            validateSurface(sg2d);
+
+            XRSurfaceData xrsd = (XRSurfaceData) sg2d.surfaceData;
+
+            TrapezoidList traps = buf.tesselateFill(s, sg2d.transform,
+                                                    sg2d.getCompClip());
+            compMan.XRCompositeTraps(xrsd.picture, 0, 0, traps);
+
+            buf.clear();
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/jules/JulesTile.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.jules;
+
+public class JulesTile {
+    byte[] imgBuffer;
+    long pixmanImgPtr = 0;
+    int tilePos;
+
+    public JulesTile() {
+    }
+
+    public byte[] getImgBuffer() {
+        if(imgBuffer == null) {
+            imgBuffer = new byte[1024];
+        }
+
+        return imgBuffer;
+    }
+
+    public long getPixmanImgPtr() {
+        return pixmanImgPtr;
+    }
+
+    public void setPixmanImgPtr(long pixmanImgPtr) {
+        this.pixmanImgPtr = pixmanImgPtr;
+    }
+
+    public boolean hasBuffer() {
+        return imgBuffer != null;
+    }
+
+    public int getTilePos() {
+        return tilePos;
+    }
+
+    public void setTilePos(int tilePos) {
+        this.tilePos = tilePos;
+    }
+
+    public void setImgBuffer(byte[] imgBuffer){
+        this.imgBuffer = imgBuffer;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/jules/TileWorker.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.jules;
+
+import java.util.*;
+
+public class TileWorker implements Runnable {
+    final static int RASTERIZED_TILE_SYNC_GRANULARITY = 8;
+    final ArrayList<JulesTile> rasterizedTileConsumerCache =
+         new ArrayList<JulesTile>();
+    final LinkedList<JulesTile> rasterizedBuffers = new LinkedList<JulesTile>();
+
+    IdleTileCache tileCache;
+    JulesAATileGenerator tileGenerator;
+    int workerStartIndex;
+    volatile int consumerPos = 0;
+
+    /* Threading statistics */
+    int mainThreadCnt = 0;
+    int workerCnt = 0;
+    int doubled = 0;
+
+    public TileWorker(JulesAATileGenerator tileGenerator, int workerStartIndex, IdleTileCache tileCache) {
+        this.tileGenerator = tileGenerator;
+        this.workerStartIndex = workerStartIndex;
+        this.tileCache = tileCache;
+    }
+
+    public void run() {
+        ArrayList<JulesTile> tiles = new ArrayList<JulesTile>(16);
+
+        for (int i = workerStartIndex; i < tileGenerator.getTileCount(); i++) {
+            TileTrapContainer tile = tileGenerator.getTrapContainer(i);
+
+            if (tile != null && tile.getTileAlpha() == 127) {
+                JulesTile rasterizedTile =
+                      tileGenerator.rasterizeTile(i,
+                           tileCache.getIdleTileWorker(
+                               tileGenerator.getTileCount() - i - 1));
+                tiles.add(rasterizedTile);
+
+                if (tiles.size() > RASTERIZED_TILE_SYNC_GRANULARITY) {
+                    addRasterizedTiles(tiles);
+                    tiles.clear();
+                }
+            }
+
+            i = Math.max(i, consumerPos + RASTERIZED_TILE_SYNC_GRANULARITY / 2);
+        }
+        addRasterizedTiles(tiles);
+
+        tileCache.disposeRasterizerResources();
+    }
+
+    /**
+     * Returns a rasterized tile for the specified tilePos,
+     * or null if it isn't available.
+     * Allowed caller: MaskBlit/Consumer-Thread
+     */
+    public JulesTile getPreRasterizedTile(int tilePos) {
+        JulesTile tile = null;
+
+        if (rasterizedTileConsumerCache.size() == 0 &&
+            tilePos >= workerStartIndex)
+        {
+            synchronized (rasterizedBuffers) {
+                rasterizedTileConsumerCache.addAll(rasterizedBuffers);
+                rasterizedBuffers.clear();
+            }
+        }
+
+        while (tile == null && rasterizedTileConsumerCache.size() > 0) {
+            JulesTile t = rasterizedTileConsumerCache.get(0);
+
+            if (t.getTilePos() > tilePos) {
+                break;
+            }
+
+            if (t.getTilePos() < tilePos) {
+                tileCache.releaseTile(t);
+                doubled++;
+            }
+
+            if (t.getTilePos() <= tilePos) {
+                rasterizedTileConsumerCache.remove(0);
+            }
+
+            if (t.getTilePos() == tilePos) {
+                tile = t;
+            }
+        }
+
+        if (tile == null) {
+            mainThreadCnt++;
+
+            // If there are no tiles left, tell the producer the current
+            // position. This avoids producing tiles twice.
+            consumerPos = tilePos;
+        } else {
+            workerCnt++;
+        }
+
+        return tile;
+    }
+
+    private void addRasterizedTiles(ArrayList<JulesTile> tiles) {
+        synchronized (rasterizedBuffers) {
+            rasterizedBuffers.addAll(tiles);
+        }
+    }
+
+    /**
+     * Releases cached tiles.
+     * Allowed caller: MaskBlit/Consumer-Thread
+     */
+    public void disposeConsumerResources() {
+        synchronized (rasterizedBuffers) {
+            tileCache.releaseTiles(rasterizedBuffers);
+        }
+
+        tileCache.releaseTiles(rasterizedTileConsumerCache);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/jules/TrapezoidList.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.jules;
+
+public class TrapezoidList {
+    public static final int TRAP_START_INDEX = 5;
+    public static final int TRAP_SIZE = 10;
+
+    int[] trapArray;
+
+    public TrapezoidList(int[] trapArray) {
+        this.trapArray = trapArray;
+    }
+
+    public final int[] getTrapArray() {
+        return trapArray;
+    }
+
+    public final int getSize() {
+        return trapArray[0];
+    }
+
+    public final void setSize(int size) {
+        trapArray[0] = 0;
+    }
+
+    public final int getLeft() {
+        return trapArray[1];
+    }
+
+    public final int getTop() {
+        return trapArray[2];
+    }
+
+    public final int getRight() {
+        return trapArray[3];
+    }
+
+    public final int getBottom() {
+        return trapArray[4];
+    }
+
+
+    private final int getTrapStartAddresse(int pos) {
+        return TRAP_START_INDEX + TRAP_SIZE * pos;
+    }
+
+    public final int getTop(int pos) {
+        return trapArray[getTrapStartAddresse(pos) + 0];
+    }
+
+    public final int getBottom(int pos) {
+        return trapArray[getTrapStartAddresse(pos) + 1];
+    }
+
+    public final int getP1XLeft(int pos) {
+        return trapArray[getTrapStartAddresse(pos) + 2];
+    }
+
+    public final int getP1YLeft(int pos) {
+        return trapArray[getTrapStartAddresse(pos) + 3];
+    }
+
+    public final int getP2XLeft(int pos) {
+        return trapArray[getTrapStartAddresse(pos) + 4];
+    }
+
+    public final int getP2YLeft(int pos) {
+        return trapArray[getTrapStartAddresse(pos) + 5];
+    }
+
+    public final int getP1XRight(int pos) {
+        return trapArray[getTrapStartAddresse(pos) + 6];
+    }
+
+    public final int getP1YRight(int pos) {
+        return trapArray[getTrapStartAddresse(pos) + 7];
+    }
+
+    public final int getP2XRight(int pos) {
+        return trapArray[getTrapStartAddresse(pos) + 8];
+    }
+
+    public final int getP2YRight(int pos) {
+        return trapArray[getTrapStartAddresse(pos) + 9];
+    }
+}
--- a/jdk/src/solaris/classes/sun/java2d/x11/X11SurfaceData.java	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/src/solaris/classes/sun/java2d/x11/X11SurfaceData.java	Fri May 28 11:37:44 2010 -0700
@@ -46,6 +46,7 @@
 import sun.awt.SunToolkit;
 import sun.awt.X11ComponentPeer;
 import sun.awt.X11GraphicsConfig;
+import sun.awt.X11GraphicsEnvironment;
 import sun.awt.image.PixelConverter;
 import sun.font.X11TextRenderer;
 import sun.java2d.InvalidPipeException;
@@ -64,7 +65,7 @@
 import sun.java2d.pipe.TextPipe;
 import sun.java2d.pipe.Region;
 
-public abstract class X11SurfaceData extends SurfaceData {
+public abstract class X11SurfaceData extends XSurfaceData {
     X11ComponentPeer peer;
     X11GraphicsConfig graphicsConfig;
     private RenderLoops solidloops;
@@ -74,8 +75,6 @@
     private static native void initIDs(Class xorComp, boolean tryDGA);
     protected native void initSurface(int depth, int width, int height,
                                       long drawable);
-    native boolean isDrawableValid();
-    protected native void flushNativeSurface();
 
     public static final String
         DESC_INT_BGR_X11        = "Integer BGR Pixmap";
@@ -212,7 +211,8 @@
     protected static boolean dgaAvailable;
 
     static {
-        if (!GraphicsEnvironment.isHeadless()) {
+       if (!isX11SurfaceDataInitialized() &&
+           !GraphicsEnvironment.isHeadless()) {
             // If a screen magnifier is present, don't attempt to use DGA
             String magPresent = (String) java.security.AccessController.doPrivileged
                 (new sun.security.action.GetPropertyAction("javax.accessibility.screen_magnifier_present"));
@@ -245,7 +245,7 @@
                 X11PMBlitLoops.register();
                 X11PMBlitBgLoops.register();
             }
-        }
+       }
     }
 
     /**
@@ -432,11 +432,11 @@
                                         cm, drawable, transparency);
     }
 
-    /**
-     * Initializes the native Ops pointer.
-     */
-    private native void initOps(X11ComponentPeer peer,
-                                X11GraphicsConfig gc, int depth);
+//    /**
+//     * Initializes the native Ops pointer.
+//     */
+//    private native void initOps(X11ComponentPeer peer,
+//                                X11GraphicsConfig gc, int depth);
 
     protected X11SurfaceData(X11ComponentPeer peer,
                              X11GraphicsConfig gc,
@@ -613,8 +613,6 @@
         return sType;
     }
 
-    public native void setInvalid();
-
     public void invalidate() {
         if (isValid()) {
             setInvalid();
@@ -628,16 +626,9 @@
      * X11SurfaceData object.
      */
 
-    private static native long XCreateGC(long pXSData);
-    private static native void XResetClip(long xgc);
-    private static native void XSetClip(long xgc,
-                                        int lox, int loy, int hix, int hiy,
-                                        Region complexclip);
     private static native void XSetCopyMode(long xgc);
     private static native void XSetXorMode(long xgc);
     private static native void XSetForeground(long xgc, int pixel);
-    private static native void XSetGraphicsExposures(long xgc,
-                                                     boolean needExposures);
 
     private long xgc;
     private Region validatedClip;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/x11/XSurfaceData.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,40 @@
+package sun.java2d.x11;
+
+import java.awt.image.*;
+
+import sun.awt.*;
+import sun.java2d.*;
+import sun.java2d.loops.*;
+import sun.java2d.pipe.*;
+
+public abstract class XSurfaceData extends SurfaceData {
+    static boolean isX11SurfaceDataInitialized = false;
+
+    public static boolean isX11SurfaceDataInitialized() {
+        return isX11SurfaceDataInitialized;
+    }
+
+    public static void setX11SurfaceDataInitialized() {
+        isX11SurfaceDataInitialized = true;
+    }
+
+    public XSurfaceData(SurfaceType surfaceType, ColorModel cm) {
+        super(surfaceType, cm);
+    }
+
+    protected native void initOps(X11ComponentPeer peer, X11GraphicsConfig gc, int depth);
+
+    protected static native long XCreateGC(long pXSData);
+
+    protected static native void XResetClip(long xgc);
+
+    protected static native void XSetClip(long xgc, int lox, int loy, int hix, int hiy, Region complexclip);
+
+    protected native void flushNativeSurface();
+
+    protected native boolean isDrawableValid();
+
+    protected native void setInvalid();
+
+    protected static native void XSetGraphicsExposures(long xgc, boolean needExposures);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/DirtyRegion.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import static java.lang.Math.min;
+import static java.lang.Math.max;
+import static sun.java2d.xr.MaskTileManager.MASK_SIZE;
+
+/**
+ * This class implements region tracking, used by the tiled-mask code.
+ *
+ * @author Clemens Eisserer
+ */
+
+public class DirtyRegion implements Cloneable {
+    int x, y, x2, y2;
+
+    public DirtyRegion() {
+        clear();
+    }
+
+    public void clear() {
+        x = Integer.MAX_VALUE;
+        y = Integer.MAX_VALUE;
+        x2 = Integer.MIN_VALUE;
+        y2 = Integer.MIN_VALUE;
+    }
+
+    public void growDirtyRegion(int x, int y, int x2, int y2) {
+        this.x = min(x, this.x);
+        this.y = min(y, this.y);
+        this.x2 = max(x2, this.x2);
+        this.y2 = max(y2, this.y2);
+    }
+
+    public int getWidth() {
+        return x2 - x;
+    }
+
+    public int getHeight() {
+        return y2 - y;
+    }
+
+    public void growDirtyRegionTileLimit(int x, int y, int x2, int y2) {
+        if (x < this.x) {
+            this.x = max(x, 0);
+        }
+        if (y < this.y) {
+            this.y = max(y, 0);
+        }
+        if (x2 > this.x2) {
+            this.x2 = min(x2, MASK_SIZE);
+        }
+        if (y2 > this.y2) {
+            this.y2 = min(y2, MASK_SIZE);
+        }
+    }
+
+    public static DirtyRegion combineRegion(DirtyRegion region1,
+                                            DirtyRegion region2) {
+        DirtyRegion region = new DirtyRegion();
+        region.x = min(region1.x, region2.x);
+        region.y = min(region1.y, region2.y);
+        region.x2 = max(region1.x2, region2.x2);
+        region.y2 = max(region1.y2, region2.y2);
+        return region;
+    }
+
+    public void setDirtyLineRegion(int x1, int y1, int x2, int y2) {
+        if (x1 < x2) {
+            this.x = x1;
+            this.x2 = x2;
+        } else {
+            this.x = x2;
+            this.x2 = x1;
+        }
+
+        if (y1 < y2) {
+            this.y = y1;
+            this.y2 = y2;
+        } else {
+            this.y = y2;
+            this.y2 = y1;
+        }
+    }
+
+    public void translate(int x, int y) {
+        if (this.x != Integer.MAX_VALUE) {
+            this.x += x;
+            this.x2 += x;
+            this.y += y;
+            this.y2 += y;
+        }
+    }
+
+    public String toString() {
+        return this.getClass().getName() +
+                "(x: " + x + ", y:" + y + ", x2:" + x2 + ", y2:" + y2 + ")";
+    }
+
+    public DirtyRegion cloneRegion() {
+        try {
+            return (DirtyRegion) clone();
+        } catch (CloneNotSupportedException ex) {
+            ex.printStackTrace();
+        }
+
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/GrowableByteArray.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import java.util.*;
+
+/**
+ * Growable int array, designed to allow subclasses to emulate
+ * the behaviour of value types.
+ *
+ * @author Clemens Eisserer
+ */
+
+public class GrowableByteArray
+{
+
+        byte[] array;
+        int size;
+        int cellSize;
+
+        public GrowableByteArray(int cellSize, int initialSize)
+        {
+                array = new byte[initialSize];
+                size = 0;
+                this.cellSize = cellSize;
+        }
+
+        private int getNextCellIndex()
+        {
+                int oldSize = size;
+                size += cellSize;
+
+                if (size >= array.length)
+                {
+                        growArray();
+                }
+
+                return oldSize;
+        }
+
+        /**
+         * @return a direct reference to the backing array.
+         */
+        public byte[] getArray()
+        {
+                return array;
+        }
+
+        /**
+         * @return a copy of the backing array.
+         */
+        public byte[] getSizedArray()
+        {
+                return Arrays.copyOf(array, getSize());
+        }
+
+        public final int getByte(int index)
+        {
+                return array[getCellIndex(index)];
+        }
+
+        /**
+         * Returns the index of the next free cell,
+         * and grows the backing arrays if required.
+         */
+        public final int getNextIndex()
+        {
+                return getNextCellIndex() / cellSize;
+        }
+
+        protected final int getCellIndex(int cellIndex)
+        {
+                return cellSize * cellIndex;
+        }
+
+        public final void addByte(byte i)
+        {
+            int nextIndex = getNextIndex();
+            array[nextIndex] = i;
+        }
+
+        /**
+         * @return The number of stored cells.
+         */
+        public final int getSize()
+        {
+                return size / cellSize;
+        }
+
+        public void clear()
+        {
+                size = 0;
+        }
+
+        protected void growArray()
+        {
+                int newSize = Math.max(array.length * 2, 10);
+                byte[] oldArray = array;
+                array = new byte[newSize];
+
+                System.arraycopy(oldArray, 0, array, 0, oldArray.length);
+        }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/GrowableEltArray.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+/**
+ * Class to efficiently store glyph information for laid out glyphs,
+ * passed to native or java backend.
+ *
+ * @author Clemens Eisserer
+ */
+public class GrowableEltArray extends GrowableIntArray {
+    private static final int ELT_SIZE = 4;
+    GrowableIntArray glyphs;
+
+    public GrowableEltArray(int initialSize)
+    {
+        super(ELT_SIZE, initialSize);
+        glyphs = new GrowableIntArray(1, initialSize*8);
+    }
+
+    public final int getCharCnt(int index) {
+        return array[getCellIndex(index) + 0];
+    }
+
+    public final void setCharCnt(int index, int cnt) {
+        array[getCellIndex(index) + 0] = cnt;
+    }
+
+    public final int getXOff(int index) {
+        return array[getCellIndex(index) + 1];
+    }
+
+    public final void setXOff(int index, int xOff) {
+        array[getCellIndex(index) + 1] = xOff;
+    }
+
+    public final int getYOff(int index) {
+        return array[getCellIndex(index) + 2];
+    }
+
+    public final void setYOff(int index, int yOff) {
+        array[getCellIndex(index) + 2] = yOff;
+    }
+
+    public final int getGlyphSet(int index) {
+        return array[getCellIndex(index) + 3];
+    }
+
+    public final void setGlyphSet(int index, int glyphSet) {
+        array[getCellIndex(index) + 3] = glyphSet;
+    }
+
+    public GrowableIntArray getGlyphs() {
+        return glyphs;
+    }
+
+    public void clear() {
+        glyphs.clear();
+        super.clear();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/GrowableIntArray.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import java.util.*;
+
+/**
+ * Growable int array, designed to allow subclasses to emulate
+ * the behaviour of value types.
+ *
+ * @author Clemens Eisserer
+ */
+
+public class GrowableIntArray {
+
+    int[] array;
+    int size;
+    int cellSize;
+
+    public GrowableIntArray(int cellSize, int initialSize) {
+        array = new int[initialSize];
+        size = 0;
+        this.cellSize = cellSize;
+    }
+
+    private int getNextCellIndex() {
+        int oldSize = size;
+        size += cellSize;
+
+        if (size >= array.length) {
+            growArray();
+        }
+
+        return oldSize;
+    }
+
+    /**
+     * @return a direct reference to the backing array.
+     */
+    public int[] getArray() {
+        return array;
+    }
+
+    /**
+     * @return a copy of the backing array.
+     */
+    public int[] getSizedArray() {
+        return Arrays.copyOf(array, getSize());
+    }
+
+    /**
+     * Returns the index of the next free cell,
+     * and grows the backing arrays if required.
+     */
+    public final int getNextIndex() {
+        return getNextCellIndex() / cellSize;
+    }
+
+    protected final int getCellIndex(int cellIndex) {
+        return cellSize * cellIndex;
+    }
+
+    public final int getInt(int cellIndex) {
+        return array[cellIndex];
+    }
+
+    public final void addInt(int i) {
+        int nextIndex = getNextIndex();
+        array[nextIndex] = i;
+    }
+
+    /**
+     * @return The number of stored cells.
+     */
+    public final int getSize() {
+        return size / cellSize;
+    }
+
+    public void clear() {
+        size = 0;
+    }
+
+    protected void growArray() {
+        int newSize = Math.max(array.length * 2, 10);
+        int[] oldArray = array;
+        array = new int[newSize];
+
+        System.arraycopy(oldArray, 0, array, 0, oldArray.length);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/GrowablePointArray.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+/**
+ * Class to efficiently store rectangles.
+ *
+ * @author Clemens Eisserer
+ */
+public class GrowablePointArray extends GrowableIntArray
+{
+
+        private static final int POINT_SIZE = 2;
+
+        public GrowablePointArray(int initialSize)
+        {
+                super(POINT_SIZE, initialSize);
+        }
+
+        public final int getX(int index)
+        {
+                return array[getCellIndex(index)];
+        }
+
+        public final int getY(int index)
+        {
+                return array[getCellIndex(index) + 1];
+        }
+
+        public final void setX(int index, int x)
+        {
+                array[getCellIndex(index)] = x;
+        }
+
+        public final void setY(int index, int y)
+        {
+                array[getCellIndex(index) + 1] = y;
+        }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/GrowableRectArray.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+/**
+ * Class to efficiently store rectangles.
+ *
+ * @author Clemens Eisserer
+ */
+public class GrowableRectArray extends GrowableIntArray {
+
+    private static final int RECT_SIZE = 4;
+
+    public GrowableRectArray(int initialSize) {
+        super(RECT_SIZE, initialSize);
+    }
+
+    public final void setX(int index, int x) {
+        array[getCellIndex(index)] = x;
+    }
+
+    public final void setY(int index, int y) {
+        array[getCellIndex(index) + 1] = y;
+    }
+
+    public final void setWidth(int index, int width) {
+        array[getCellIndex(index) + 2] = width;
+    }
+
+    public final void setHeight(int index, int height) {
+        array[getCellIndex(index) + 3] = height;
+    }
+
+    public final int getX(int index) {
+        return array[getCellIndex(index)];
+    }
+
+    public final int getY(int index) {
+        return array[getCellIndex(index) + 1];
+    }
+
+    public final int getWidth(int index) {
+        return array[getCellIndex(index) + 2];
+    }
+
+    public final int getHeight(int index) {
+        return array[getCellIndex(index) + 3];
+    }
+
+    public final void translateRects(int x, int y) {
+        for (int i = 0; i < getSize(); i++) {
+            setX(i, getX(i) + x);
+            setY(i, getY(i) + y);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/MaskTile.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+/**
+ * Represents a single tile, used to store the rectangles covering the area
+ * of the mask where the tile is located.
+ *
+ * @author Clemens Eisserer
+ */
+public class MaskTile {
+    GrowableRectArray rects;
+    DirtyRegion dirtyArea;
+
+    public MaskTile()
+    {
+        rects = new GrowableRectArray(128);
+        dirtyArea = new DirtyRegion();
+    }
+
+    public void addRect(int x, int y, int width, int height) {
+        int index = rects.getNextIndex();
+        rects.setX(index, x);
+        rects.setY(index, y);
+        rects.setWidth(index, width);
+        rects.setHeight(index, height);
+    }
+
+    public void addLine(int x1, int y1, int x2, int y2) {
+        /*
+         * EXA is not able to accalerate diagonal lines, we try to "guide" it a
+         * bit to avoid excessive migration See project documentation for an
+         * detailed explanation
+         */
+        DirtyRegion region = new DirtyRegion();
+        region.setDirtyLineRegion(x1, y1, x2, y2);
+        int xDiff = region.x2 - region.x;
+        int yDiff = region.y2 - region.y;
+
+        if (xDiff == 0 || yDiff == 0) {
+            addRect(region.x, region.y,
+                    region.x2 - region.x + 1, region.y2 - region.y + 1);
+        } else if (xDiff == 1 && yDiff == 1) {
+            addRect(x1, y1, 1, 1);
+            addRect(x2, y2, 1, 1);
+        } else {
+            lineToRects(x1, y1, x2, y2);
+        }
+    }
+
+    private void lineToRects(int xstart, int ystart, int xend, int yend) {
+        int x, y, t, dx, dy, incx, incy, pdx, pdy, ddx, ddy, es, el, err;
+
+        /* Entfernung in beiden Dimensionen berechnen */
+        dx = xend - xstart;
+        dy = yend - ystart;
+
+        /* Vorzeichen des Inkrements bestimmen */
+        incx = dx > 0 ? 1 : (dx < 0) ? -1 : 0;
+        incy = dy > 0 ? 1 : (dy < 0) ? -1 : 0;
+        if (dx < 0)
+            dx = -dx;
+        if (dy < 0)
+            dy = -dy;
+
+        /* feststellen, welche Entfernung groesser ist */
+        if (dx > dy) {
+            /* x ist schnelle Richtung */
+            pdx = incx;
+            pdy = 0; /* pd. ist Parallelschritt */
+            ddx = incx;
+            ddy = incy; /* dd. ist Diagonalschritt */
+            es = dy;
+            el = dx; /* Fehlerschritte schnell, langsam */
+        } else {
+            /* y ist schnelle Richtung */
+            pdx = 0;
+            pdy = incy; /* pd. ist Parallelschritt */
+            ddx = incx;
+            ddy = incy; /* dd. ist Diagonalschritt */
+            es = dx;
+            el = dy; /* Fehlerschritte schnell, langsam */
+        }
+
+        /* Initialisierungen vor Schleifenbeginn */
+        x = xstart;
+        y = ystart;
+        err = el / 2;
+        addRect(x, y, 1, 1);
+
+        /* Pixel berechnen */
+        for (t = 0; t < el; ++t) /* t zaehlt die Pixel, el ist auch Anzahl */
+        {
+            /* Aktualisierung Fehlerterm */
+            err -= es;
+            if (err < 0) {
+                /* Fehlerterm wieder positiv (>=0) machen */
+                err += el;
+                /* Schritt in langsame Richtung, Diagonalschritt */
+                x += ddx;
+                y += ddy;
+            } else {
+                /* Schritt in schnelle Richtung, Parallelschritt */
+                x += pdx;
+                y += pdy;
+            }
+            addRect(x, y, 1, 1);
+            // SetPixel(x,y);
+            // System.out.println(x+":"+y);
+        }
+    }
+
+    public void calculateDirtyAreas()
+    {
+        for (int i=0; i < rects.getSize(); i++) {
+            int x = rects.getX(i);
+            int y = rects.getY(i);
+            dirtyArea.growDirtyRegion(x, y,
+                                      x + rects.getWidth(i),
+                                      y + rects.getHeight(i));
+        }
+    }
+
+    public void reset() {
+        rects.clear();
+        dirtyArea.clear();
+    }
+
+    public void translate(int x, int y) {
+        if (rects.getSize() > 0) {
+            dirtyArea.translate(x, y);
+        }
+        rects.translateRects(x, y);
+    }
+
+    public GrowableRectArray getRects() {
+        return rects;
+    }
+
+    public DirtyRegion getDirtyArea() {
+        return dirtyArea;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/MaskTileManager.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import java.awt.*;
+import java.util.*;
+
+/**
+ * We render non-antialiased geometry (consisting of rectangles) into a mask,
+ * which is later used in a composition step.
+ * To avoid mask-allocations of large size, MaskTileManager splits
+ * geometry larger than MASK_SIZE into several tiles,
+ * and stores the geometry in instances of MaskTile.
+ *
+ * @author Clemens Eisserer
+ */
+
+public class MaskTileManager {
+
+    public static final int MASK_SIZE = 256;
+
+    MaskTile mainTile = new MaskTile();
+
+    ArrayList<MaskTile> tileList;
+    int allocatedTiles = 0;
+    int xTiles, yTiles;
+
+    XRCompositeManager xrMgr;
+    XRBackend con;
+
+    int maskPixmap;
+    int maskPicture;
+    long maskGC;
+    int lineMaskPixmap;
+    int lineMaskPicture;
+    long drawLineGC;
+    long clearLineGC;
+
+    public MaskTileManager(XRCompositeManager xrMgr, int parentXid) {
+        tileList = new ArrayList<MaskTile>();
+        this.xrMgr = xrMgr;
+        this.con = xrMgr.getBackend();
+
+        maskPixmap = con.createPixmap(parentXid, 8, MASK_SIZE, MASK_SIZE);
+        maskPicture = con.createPicture(maskPixmap, XRUtils.PictStandardA8);
+        con.renderRectangle(maskPicture, XRUtils.PictOpClear,
+                            new XRColor(Color.black),
+                            0, 0, MASK_SIZE, MASK_SIZE);
+        maskGC = con.createGC(maskPixmap);
+        con.setGCExposures(maskGC, false);
+
+        lineMaskPixmap = con.createPixmap(parentXid, 8, MASK_SIZE, MASK_SIZE);
+        lineMaskPicture =
+             con.createPicture(lineMaskPixmap, XRUtils.PictStandardA8);
+        con.renderRectangle(lineMaskPicture, XRUtils.PictOpClear,
+                          new XRColor(Color.black), 0, 0, MASK_SIZE, MASK_SIZE);
+
+        drawLineGC = con.createGC(lineMaskPixmap);
+        con.setGCExposures(drawLineGC, false);
+        con.setGCForeground(drawLineGC, 255);
+
+        clearLineGC = con.createGC(lineMaskPixmap);
+        con.setGCExposures(clearLineGC, false);
+        con.setGCForeground(clearLineGC, 0);
+    }
+
+    /**
+     * Adds a rectangle to the mask.
+     */
+    public void addRect(int x, int y, int width, int height) {
+        mainTile.addRect(x, y, width, height);
+    }
+
+    /**
+     * Adds a line to the mask.
+     */
+    public void addLine(int x1, int y1, int x2, int y2) {
+        mainTile.addLine(x1, y1, x2, y2);
+    }
+
+    /**
+     * Transfers the geometry stored (rectangles, lines) to one or more masks,
+     * and renders the result to the destination surface.
+     */
+    public void fillMask(XRSurfaceData dst) {
+
+        boolean maskRequired = xrMgr.maskRequired();
+
+        if (maskRequired) {
+            mainTile.calculateDirtyAreas();
+            DirtyRegion dirtyArea = mainTile.getDirtyArea().cloneRegion();
+            mainTile.translate(-dirtyArea.x, -dirtyArea.y);
+
+            XRColor maskColor = xrMgr.getMaskColor();
+
+            // We don't need tiling if all geometry fits in a single tile
+            if (dirtyArea.getWidth() <= MASK_SIZE &&
+                dirtyArea.getHeight() <= MASK_SIZE)
+            {
+                compositeSingleTile(dst, mainTile, dirtyArea,
+                                     maskRequired, 0, 0, maskColor);
+            } else {
+                allocTiles(dirtyArea);
+                tileRects();
+
+                for (int i = 0; i < yTiles; i++) {
+                    for (int m = 0; m < xTiles; m++) {
+                        MaskTile tile = tileList.get(i * xTiles + m);
+
+                        int tileStartX = m * MASK_SIZE;
+                        int tileStartY = i * MASK_SIZE;
+                        compositeSingleTile(dst, tile, dirtyArea, maskRequired,
+                                            tileStartX, tileStartY, maskColor);
+                    }
+                }
+            }
+        } else {
+            xrMgr.XRRenderRectangles(dst, mainTile.getRects());
+        }
+
+        mainTile.reset();
+    }
+
+    /**
+     * Uploads aa geometry generated for maskblit/fill into the mask pixmap.
+     */
+    public int uploadMask(int w, int h, int maskscan, int maskoff, byte[] mask) {
+        int maskPic = XRUtils.None;
+
+        if (mask != null) {
+            float maskAlpha =
+                 xrMgr.isTexturePaintActive() ? xrMgr.getExtraAlpha() : 1.0f;
+            con.putMaskImage(maskPixmap, maskGC, mask, 0, 0, 0, 0,
+                             w, h, maskoff, maskscan, maskAlpha);
+            maskPic = maskPicture;
+        } else if (xrMgr.isTexturePaintActive()) {
+            maskPic = xrMgr.getExtraAlphaMask();
+         }
+
+        return maskPic;
+    }
+
+    /**
+     * Clears the area of the mask-pixmap used for uploading aa coverage values.
+     */
+    public void clearUploadMask(int mask, int w, int h) {
+        if (mask == maskPicture) {
+            con.renderRectangle(maskPicture, XRUtils.PictOpClear,
+                                XRColor.NO_ALPHA, 0, 0, w, h);
+        }
+    }
+
+
+    /**
+     * Renders the rectangles provided to the mask, and does a composition
+     * operation with the properties set inXRCompositeManager.
+     */
+    protected void compositeSingleTile(XRSurfaceData dst, MaskTile tile,
+                                       DirtyRegion dirtyArea,
+                                       boolean maskRequired,
+                                       int tileStartX, int tileStartY,
+                                       XRColor maskColor) {
+        if (tile.rects.getSize() > 0) {
+            DirtyRegion tileDirtyArea = tile.getDirtyArea();
+
+            int x = tileDirtyArea.x + tileStartX + dirtyArea.x;
+            int y = tileDirtyArea.y + tileStartY + dirtyArea.y;
+            int width = tileDirtyArea.x2 - tileDirtyArea.x;
+            int height = tileDirtyArea.y2 - tileDirtyArea.y;
+            width = Math.min(width, MASK_SIZE);
+            height = Math.min(height, MASK_SIZE);
+
+            int rectCnt = tile.rects.getSize();
+
+            if (maskRequired) {
+                int mask = XRUtils.None;
+
+                /*
+                 * Optimization: When the tile only contains one rectangle, the
+                 * composite-operation boundaries can be used as geometry
+                 */
+                if (rectCnt > 1) {
+                    con.renderRectangles(maskPicture, XRUtils.PictOpSrc,
+                                         maskColor, tile.rects);
+                    mask = maskPicture;
+                } else {
+                    if (xrMgr.isTexturePaintActive()) {
+                        mask = xrMgr.getExtraAlphaMask();
+                    }
+                }
+
+                xrMgr.XRComposite(XRUtils.None, mask, dst.getPicture(),
+                                  x, y, tileDirtyArea.x, tileDirtyArea.y,
+                                  x, y, width, height);
+
+                /* Clear dirty rectangle of the rect-mask */
+                if (rectCnt > 1) {
+                    con.renderRectangle(maskPicture, XRUtils.PictOpClear,
+                                        XRColor.NO_ALPHA,
+                                        tileDirtyArea.x, tileDirtyArea.y,
+                                        width, height);
+                }
+
+                tile.reset();
+            } else if (rectCnt > 0) {
+                tile.rects.translateRects(tileStartX + dirtyArea.x,
+                                          tileStartY + dirtyArea.y);
+                xrMgr.XRRenderRectangles(dst, tile.rects);
+            }
+        }
+    }
+
+
+    /**
+     * Allocates enough MaskTile instances, to cover the whole
+     * mask area, or resets existing ones.
+     */
+    protected void allocTiles(DirtyRegion maskArea) {
+        xTiles = (maskArea.getWidth() / MASK_SIZE) + 1;
+        yTiles = (maskArea.getHeight() / MASK_SIZE) + 1;
+        int tileCnt = xTiles * yTiles;
+
+        if (tileCnt > allocatedTiles) {
+            for (int i = 0; i < tileCnt; i++) {
+                if (i < allocatedTiles) {
+                    tileList.get(i).reset();
+                } else {
+                    tileList.add(new MaskTile());
+                }
+            }
+
+            allocatedTiles = tileCnt;
+        }
+    }
+
+    /**
+     * Tiles the stored rectangles, if they are larger than the MASK_SIZE
+     */
+    protected void tileRects() {
+        GrowableRectArray rects = mainTile.rects;
+
+        for (int i = 0; i < rects.getSize(); i++) {
+            int tileXStartIndex = rects.getX(i) / MASK_SIZE;
+            int tileYStartIndex = rects.getY(i) / MASK_SIZE;
+            int tileXLength =
+                ((rects.getX(i) + rects.getWidth(i)) / MASK_SIZE + 1) -
+                 tileXStartIndex;
+            int tileYLength =
+                 ((rects.getY(i) + rects.getHeight(i)) / MASK_SIZE + 1) -
+                 tileYStartIndex;
+
+            for (int n = 0; n < tileYLength; n++) {
+                for (int m = 0; m < tileXLength; m++) {
+
+                    int tileIndex =
+                         xTiles * (tileYStartIndex + n) + tileXStartIndex + m;
+                    MaskTile tile = tileList.get(tileIndex);
+
+                    GrowableRectArray rectTileList = tile.getRects();
+                    int tileArrayIndex = rectTileList.getNextIndex();
+
+                    int tileStartPosX = (tileXStartIndex + m) * MASK_SIZE;
+                    int tileStartPosY = (tileYStartIndex + n) * MASK_SIZE;
+
+                    rectTileList.setX(tileArrayIndex, rects.getX(i) - tileStartPosX);
+                    rectTileList.setY(tileArrayIndex, rects.getY(i) - tileStartPosY);
+                    rectTileList.setWidth(tileArrayIndex, rects.getWidth(i));
+                    rectTileList.setHeight(tileArrayIndex, rects.getHeight(i));
+
+                    limitRectCoords(rectTileList, tileArrayIndex);
+
+                    tile.getDirtyArea().growDirtyRegion
+                       (rectTileList.getX(tileArrayIndex),
+                        rectTileList.getY(tileArrayIndex),
+                        rectTileList.getWidth(tileArrayIndex) +
+                             rectTileList.getX(tileArrayIndex),
+                        rectTileList.getHeight(tileArrayIndex) +
+                            rectTileList.getY(tileArrayIndex));
+                }
+            }
+        }
+    }
+
+    /**
+     * Limits the rect's coordinates to the mask coordinates. The result is used
+     * by growDirtyRegion.
+     */
+    private void limitRectCoords(GrowableRectArray rects, int index) {
+        if ((rects.getX(index) + rects.getWidth(index)) > MASK_SIZE) {
+            rects.setWidth(index, MASK_SIZE - rects.getX(index));
+        }
+        if ((rects.getY(index) + rects.getHeight(index)) > MASK_SIZE) {
+            rects.setHeight(index, MASK_SIZE - rects.getY(index));
+        }
+        if (rects.getX(index) < 0) {
+            rects.setWidth(index, rects.getWidth(index) + rects.getX(index));
+            rects.setX(index, 0);
+        }
+        if (rects.getY(index) < 0) {
+            rects.setHeight(index, rects.getHeight(index) + rects.getY(index));
+            rects.setY(index, 0);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/MutableInteger.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+/**
+ * Simple MutableInteger implementation to be used as a reuseable HashMap key.
+ *
+ * @author Clemens Eisserer
+ */
+
+public class MutableInteger {
+    private int value;
+
+    public MutableInteger(int value) {
+        this.setValue(value);
+    }
+
+    public int hashCode() {
+        return getValue();
+    }
+
+    public boolean equals(Object o) {
+        return (o instanceof MutableInteger) &&
+               (((MutableInteger) o).getValue() == getValue());
+    }
+
+    public void setValue(int value) {
+        this.value = value;
+    }
+
+    public int getValue() {
+        return value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XIDGenerator.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+/**
+ * Class provides unused XIDs, used for creating server-side objects
+ * created by the java backend.
+ * It does buffering, to minimize JNI overhead.
+ *
+ * @author Clemens Eisserer
+ */
+
+public class XIDGenerator {
+    private final static int XID_BUFFER_SIZE = 512;
+
+    int[] xidBuffer = new int[XID_BUFFER_SIZE];
+    int currentIndex = XID_BUFFER_SIZE;
+
+    public int getNextXID() {
+
+        if (currentIndex >= XID_BUFFER_SIZE) {
+            bufferXIDs(xidBuffer, xidBuffer.length);
+            currentIndex = 0;
+        }
+
+        return xidBuffer[currentIndex++];
+    }
+
+    private static native void bufferXIDs(int[] buffer, int arraySize);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRBackend.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+/**
+ * XRender pipeline backend interface.
+ * Currently there are two different backends implemented:
+ * - XRBackendJava: And experimental backend, generating protocol directly using java-code and xcb's socket handoff functionality.
+ * - XRBackendNative: Native 1:1 binding with libX11.
+ */
+
+import java.awt.geom.*;
+import java.util.*;
+
+import sun.font.*;
+import sun.java2d.jules.*;
+import sun.java2d.pipe.*;
+
+public interface XRBackend {
+
+    public void freePicture(int picture);
+
+    public void freePixmap(int pixmap);
+
+    public int createPixmap(int drawable, int depth, int width, int height);
+
+    public int createPicture(int drawable, int formatID);
+
+    public long createGC(int drawable);
+
+    public void freeGC(long gc); /* TODO: Use!! */
+
+    public void copyArea(int src, int dst, long gc, int srcx, int srcy,
+                         int width, int height, int dstx, int dsty);
+
+    public void putMaskImage(int drawable, long gc, byte[] imageData,
+                             int sx, int sy, int dx, int dy,
+                             int width, int height, int maskOff,
+                             int maskScan, float ea);
+
+    public void setGCClipRectangles(long gc, Region clip);
+
+    public void GCRectangles(int drawable, long gc, GrowableRectArray rects);
+
+    public void setClipRectangles(int picture, Region clip);
+
+    public void setGCExposures(long gc, boolean exposure);
+
+    public void setGCForeground(long gc, int pixel);
+
+    public void setPictureTransform(int picture, AffineTransform transform);
+
+    public void setPictureRepeat(int picture, int repeat);
+
+    public void setFilter(int picture, int filter);
+
+    public void renderRectangle(int dst, byte op, XRColor color,
+                                int x, int y, int width, int height);
+
+    public void renderRectangles(int dst, byte op, XRColor color,
+                                 GrowableRectArray rects);
+
+    public void renderComposite(byte op, int src, int mask, int dst,
+                                int srcX, int srcY, int maskX, int maskY,
+                                int dstX, int dstY, int width, int height);
+
+    public int XRenderCreateGlyphSet(int formatID);
+
+    public void XRenderAddGlyphs(int glyphSet, GlyphList gl,
+                                 List<XRGlyphCacheEntry> cacheEntries,
+                                 byte[] pixelData);
+
+    public void XRenderFreeGlyphs(int glyphSet, int[] gids);
+
+    public void XRenderCompositeText(byte op, int src, int dst,
+                                     int maskFormatID,
+                                     int xSrc, int ySrc, int xDst, int yDst,
+                                     int glyphset, GrowableEltArray elts);
+
+    public int createRadialGradient(Point2D inner, Point2D outer,
+                                    float innerRadius, float outerRadius,
+                                    float[] fractions, int[] pixels,
+                                    int repeat, AffineTransform transform);
+
+    public int createLinearGradient(Point2D p1, Point2D p2, float[] fractions,
+                                    int[] pixels, int repeat,
+                                     AffineTransform transform);
+
+    public void setGCMode(long gc, boolean copy);
+
+    public void renderCompositeTrapezoids(byte op, int src, int maskFormat,
+                                          int dst, int srcX, int srcY,
+                                          TrapezoidList trapList);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRBackendNative.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,343 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import java.awt.geom.*;
+import java.util.*;
+
+import sun.font.*;
+import sun.java2d.jules.*;
+import sun.java2d.pipe.*;
+
+import static sun.java2d.xr.XRUtils.XDoubleToFixed;
+
+/**
+ * Native implementation of XRBackend.
+ * Almost direct 1:1 binding to libX11.
+ *
+ * @author Clemens Eisserer
+ */
+
+public class XRBackendNative implements XRBackend {
+
+    static {
+        initIDs();
+    }
+
+    private static long FMTPTR_A8;
+    private static long FMTPTR_ARGB32;
+    private static long MASK_XIMG;
+
+    private static native void initIDs();
+
+    public native long createGC(int drawable);
+
+    public native void freeGC(long gc);
+
+    public native int createPixmap(int drawable, int depth,
+                                   int width, int height);
+
+    private native int createPictureNative(int drawable, long formatID);
+
+    public native void freePicture(int picture);
+
+    public native void freePixmap(int pixmap);
+
+    public native void setGCExposures(long gc, boolean exposure);
+
+    public native void setGCForeground(long gc, int pixel);
+
+    public native void setPictureRepeat(int picture, int repeat);
+
+    public native void copyArea(int src, int dst, long gc,
+                                int srcx, int srcy, int width, int height,
+                                 int dstx, int dsty);
+
+    public native void setGCMode(long gc, boolean copy);
+
+    private static native void GCRectanglesNative(int drawable, long gc,
+                                                  int[] rectArray, int rectCnt);
+
+    public native void renderComposite(byte op, int src, int mask,
+                                       int dst, int srcX, int srcY,
+                                       int maskX, int maskY, int dstX, int dstY,
+                                       int width, int height);
+
+    private native void renderRectangle(int dst, byte op,
+                                        short red, short green,
+                                        short blue, short alpha,
+                                        int x, int y, int width, int height);
+
+    private static native void
+         XRenderRectanglesNative(int dst, byte op,
+                                 short red, short green,
+                                 short blue, short alpha,
+                                 int[] rects, int rectCnt);
+
+    private native void XRSetTransformNative(int pic,
+                                             int m00, int m01, int m02,
+                                             int m10, int m11, int m12);
+
+    private static native int
+        XRCreateLinearGradientPaintNative(float[] fractionsArray,
+                                          short[] pixelsArray,
+                                          int x1, int y1, int x2, int y2,
+                                          int numStops, int repeat,
+                                          int m00, int m01, int m02,
+                                           int m10, int m11, int m12);
+
+    private native static int
+        XRCreateRadialGradientPaintNative(float[] fractionsArray,
+                                          short[] pixelsArray, int numStops,
+                                          int innerRadius, int outerRadius,
+                                          int repeat,
+                                          int m00, int m01, int m02,
+                                          int m10, int m11, int m12);
+
+    public native void setFilter(int picture, int filter);
+
+    private static native void XRSetClipNative(long dst,
+                                               int x1, int y1, int x2, int y2,
+                                               Region clip, boolean isGC);
+
+    public void GCRectangles(int drawable, long gc, GrowableRectArray rects) {
+        GCRectanglesNative(drawable, gc, rects.getArray(), rects.getSize());
+    }
+
+    public int createPicture(int drawable, int formatID) {
+        return createPictureNative(drawable, getFormatPtr(formatID));
+    }
+
+    public void setPictureTransform(int picture, AffineTransform transform) {
+        XRSetTransformNative(picture,
+                             XDoubleToFixed(transform.getScaleX()),
+                             XDoubleToFixed(transform.getShearX()),
+                             XDoubleToFixed(transform.getTranslateX()),
+                             XDoubleToFixed(transform.getShearY()),
+                             XDoubleToFixed(transform.getScaleY()),
+                             XDoubleToFixed(transform.getTranslateY()));
+    }
+
+    public void renderRectangle(int dst, byte op, XRColor color,
+                                int x, int y, int width, int height) {
+        renderRectangle(dst, op, (short)color.red, (short)color.green,
+                       (short)color.blue, (short)color.alpha,
+                        x, y, width, height);
+    }
+
+    private short[] getRenderColors(int[] pixels) {
+        short[] renderColors = new short[pixels.length * 4];
+
+        XRColor c = new XRColor();
+        for (int i = 0; i < pixels.length; i++) {
+            c.setColorValues(pixels[i], true);
+            renderColors[i * 4 + 0] = (short) c.alpha;
+            renderColors[i * 4 + 1] = (short) c.red;
+            renderColors[i * 4 + 2] = (short) c.green;
+            renderColors[i * 4 + 3] = (short) c.blue;
+        }
+
+        return renderColors;
+    }
+
+    private static long getFormatPtr(int formatID) {
+        switch (formatID) {
+        case XRUtils.PictStandardA8:
+            return FMTPTR_A8;
+        case XRUtils.PictStandardARGB32:
+            return FMTPTR_ARGB32;
+        }
+
+        return 0L;
+    }
+
+    public int createLinearGradient(Point2D p1, Point2D p2, float[] fractions,
+                              int[] pixels,  int repeat, AffineTransform trx) {
+
+        short[] colorValues = getRenderColors(pixels);
+        int gradient =
+           XRCreateLinearGradientPaintNative(fractions, colorValues,
+                XDoubleToFixed(p1.getX()), XDoubleToFixed(p1.getY()),
+                XDoubleToFixed(p2.getX()), XDoubleToFixed(p2.getY()),
+                fractions.length, repeat,
+                XDoubleToFixed(trx.getScaleX()),
+                XDoubleToFixed(trx.getShearX()),
+                XDoubleToFixed(trx.getTranslateX()),
+                XDoubleToFixed(trx.getShearY()),
+                XDoubleToFixed(trx.getScaleY()),
+                XDoubleToFixed(trx.getTranslateY()));
+        return gradient;
+    }
+
+    public int createRadialGradient(Point2D inner, Point2D outer,
+                                   float innerRadius, float outerRadius,
+                                   float[] fractions, int[] pixels, int repeat,
+                                   AffineTransform trx) {
+
+        short[] colorValues = getRenderColors(pixels);
+        return XRCreateRadialGradientPaintNative
+             (fractions, colorValues, fractions.length,
+              XDoubleToFixed(innerRadius),
+              XDoubleToFixed(outerRadius),
+              repeat,
+              XDoubleToFixed(trx.getScaleX()),
+              XDoubleToFixed(trx.getShearX()),
+              XDoubleToFixed(trx.getTranslateX()),
+              XDoubleToFixed(trx.getShearY()),
+              XDoubleToFixed(trx.getScaleY()),
+              XDoubleToFixed(trx.getTranslateY()));
+    }
+
+    public void setGCClipRectangles(long gc, Region clip) {
+        XRSetClipNative(gc, clip.getLoX(), clip.getLoY(),
+                        clip.getHiX(), clip.getHiY(),
+                        clip.isRectangular() ? null : clip, true);
+    }
+
+    public void setClipRectangles(int picture, Region clip) {
+        if (clip != null) {
+            XRSetClipNative(picture, clip.getLoX(), clip.getLoY(),
+                            clip.getHiX(), clip.getHiY(),
+                            clip.isRectangular() ? null : clip, false);
+        } else {
+            XRSetClipNative(picture, 0, 0, 32767, 32767, null, false);
+        }
+    }
+
+    public void renderRectangles(int dst, byte op, XRColor color,
+                                 GrowableRectArray rects) {
+        XRenderRectanglesNative(dst, op,
+                                (short) color.red, (short) color.green,
+                                (short) color.blue, (short) color.alpha,
+                                rects.getArray(), rects
+                .getSize());
+    }
+
+    private static long[] getGlyphInfoPtrs(List<XRGlyphCacheEntry> cacheEntries) {
+        long[] glyphInfoPtrs = new long[cacheEntries.size()];
+        for (int i = 0; i < cacheEntries.size(); i++) {
+            glyphInfoPtrs[i] = cacheEntries.get(i).getGlyphInfoPtr();
+        }
+        return glyphInfoPtrs;
+    }
+
+    public void XRenderAddGlyphs(int glyphSet, GlyphList gl,
+                                 List<XRGlyphCacheEntry> cacheEntries,
+                                 byte[] pixelData) {
+        long[] glyphInfoPtrs = getGlyphInfoPtrs(cacheEntries);
+        XRAddGlyphsNative(glyphSet, glyphInfoPtrs,
+                          glyphInfoPtrs.length, pixelData, pixelData.length);
+    }
+
+    public void XRenderFreeGlyphs(int glyphSet, int[] gids) {
+        XRFreeGlyphsNative(glyphSet, gids, gids.length);
+    }
+
+    private static native void XRAddGlyphsNative(int glyphSet,
+                                                 long[] glyphInfoPtrs,
+                                                 int glyphCnt,
+                                                 byte[] pixelData,
+                                                 int pixelDataLength);
+
+    private static native void XRFreeGlyphsNative(int glyphSet,
+                                                  int[] gids, int idCnt);
+
+    private static native void
+        XRenderCompositeTextNative(int op, int src, int dst,
+                                   long maskFormat, int[] eltArray,
+                                   int[] glyphIDs, int eltCnt, int glyphCnt);
+
+    public int XRenderCreateGlyphSet(int formatID) {
+        return XRenderCreateGlyphSetNative(getFormatPtr(formatID));
+    }
+
+    private static native int XRenderCreateGlyphSetNative(long format);
+
+    public void XRenderCompositeText(byte op, int src, int dst,
+                                     int maskFormatID,
+                                     int src2, int src3, int dst2, int dst3,
+                                     int glyphset, GrowableEltArray elts) {
+
+        GrowableIntArray glyphs = elts.getGlyphs();
+        XRenderCompositeTextNative(op, src, dst, 0, elts.getArray(),
+                                   glyphs.getArray(), elts.getSize(),
+                                   glyphs.getSize());
+    }
+
+    public void putMaskImage(int drawable, long gc, byte[] imageData,
+                             int sx, int sy, int dx, int dy,
+                             int width, int height, int maskOff,
+                             int maskScan, float ea) {
+        putMaskNative(drawable, gc, imageData, sx, sy, dx, dy,
+                      width, height, maskOff, maskScan, ea, MASK_XIMG);
+    }
+
+    private static native void putMaskNative(int drawable, long gc,
+                                             byte[] imageData,
+                                             int sx, int sy, int dx, int dy,
+                                             int width, int height,
+                                             int maskOff, int maskScan,
+                                             float ea, long xImg);
+
+    public void padBlit(byte op, int srcPict, int maskPict, int dstPict,
+                        AffineTransform maskTrx, int maskWidth, int maskHeight,
+                        int lastMaskWidth, int lastMaskHeight,
+                        int sx, int sy, int dx, int dy, int w, int h) {
+
+        padBlitNative(op, srcPict, maskPict, dstPict,
+                      XDoubleToFixed(maskTrx.getScaleX()),
+                      XDoubleToFixed(maskTrx.getShearX()),
+                      XDoubleToFixed(maskTrx.getTranslateX()),
+                      XDoubleToFixed(maskTrx.getShearY()),
+                      XDoubleToFixed(maskTrx.getScaleY()),
+                      XDoubleToFixed(maskTrx.getTranslateY()),
+                      maskWidth, maskHeight, lastMaskWidth, lastMaskHeight,
+                      sx, sy, dx, dy, w, h);
+    }
+
+    private static native void padBlitNative(byte op, int srcPict,
+                                             int maskPict, int dstPict,
+                                             int m00, int m01, int m02,
+                                             int m10, int m11, int m12,
+                                             int maskWidth, int maskHeight,
+                                             int lastMaskWidth,
+                                             int lastMaskHeight,
+                                             int sx, int sy, int dx, int dy,
+                                             int w, int h);
+
+    public void renderCompositeTrapezoids(byte op, int src, int maskFormat,
+                                          int dst, int srcX, int srcY,
+                                          TrapezoidList trapList) {
+        renderCompositeTrapezoidsNative(op, src, getFormatPtr(maskFormat),
+                                        dst, srcX, srcY,
+                                        trapList.getTrapArray());
+    }
+
+    private static native void
+        renderCompositeTrapezoidsNative(byte op, int src, long maskFormat,
+                                        int dst, int srcX, int srcY,
+                                        int[] trapezoids);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRColor.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import java.awt.*;
+
+/**
+ * XRender color class.
+ *
+ * @author Clemens Eisserer
+ */
+
+public class XRColor {
+    public static final XRColor FULL_ALPHA = new XRColor(0xffff, 0, 0, 0);
+    public static final XRColor NO_ALPHA = new XRColor(0, 0, 0, 0);
+
+    int red, green, blue, alpha;
+
+    public XRColor() {
+        red = 0;
+        green = 0;
+        blue = 0;
+        alpha = 0;
+    }
+
+    public XRColor(int alpha, int red, int green, int blue) {
+        this.alpha = alpha;
+        this.red = red;
+        this.green = green;
+        this.blue = blue;
+    }
+
+    public XRColor(Color color) {
+    }
+
+    public void setColorValues(Color color) {
+        alpha = byteToXRColorValue(color.getAlpha());
+
+        red = byteToXRColorValue(
+                      (int)(color.getRed() * color.getAlpha() / 255.0));
+        green = byteToXRColorValue(
+                      (int)(color.getGreen() * color.getAlpha() / 255.0));
+        blue = byteToXRColorValue(
+                      (int)(color.getBlue() * color.getAlpha() / 255.0));
+    }
+
+    public static int[] ARGBPrePixelToXRColors(int[] pixels) {
+        int[] colorValues = new int[pixels.length * 4];
+        XRColor c = new XRColor();
+
+        for (int i = 0; i < pixels.length; i++) {
+            c.setColorValues(pixels[i], true);
+            colorValues[i * 4 + 0] = c.alpha;
+            colorValues[i * 4 + 1] = c.red;
+            colorValues[i * 4 + 2] = c.green;
+            colorValues[i * 4 + 3] = c.blue;
+        }
+
+        return colorValues;
+    }
+
+    public void setColorValues(int pixel, boolean pre) {
+        long pix = XRUtils.intToULong(pixel);
+        alpha = (int) (((pix & 0xFF000000) >> 16) + 255);
+        red = (int) (((pix & 0x00FF0000) >> 8) + 255);
+        green = (int) (((pix & 0x0000FF00) >> 0) + 255);
+        blue = (int) (((pix & 0x000000FF) << 8) + 255);
+
+        if (alpha == 255) {
+            alpha = 0;
+        }
+
+        if (!pre) {
+            double alphaMult = XRUtils.XFixedToDouble(alpha);
+            this.red = (int) (red * alphaMult);
+            this.green = (int) (green * alphaMult);
+            this.blue = (int) (blue * alphaMult);
+        }
+    }
+
+    public static int byteToXRColorValue(int byteValue) {
+        int xrValue = 0;
+
+        if (byteValue != 0) {
+            if (byteValue == 255) {
+                xrValue = 0xffff;
+            } else {
+                xrValue = ((byteValue << 8) + 255);
+            }
+        }
+
+        return xrValue;
+    }
+
+    public String toString(){
+        return "A:"+alpha+"  R:"+red+"  G:"+green+" B:"+blue;
+    }
+
+    public void setAlpha(int alpha) {
+        this.alpha = alpha;
+    }
+
+    public int getAlpha() {
+        return alpha;
+    }
+
+    public int getRed() {
+        return red;
+    }
+
+    public int getGreen() {
+        return green;
+    }
+
+    public int getBlue() {
+        return blue;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,334 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+import sun.font.*;
+import sun.java2d.*;
+import sun.java2d.jules.*;
+import sun.java2d.loops.*;
+
+/**
+ * Manages per-application resources, e.g. the 1x1 pixmap used for solid color
+ * fill as well as per-application state e.g. the currently set source picture
+ * used for composition .
+ *
+ * @author Clemens Eisserer
+ */
+
+public class XRCompositeManager {
+    private static boolean enableGradCache = true;
+    private static XRCompositeManager instance;
+
+    XRSurfaceData src;
+    XRSurfaceData texture;
+    XRSurfaceData gradient;
+    int alphaMask = XRUtils.None;
+
+    XRColor solidColor = new XRColor();
+    float extraAlpha = 1.0f;
+    byte compRule = XRUtils.PictOpOver;
+    XRColor alphaColor = new XRColor();
+
+    XRSurfaceData solidSrcPict;
+    int alphaMaskPict;
+    int gradCachePixmap;
+    int gradCachePicture;
+
+    boolean xorEnabled = false;
+    int validatedPixel = 0;
+    Composite validatedComp;
+    Paint validatedPaint;
+    float validatedExtraAlpha = 1.0f;
+
+    XRBackend con;
+    MaskTileManager maskBuffer;
+    XRTextRenderer textRenderer;
+    XRMaskImage maskImage;
+
+    public static synchronized XRCompositeManager getInstance(
+            XRSurfaceData surface) {
+        if (instance == null) {
+            instance = new XRCompositeManager(surface);
+        }
+        return instance;
+    }
+
+    private XRCompositeManager(XRSurfaceData surface) {
+        con = new XRBackendNative();
+        // con = XRBackendJava.getInstance();
+
+        String gradProp = System.getProperty("sun.java2d.xrgradcache");
+        enableGradCache = gradProp == null ||
+                          !(gradProp.equalsIgnoreCase("false") ||
+                          gradProp.equalsIgnoreCase("f"));
+
+        XRPaints.register(this);
+
+        initResources(surface);
+
+        maskBuffer = new MaskTileManager(this, surface.getXid());
+        textRenderer = new XRTextRenderer(this);
+        maskImage = new XRMaskImage(this, surface.getXid());
+    }
+
+    public void initResources(XRSurfaceData surface) {
+        int parentXid = surface.getXid();
+
+        int solidPixmap = con.createPixmap(parentXid, 32, 1, 1);
+        int solidSrcPictXID = con.createPicture(solidPixmap,
+                XRUtils.PictStandardARGB32);
+        con.setPictureRepeat(solidSrcPictXID, XRUtils.RepeatNormal);
+        con.renderRectangle(solidSrcPictXID, XRUtils.PictOpSrc,
+                XRColor.FULL_ALPHA, 0, 0, 1, 1);
+        solidSrcPict = new XRSurfaceData.XRInternalSurfaceData(con,
+                solidSrcPictXID, null);
+        setForeground(0);
+
+        int extraAlphaMask = con.createPixmap(parentXid, 8, 1, 1);
+        alphaMaskPict = con.createPicture(extraAlphaMask,
+                XRUtils.PictStandardA8);
+        con.setPictureRepeat(alphaMaskPict, XRUtils.RepeatNormal);
+        con.renderRectangle(alphaMaskPict, XRUtils.PictOpClear,
+                XRColor.NO_ALPHA, 0, 0, 1, 1);
+
+        if (enableGradCache) {
+            gradCachePixmap = con.createPixmap(parentXid, 32,
+                    MaskTileManager.MASK_SIZE, MaskTileManager.MASK_SIZE);
+            gradCachePicture = con.createPicture(gradCachePixmap,
+                    XRUtils.PictStandardARGB32);
+        }
+    }
+
+    public void setForeground(int pixel) {
+        solidColor.setColorValues(pixel, false);
+        con.renderRectangle(solidSrcPict.picture, XRUtils.PictOpSrc,
+                solidColor, 0, 0, 1, 1);
+    }
+
+    public void setGradientPaint(XRSurfaceData gradient) {
+        if (this.gradient != null) {
+            con.freePicture(this.gradient.picture);
+        }
+        this.gradient = gradient;
+        src = gradient;
+    }
+
+    public void setTexturePaint(XRSurfaceData texture) {
+        this.texture = texture;
+        src = texture;
+    }
+
+    public void XRResetPaint() {
+        src = solidSrcPict;
+    }
+
+    public void validateCompositeState(Composite comp, AffineTransform xform,
+            Paint paint, SunGraphics2D sg2d) {
+        boolean updatePaint = (paint != validatedPaint) || paint == null;
+
+        // validate composite
+        if ((comp != validatedComp)) {
+            if (comp != null) {
+                setComposite(comp);
+            } else {
+                comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER);
+                setComposite(comp);
+            }
+            // the paint state is dependent on the composite state, so make
+            // sure we update the color below
+            updatePaint = true;
+            validatedComp = comp;
+        }
+
+        if (sg2d != null && validatedPixel != sg2d.pixel) {
+            validatedPixel = sg2d.pixel;
+            setForeground(validatedPixel);
+        }
+
+        // validate paint
+        if (updatePaint) {
+            if (paint != null && sg2d != null
+                    && sg2d.paintState >= SunGraphics2D.PAINT_GRADIENT) {
+                XRPaints.setPaint(sg2d, paint);
+            } else {
+                XRResetPaint();
+            }
+            validatedPaint = paint;
+        }
+
+        if (src != solidSrcPict) {
+            AffineTransform at = (AffineTransform) xform.clone();
+            try {
+                at.invert();
+            } catch (NoninvertibleTransformException e) {
+                at.setToIdentity();
+            }
+            src.validateAsSource(at, -1, -1);
+        }
+    }
+
+    private void setComposite(Composite comp) {
+        if (comp instanceof AlphaComposite) {
+            AlphaComposite aComp = (AlphaComposite) comp;
+            validatedExtraAlpha = aComp.getAlpha();
+
+            this.compRule = XRUtils.j2dAlphaCompToXR(aComp.getRule());
+            this.extraAlpha = validatedExtraAlpha;
+
+            if (extraAlpha == 1.0f) {
+                alphaMask = XRUtils.None;
+                alphaColor.alpha = XRColor.FULL_ALPHA.alpha;
+            } else {
+                alphaColor.alpha = XRColor
+                        .byteToXRColorValue((int) (extraAlpha * 255));
+                alphaMask = alphaMaskPict;
+                con.renderRectangle(alphaMaskPict, XRUtils.PictOpSrc,
+                        alphaColor, 0, 0, 1, 1);
+            }
+
+            xorEnabled = false;
+        } else if (comp instanceof XORComposite) {
+            /* XOR composite validation is handled in XRSurfaceData */
+            xorEnabled = true;
+        } else {
+            throw new InternalError(
+                    "Composite accaleration not implemented for: "
+                            + comp.getClass().getName());
+        }
+    }
+
+    public boolean maskRequired() {
+        return (!xorEnabled)
+                && ((src != solidSrcPict)
+                        || (src == solidSrcPict && solidColor.alpha != 0xffff) || (extraAlpha != 1.0f));
+    }
+
+    public void XRComposite(int src, int mask, int dst, int srcX, int srcY,
+            int maskX, int maskY, int dstX, int dstY, int width, int height) {
+        int cachedSrc = (src == XRUtils.None) ? this.src.picture : src;
+        int cachedX = srcX;
+        int cachedY = srcY;
+
+        if (enableGradCache && gradient != null
+                && cachedSrc == gradient.picture) {
+            con.renderComposite(XRUtils.PictOpSrc, gradient.picture,
+                    XRUtils.None, gradCachePicture, srcX, srcY, 0, 0, 0, 0,
+                    width, height);
+            cachedX = 0;
+            cachedY = 0;
+            cachedSrc = gradCachePicture;
+        }
+
+        con.renderComposite(compRule, cachedSrc, mask, dst, cachedX, cachedY,
+                maskX, maskY, dstX, dstY, width, height);
+    }
+
+    public void XRCompositeTraps(int dst, int srcX, int srcY,
+            TrapezoidList trapList) {
+        int renderReferenceX = 0;
+        int renderReferenceY = 0;
+
+        if (trapList.getP1YLeft(0) < trapList.getP2YLeft(0)) {
+            renderReferenceX = trapList.getP1XLeft(0);
+            renderReferenceY = trapList.getP1YLeft(0);
+        } else {
+            renderReferenceX = trapList.getP2XLeft(0);
+            renderReferenceY = trapList.getP2YLeft(0);
+        }
+
+        renderReferenceX = (int) Math.floor(XRUtils
+                .XFixedToDouble(renderReferenceX));
+        renderReferenceY = (int) Math.floor(XRUtils
+                .XFixedToDouble(renderReferenceY));
+
+        con.renderCompositeTrapezoids(compRule, src.picture,
+                XRUtils.PictStandardA8, dst, renderReferenceX,
+                renderReferenceY, trapList);
+    }
+
+    public void XRRenderRectangles(XRSurfaceData dst, GrowableRectArray rects) {
+        if (xorEnabled) {
+            con.GCRectangles(dst.getXid(), dst.getGC(), rects);
+        } else {
+            con.renderRectangles(dst.getPicture(), compRule, solidColor, rects);
+        }
+    }
+
+    public void compositeBlit(XRSurfaceData src, XRSurfaceData dst, int sx,
+            int sy, int dx, int dy, int w, int h) {
+        con.renderComposite(compRule, src.picture, alphaMask, dst.picture, sx,
+                sy, 0, 0, dx, dy, w, h);
+    }
+
+    public void compositeText(int dst, int glyphSet, int maskFormat,
+            GrowableEltArray elts) {
+        con.XRenderCompositeText(compRule, src.picture, dst, maskFormat, 0, 0,
+                0, 0, glyphSet, elts);
+    }
+
+    public XRColor getMaskColor() {
+        return !isTexturePaintActive() ? XRColor.FULL_ALPHA : getAlphaColor();
+    }
+
+    public int getExtraAlphaMask() {
+        return alphaMask;
+    }
+
+    public boolean isTexturePaintActive() {
+        return src == texture;
+    }
+
+    public XRColor getAlphaColor() {
+        return alphaColor;
+    }
+
+    public XRBackend getBackend() {
+        return con;
+    }
+
+    public float getExtraAlpha() {
+        return validatedExtraAlpha;
+    }
+
+    public byte getCompRule() {
+        return compRule;
+    }
+
+    public XRTextRenderer getTextRenderer() {
+        return textRenderer;
+    }
+
+    public MaskTileManager getMaskBuffer() {
+        return maskBuffer;
+    }
+
+    public XRMaskImage getMaskImage() {
+        return maskImage;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRDrawImage.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+import sun.java2d.*;
+import sun.java2d.loops.*;
+import sun.java2d.pipe.*;
+
+/**
+ * Class used for re-routing transformed blits to the accelerated loops.
+ */
+
+public class XRDrawImage extends DrawImage {
+    @Override
+    protected void renderImageXform(SunGraphics2D sg, Image img,
+            AffineTransform tx, int interpType, int sx1, int sy1, int sx2,
+            int sy2, Color bgColor) {
+        SurfaceData dstData = sg.surfaceData;
+        SurfaceData srcData = dstData.getSourceSurfaceData(img,
+                SunGraphics2D.TRANSFORM_GENERIC, sg.imageComp, bgColor);
+
+        if (srcData != null && !isBgOperation(srcData, bgColor))  { // TODO: Do we bail out on bgBlits?
+        //      && srcData instanceof XRSurfaceData) {
+            SurfaceType srcType = srcData.getSurfaceType();
+            SurfaceType dstType = dstData.getSurfaceType();
+
+            TransformBlit blit = TransformBlit.getFromCache(srcType,
+                    sg.imageComp, dstType);
+
+            if (blit != null) {
+                blit.Transform(srcData, dstData, sg.composite,
+                        sg.getCompClip(), tx, interpType, sx1, sy1, 0, 0, sx2
+                                - sx1, sy2 - sy1);
+                return;
+            }
+        }
+
+        super.renderImageXform(sg, img, tx, interpType, sx1, sy1, sx2, sy2,
+                bgColor);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRGraphicsConfig.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package sun.java2d.xr;
+
+import sun.awt.*;
+import sun.awt.image.*;
+import sun.java2d.*;
+
+public class XRGraphicsConfig extends X11GraphicsConfig implements
+        SurfaceManager.ProxiedGraphicsConfig {
+    private XRGraphicsConfig(X11GraphicsDevice device, int visualnum,
+            int depth, int colormap, boolean doubleBuffer) {
+        super(device, visualnum, depth, colormap, doubleBuffer);
+    }
+
+    public SurfaceData createSurfaceData(X11ComponentPeer peer) {
+        return XRSurfaceData.createData(peer);
+    }
+
+    public static XRGraphicsConfig getConfig(X11GraphicsDevice device,
+            int visualnum, int depth, int colormap, boolean doubleBuffer) {
+        if (!X11GraphicsEnvironment.isXRenderAvailable()) {
+            return null;
+        }
+
+        return new XRGraphicsConfig(device, visualnum, depth, colormap,
+                doubleBuffer);
+    }
+
+    public Object getProxyKey() {
+        return this;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRMaskBlit.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import static sun.java2d.loops.CompositeType.SrcNoEa;
+import static sun.java2d.loops.CompositeType.SrcOver;
+
+import java.awt.Composite;
+
+import sun.awt.*;
+import sun.java2d.*;
+import sun.java2d.loops.*;
+import sun.java2d.pipe.Region;
+
+/**
+ * For XRender there is no "blit", everything is just a fill with Repeat or Not.
+ * So basically this just quite the same as MaskFill.
+ *
+ * @author Clemens Eisserer
+ */
+public class XRMaskBlit extends MaskBlit {
+    static void register() {
+        GraphicsPrimitive[] primitives = {
+                new XRMaskBlit(XRSurfaceData.IntArgbPreX11, SrcOver,
+                               XRSurfaceData.IntArgbPreX11),
+                new XRMaskBlit(XRSurfaceData.IntRgbX11, SrcOver,
+                               XRSurfaceData.IntRgbX11),
+                new XRMaskBlit(XRSurfaceData.IntArgbPreX11, SrcNoEa,
+                               XRSurfaceData.IntRgbX11),
+                new XRMaskBlit(XRSurfaceData.IntRgbX11, SrcNoEa,
+                               XRSurfaceData.IntArgbPreX11)
+                };
+        GraphicsPrimitiveMgr.register(primitives);
+    }
+
+    public XRMaskBlit(SurfaceType srcType, CompositeType compType,
+            SurfaceType dstType) {
+        super(srcType, CompositeType.AnyAlpha, dstType);
+    }
+
+    protected native void maskBlit(long srcXsdo, long dstxsdo, int srcx,
+            int srcy, int dstx, int dsty, int w, int h, int maskoff,
+            int maskscan, int masklen, byte[] mask);
+
+    public void MaskBlit(SurfaceData src, SurfaceData dst, Composite comp,
+            Region clip, int srcx, int srcy, int dstx, int dsty, int width,
+            int height, byte[] mask, int maskoff, int maskscan) {
+        if (width <= 0 || height <= 0) {
+            return;
+        }
+
+        try {
+            SunToolkit.awtLock();
+
+            XRSurfaceData x11sd = (XRSurfaceData) src;
+            x11sd.validateAsSource(null, XRUtils.RepeatNone, XRUtils.FAST);
+
+            XRCompositeManager maskBuffer = x11sd.maskBuffer;
+            XRSurfaceData x11dst = (XRSurfaceData) dst;
+            x11dst.validateAsDestination(null, clip);
+
+            int maskPict = maskBuffer.getMaskBuffer().
+                         uploadMask(width, height, maskscan, maskoff, mask);
+            maskBuffer.XRComposite(x11sd.getPicture(), maskPict, x11sd.picture,
+                                  srcx, srcy, 0, 0, dstx, dsty, width, height);
+            maskBuffer.getMaskBuffer().clearUploadMask(maskPict, width, height);
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRMaskFill.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import static sun.java2d.loops.CompositeType.SrcNoEa;
+
+import static sun.java2d.loops.CompositeType.SrcOver;
+import static sun.java2d.loops.SurfaceType.AnyColor;
+import static sun.java2d.loops.SurfaceType.GradientPaint;
+import static sun.java2d.loops.SurfaceType.LinearGradientPaint;
+import static sun.java2d.loops.SurfaceType.OpaqueColor;
+import static sun.java2d.loops.SurfaceType.OpaqueGradientPaint;
+import static sun.java2d.loops.SurfaceType.OpaqueLinearGradientPaint;
+import static sun.java2d.loops.SurfaceType.OpaqueRadialGradientPaint;
+import static sun.java2d.loops.SurfaceType.OpaqueTexturePaint;
+import static sun.java2d.loops.SurfaceType.RadialGradientPaint;
+import static sun.java2d.loops.SurfaceType.TexturePaint;
+
+import java.awt.*;
+import sun.awt.*;
+import sun.java2d.*;
+import sun.java2d.loops.*;
+
+public class XRMaskFill extends MaskFill {
+    static void register() {
+        GraphicsPrimitive[] primitives = {
+                new XRMaskFill(AnyColor, SrcOver, XRSurfaceData.IntRgbX11),
+                new XRMaskFill(OpaqueColor, SrcNoEa, XRSurfaceData.IntRgbX11),
+                new XRMaskFill(GradientPaint, SrcOver, XRSurfaceData.IntRgbX11),
+                new XRMaskFill(OpaqueGradientPaint, SrcNoEa,
+                        XRSurfaceData.IntRgbX11),
+                new XRMaskFill(LinearGradientPaint, SrcOver,
+                        XRSurfaceData.IntRgbX11),
+                new XRMaskFill(OpaqueLinearGradientPaint, SrcNoEa,
+                        XRSurfaceData.IntRgbX11),
+                new XRMaskFill(RadialGradientPaint, SrcOver,
+                        XRSurfaceData.IntRgbX11),
+                new XRMaskFill(OpaqueRadialGradientPaint, SrcNoEa,
+                        XRSurfaceData.IntRgbX11),
+                new XRMaskFill(TexturePaint, SrcOver, XRSurfaceData.IntRgbX11),
+                new XRMaskFill(OpaqueTexturePaint, SrcNoEa,
+                        XRSurfaceData.IntRgbX11),
+
+                new XRMaskFill(AnyColor, SrcOver, XRSurfaceData.IntArgbPreX11),
+                new XRMaskFill(OpaqueColor, SrcNoEa, XRSurfaceData.IntArgbPreX11),
+                new XRMaskFill(GradientPaint, SrcOver, XRSurfaceData.IntArgbPreX11),
+                new XRMaskFill(OpaqueGradientPaint, SrcNoEa,
+                        XRSurfaceData.IntArgbPreX11),
+                new XRMaskFill(LinearGradientPaint, SrcOver,
+                        XRSurfaceData.IntArgbPreX11),
+                new XRMaskFill(OpaqueLinearGradientPaint, SrcNoEa,
+                        XRSurfaceData.IntArgbPreX11),
+                new XRMaskFill(RadialGradientPaint, SrcOver,
+                        XRSurfaceData.IntArgbPreX11),
+                new XRMaskFill(OpaqueRadialGradientPaint, SrcNoEa,
+                        XRSurfaceData.IntArgbPreX11),
+                new XRMaskFill(TexturePaint, SrcOver, XRSurfaceData.IntArgbPreX11),
+                new XRMaskFill(OpaqueTexturePaint, SrcNoEa,
+                        XRSurfaceData.IntArgbPreX11)
+                };
+
+        GraphicsPrimitiveMgr.register(primitives);
+    }
+
+    protected XRMaskFill(SurfaceType srcType, CompositeType compType,
+            SurfaceType surfaceType) {
+        super(srcType, compType, surfaceType);
+    }
+
+    protected native void maskFill(long xsdo, int x, int y, int w, int h,
+            int maskoff, int maskscan, int masklen, byte[] mask);
+
+    public void MaskFill(SunGraphics2D sg2d, SurfaceData sData, Composite comp,
+            final int x, final int y, final int w, final int h,
+            final byte[] mask, final int maskoff, final int maskscan) {
+        try {
+            SunToolkit.awtLock();
+
+            XRSurfaceData x11sd = (XRSurfaceData) sData;
+            x11sd.validateAsDestination(null, sg2d.getCompClip());
+
+            XRCompositeManager maskBuffer = x11sd.maskBuffer;
+            maskBuffer.validateCompositeState(comp, sg2d.transform, sg2d.paint, sg2d);
+
+            int maskPict = maskBuffer.getMaskBuffer().uploadMask(w, h, maskscan, maskoff, mask);
+            maskBuffer.XRComposite(XRUtils.None, maskPict, x11sd.picture, x, y, 0, 0, x, y, w, h);
+            maskBuffer.getMaskBuffer().clearUploadMask(maskPict, w, h);
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRMaskImage.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+/**
+ *  Management of mask used for some blit-types.
+ *
+ * @author Clemens Eisserer
+ */
+
+public class XRMaskImage {
+
+    private static final int MASK_SCALE_FACTOR = 8;
+
+    private static final int BLIT_MASK_SIZE = 8;
+
+    Dimension blitMaskDimensions = new Dimension(BLIT_MASK_SIZE, BLIT_MASK_SIZE);
+    int blitMaskPixmap;
+    int blitMaskPicture;
+    int lastMaskWidth = 0;
+    int lastMaskHeight = 0;
+    AffineTransform lastMaskTransform;
+
+    XRCompositeManager xrMgr;
+    XRBackend con;
+
+    public XRMaskImage(XRCompositeManager xrMgr, int parentDrawable) {
+        this.xrMgr = xrMgr;
+        this.con = xrMgr.getBackend();
+
+        initBlitMask(parentDrawable, BLIT_MASK_SIZE, BLIT_MASK_SIZE);
+    }
+
+
+    /**
+     * Prepares a mask used by a TransformedBlit, fills mask-contents and applies
+     * transformation.
+     */
+    public int prepareBlitMask(XRSurfaceData dst, AffineTransform maskTX, int width,
+            int height) {
+
+        int maskWidth = Math.max(width / MASK_SCALE_FACTOR, 1);
+        int maskHeight = Math.max(height / MASK_SCALE_FACTOR, 1);
+        maskTX.scale(((double) width) / maskWidth, ((double) height) / maskHeight);
+
+        try {
+            maskTX.invert();
+        } catch (NoninvertibleTransformException ex) {
+            maskTX.setToIdentity();
+        }
+
+        ensureBlitMaskSize(maskWidth, maskHeight);
+
+        if (lastMaskTransform == null || !lastMaskTransform.equals(maskTX)) {
+                con.setPictureTransform(blitMaskPicture, maskTX);
+                lastMaskTransform = maskTX;
+        }
+
+        if (lastMaskWidth != maskWidth || lastMaskHeight != maskHeight)  {
+            //Only clear mask, if previous mask area is larger than new one, otherwise simple overpaint it
+            if (lastMaskWidth > maskWidth || lastMaskHeight > maskHeight)  {
+                con.renderRectangle(blitMaskPicture, XRUtils.PictOpClear, XRColor.NO_ALPHA, 0, 0, lastMaskWidth, lastMaskHeight);
+            }
+
+            con.renderRectangle(blitMaskPicture, XRUtils.PictOpSrc, xrMgr.getAlphaColor(), 0, 0, maskWidth, maskHeight);
+        }
+
+        lastMaskWidth = maskWidth;
+        lastMaskHeight = maskHeight;
+
+        return blitMaskPicture;
+    }
+
+    private void initBlitMask(int parentDrawable, int width, int height) {
+        int newPM = con.createPixmap(parentDrawable, 8, width, height);
+        int newPict = con.createPicture(newPM, XRUtils.PictStandardA8);
+
+        /*Free old mask*/
+        if (blitMaskPixmap != 0) {
+            con.freePixmap(blitMaskPixmap);
+            con.freePicture(blitMaskPicture);
+        }
+
+        blitMaskPixmap = newPM;
+        blitMaskPicture = newPict;
+
+        con.renderRectangle(blitMaskPicture, XRUtils.PictOpClear, XRColor.NO_ALPHA, 0, 0, width, height);
+
+        blitMaskDimensions.width = width;
+        blitMaskDimensions.height = height;
+        lastMaskWidth = 0;
+        lastMaskHeight = 0;
+        lastMaskTransform = null;
+    }
+
+    private void ensureBlitMaskSize(int minSizeX, int minSizeY) {
+        if (minSizeX > blitMaskDimensions.width || minSizeY > blitMaskDimensions.height) {
+            int newWidth = Math.max(minSizeX, blitMaskDimensions.width);
+            int newHeight = Math.max(minSizeY, blitMaskDimensions.height);
+            initBlitMask(blitMaskPixmap, newWidth, newHeight);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRPMBlitLoops.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,400 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import sun.awt.SunToolkit;
+import sun.awt.image.*;
+import sun.java2d.loops.*;
+import sun.java2d.pipe.*;
+import sun.java2d.*;
+import java.awt.*;
+import java.awt.geom.*;
+import java.lang.ref.*;
+
+public class XRPMBlitLoops {
+
+    static WeakReference<SunVolatileImage> argbTmpPM = new WeakReference<SunVolatileImage>(null);
+    static WeakReference<SunVolatileImage> rgbTmpPM = new WeakReference<SunVolatileImage>(null);
+
+    public XRPMBlitLoops() {
+    }
+
+    public static void register() {
+        GraphicsPrimitive[] primitives = { new XRPMBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntRgbX11),
+                new XRPMBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntArgbPreX11),
+                new XRPMBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntRgbX11),
+                new XRPMBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntArgbPreX11),
+
+                new XRPMScaledBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntRgbX11),
+                new XRPMScaledBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntArgbPreX11),
+                new XRPMScaledBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntRgbX11),
+                new XRPMScaledBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntArgbPreX11),
+
+                new XRPMTransformedBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntRgbX11),
+                new XRPMTransformedBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntArgbPreX11),
+                new XRPMTransformedBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntRgbX11),
+                new XRPMTransformedBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntArgbPreX11),
+
+                /* SW -> Surface Blits */
+                new XrSwToPMBlit(SurfaceType.IntArgb, XRSurfaceData.IntRgbX11),
+                new XrSwToPMBlit(SurfaceType.IntRgb, XRSurfaceData.IntRgbX11),
+                new XrSwToPMBlit(SurfaceType.IntBgr, XRSurfaceData.IntRgbX11),
+                new XrSwToPMBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntRgbX11),
+                new XrSwToPMBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntRgbX11),
+                new XrSwToPMBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntRgbX11),
+                new XrSwToPMBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntRgbX11),
+
+                new XrSwToPMBlit(SurfaceType.IntArgb, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMBlit(SurfaceType.IntRgb, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMBlit(SurfaceType.IntBgr, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntArgbPreX11),
+
+                /* SW->Surface Scales */
+                new XrSwToPMScaledBlit(SurfaceType.IntArgb, XRSurfaceData.IntRgbX11),
+                new XrSwToPMScaledBlit(SurfaceType.IntRgb, XRSurfaceData.IntRgbX11),
+                new XrSwToPMScaledBlit(SurfaceType.IntBgr, XRSurfaceData.IntRgbX11),
+                new XrSwToPMScaledBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntRgbX11),
+                new XrSwToPMScaledBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntRgbX11),
+                new XrSwToPMScaledBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntRgbX11),
+                new XrSwToPMScaledBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntRgbX11),
+
+                new XrSwToPMScaledBlit(SurfaceType.IntArgb, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMScaledBlit(SurfaceType.IntRgb, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMScaledBlit(SurfaceType.IntBgr, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMScaledBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMScaledBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMScaledBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMScaledBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntArgbPreX11),
+
+                /* SW->Surface Transforms */
+                new XrSwToPMTransformedBlit(SurfaceType.IntArgb, XRSurfaceData.IntRgbX11),
+                new XrSwToPMTransformedBlit(SurfaceType.IntRgb, XRSurfaceData.IntRgbX11),
+                new XrSwToPMTransformedBlit(SurfaceType.IntBgr, XRSurfaceData.IntRgbX11),
+                new XrSwToPMTransformedBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntRgbX11),
+                new XrSwToPMTransformedBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntRgbX11),
+                new XrSwToPMTransformedBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntRgbX11),
+                new XrSwToPMTransformedBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntRgbX11),
+
+                new XrSwToPMTransformedBlit(SurfaceType.IntArgb, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMTransformedBlit(SurfaceType.IntRgb, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMTransformedBlit(SurfaceType.IntBgr, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMTransformedBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMTransformedBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMTransformedBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntArgbPreX11),
+                new XrSwToPMTransformedBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntArgbPreX11), };
+        GraphicsPrimitiveMgr.register(primitives);
+    }
+
+    /**
+     * Caches a SW surface using a temporary pixmap. The pixmap is held by a WeakReference,
+     *  allowing it to shrink again after some time.
+     */
+    protected static XRSurfaceData cacheToTmpSurface(SurfaceData src, XRSurfaceData dst, int w, int h, int sx, int sy) {
+        SunVolatileImage vImg;
+        SurfaceType vImgSurfaceType;
+
+        if (src.getTransparency() == Transparency.OPAQUE) {
+            vImg = rgbTmpPM.get();
+            vImgSurfaceType = SurfaceType.IntRgb;
+        } else {
+            vImg = argbTmpPM.get();
+            vImgSurfaceType = SurfaceType.IntArgbPre;
+        }
+
+        if (vImg == null || vImg.getWidth() < w || vImg.getHeight() < h) {
+            if (vImg != null) {
+                vImg.flush();
+            }
+            vImg = (SunVolatileImage) dst.getGraphicsConfig().createCompatibleVolatileImage(w, h, src.getTransparency());
+            vImg.setAccelerationPriority(1.0f);
+
+            if (src.getTransparency() == SurfaceData.OPAQUE) {
+                rgbTmpPM = new WeakReference<SunVolatileImage>(vImg);
+            } else {
+                argbTmpPM = new WeakReference<SunVolatileImage>(vImg);
+            }
+        }
+
+        Blit swToSurfaceBlit = Blit.getFromCache(src.getSurfaceType(), CompositeType.SrcNoEa, vImgSurfaceType);
+        XRSurfaceData vImgSurface = (XRSurfaceData) vImg.getDestSurface();
+        swToSurfaceBlit.Blit(src, vImgSurface, null, null, sx, sy, 0, 0, w, h);
+
+        return vImgSurface;
+    }
+}
+
+class XRPMBlit extends Blit {
+    public XRPMBlit(SurfaceType srcType, SurfaceType dstType) {
+        super(srcType, CompositeType.AnyAlpha, dstType);
+    }
+
+    public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) {
+        try {
+            SunToolkit.awtLock();
+
+            XRSurfaceData x11sdDst = (XRSurfaceData) dst;
+            x11sdDst.validateAsDestination(null, clip);
+            XRSurfaceData x11sdSrc = (XRSurfaceData) src;
+            x11sdSrc.validateAsSource(null, XRUtils.RepeatNone, XRUtils.FAST);
+
+            x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null);
+
+            x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, sx, sy, dx, dy, w, h);
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+}
+
+class XRPMScaledBlit extends ScaledBlit {
+    public XRPMScaledBlit(SurfaceType srcType, SurfaceType dstType) {
+        super(srcType, CompositeType.AnyAlpha, dstType);
+    }
+
+    /*
+     * TODO: This breaks scales with non-integer coordinates!?!?!
+     */
+    public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1,
+            double dx2, double dy2) {
+        try {
+            SunToolkit.awtLock();
+
+            XRSurfaceData x11sdDst = (XRSurfaceData) dst;
+            x11sdDst.validateAsDestination(null, clip);
+            XRSurfaceData x11sdSrc = (XRSurfaceData) src;
+            x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null);
+
+            double xScale = (dx2 - dx1) / (sx2 - sx1);
+            double yScale = (dy2 - dy1) / (sy2 - sy1);
+
+            sx1 *= xScale;
+            sx2 *= xScale;
+            sy1 *= yScale;
+            sy2 *= yScale;
+
+            AffineTransform xForm = AffineTransform.getScaleInstance(1 / xScale, 1 / yScale);
+
+            x11sdSrc.validateAsSource(xForm, XRUtils.RepeatNone, XRUtils.FAST); /*
+                                                                                 * TODO:
+                                                                                 * padded
+                                                                                 * blit
+                                                                                 * required
+                                                                                 * :
+                                                                                 * -
+                                                                                 * /
+                                                                                 * ?
+                                                                                 * ?
+                                                                                 */
+            x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, (int) sx1, (int) sy1, (int) dx1, (int) dy1, (int) (dx2 - dx1), (int) (dy2 - dy1));
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+}
+
+/**
+ * Called also if scale+transform is set
+ *
+ * @author Clemens Eisserer
+ */
+class XRPMTransformedBlit extends TransformBlit {
+
+    public XRPMTransformedBlit(SurfaceType srcType, SurfaceType dstType) {
+        super(srcType, CompositeType.AnyAlpha, dstType);
+    }
+
+    /*
+     * Calculates the composite-rectangle required for transformed blits. This
+     * method is functionally equal to: Shape shp =
+     * xform.createTransformedShape(rect); Rectangle bounds = shp.getBounds();
+     * but performs significantly better.
+     */
+    public Rectangle getCompositeBounds(AffineTransform tr, int dstx, int dsty, int width, int height) {
+        double[] compBounds = new double[8];
+        compBounds[0] = dstx;
+        compBounds[1] = dsty;
+        compBounds[2] = dstx + width;
+        compBounds[3] = dsty;
+        compBounds[4] = dstx + width;
+        compBounds[5] = dsty + height;
+        compBounds[6] = dstx;
+        compBounds[7] = dsty + height;
+
+        tr.transform(compBounds, 0, compBounds, 0, 4);
+
+        double minX = Math.min(compBounds[0], Math.min(compBounds[2], Math.min(compBounds[4], compBounds[6])));
+        double minY = Math.min(compBounds[1], Math.min(compBounds[3], Math.min(compBounds[5], compBounds[7])));
+        double maxX = Math.max(compBounds[0], Math.max(compBounds[2], Math.max(compBounds[4], compBounds[6])));
+        double maxY = Math.max(compBounds[1], Math.max(compBounds[3], Math.max(compBounds[5], compBounds[7])));
+
+        minX = Math.floor(minX);
+        minY = Math.floor(minY);
+        maxX = Math.ceil(maxX);
+        maxY = Math.ceil(maxY);
+
+        return new Rectangle((int) minX, (int) minY, (int) (maxX - minX), (int) (maxY - minY));
+    }
+
+    public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform xform, int hint, int srcx, int srcy,
+            int dstx, int dsty, int width, int height) {
+        try {
+            SunToolkit.awtLock();
+
+            int filter = XRUtils.ATransOpToXRQuality(hint);
+
+            XRSurfaceData x11sdDst = (XRSurfaceData) dst;
+            x11sdDst.validateAsDestination(null, clip);
+            XRSurfaceData x11sdSrc = (XRSurfaceData) src;
+            x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null);
+
+            Rectangle bounds = getCompositeBounds(xform, dstx, dsty, width, height);
+
+            AffineTransform trx = AffineTransform.getTranslateInstance((-bounds.x), (-bounds.y));
+            trx.concatenate(xform);
+            AffineTransform maskTX = (AffineTransform) trx.clone();
+
+            trx.translate(-srcx, -srcy);
+
+            try {
+                trx.invert();
+            } catch (NoninvertibleTransformException ex) {
+                trx.setToIdentity();
+                System.err.println("Reseted to identity!");
+            }
+
+            boolean omitMask = isMaskOmittable(trx, comp, filter);
+
+            if (!omitMask) {
+                XRMaskImage mask = x11sdSrc.maskBuffer.getMaskImage();
+
+                x11sdSrc.validateAsSource(trx, XRUtils.RepeatPad, filter);
+                int maskPicture = mask.prepareBlitMask(x11sdDst, maskTX, width, height);
+                x11sdDst.maskBuffer.con.renderComposite(XRCompositeManager.getInstance(x11sdSrc).getCompRule(), x11sdSrc.picture, maskPicture, x11sdDst.picture,
+                        0, 0, 0, 0, bounds.x, bounds.y, bounds.width, bounds.height);
+            } else {
+                int repeat = filter == XRUtils.FAST ? XRUtils.RepeatNone : XRUtils.RepeatPad;
+
+                x11sdSrc.validateAsSource(trx, repeat, filter);
+                x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, 0, 0, bounds.x, bounds.y, bounds.width, bounds.height);
+            }
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+
+    /* TODO: Is mask ever omitable??? ... should be for 90 degree rotation and no shear, but we always need to use RepeatPad */
+    protected static boolean isMaskOmittable(AffineTransform trx, Composite comp, int filter) {
+        return (filter == XRUtils.FAST || trx.getTranslateX() == (int) trx.getTranslateX() /*
+                                                                                            * If
+                                                                                            * translate
+                                                                                            * is
+                                                                                            * integer
+                                                                                            * only
+                                                                                            */
+                && trx.getTranslateY() == (int) trx.getTranslateY() && (trx.getShearX() == 0 && trx.getShearY() == 0 // Only
+                // 90 degree
+                // rotation
+                || trx.getShearX() == -trx.getShearY())) && ((AlphaComposite) comp).getAlpha() == 1.0f; // No
+        // ExtraAlpha!=1
+    }
+}
+
+class XrSwToPMBlit extends Blit {
+    Blit pmToSurfaceBlit;
+
+    XrSwToPMBlit(SurfaceType srcType, SurfaceType dstType) {
+        super(srcType, CompositeType.AnyAlpha, dstType);
+        pmToSurfaceBlit = new XRPMBlit(dstType, dstType);
+    }
+
+    public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) {
+        /*
+         * If the blit is write-only (putimge), no need for a temporary VI.
+         */
+        if (CompositeType.SrcOverNoEa.equals(comp) && (src.getTransparency() == Transparency.OPAQUE)) {
+            Blit opaqueSwToSurfaceBlit = Blit.getFromCache(src.getSurfaceType(), CompositeType.SrcNoEa, dst.getSurfaceType());
+            opaqueSwToSurfaceBlit.Blit(src, dst, comp, clip, sx, sy, dx, dy, w, h);
+        } else {
+            try {
+                SunToolkit.awtLock();
+
+                XRSurfaceData vImgSurface = XRPMBlitLoops.cacheToTmpSurface(src, (XRSurfaceData) dst, w, h, sx, sy);
+                pmToSurfaceBlit.Blit(vImgSurface, dst, comp, clip, 0, 0, dx, dy, w, h);
+            } finally {
+                SunToolkit.awtUnlock();
+            }
+        }
+    }
+}
+
+class XrSwToPMScaledBlit extends ScaledBlit {
+    ScaledBlit pmToSurfaceBlit;
+
+    XrSwToPMScaledBlit(SurfaceType srcType, SurfaceType dstType) {
+        super(srcType, CompositeType.AnyAlpha, dstType);
+        pmToSurfaceBlit = new XRPMScaledBlit(dstType, dstType);
+    }
+
+    public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1,
+            double dx2, double dy2) {
+        {
+            int w = sx2 - sx1;
+            int h = sy2 - sy1;
+
+            try {
+                SunToolkit.awtLock();
+                XRSurfaceData vImgSurface = XRPMBlitLoops.cacheToTmpSurface(src, (XRSurfaceData) dst, w, h, sx1, sy1);
+                pmToSurfaceBlit.Scale(vImgSurface, dst, comp, clip, 0, 0, w, h, dx1, dy1, dx2, dy2);
+            } finally {
+                SunToolkit.awtUnlock();
+            }
+        }
+    }
+}
+
+class XrSwToPMTransformedBlit extends TransformBlit {
+    TransformBlit pmToSurfaceBlit;
+
+    XrSwToPMTransformedBlit(SurfaceType srcType, SurfaceType dstType) {
+        super(srcType, CompositeType.AnyAlpha, dstType);
+        pmToSurfaceBlit = new XRPMTransformedBlit(dstType, dstType);
+    }
+
+    public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform xform, int hint, int sx, int sy, int dstx,
+            int dsty, int w, int h) {
+        try {
+            SunToolkit.awtLock();
+
+            XRSurfaceData vImgSurface = XRPMBlitLoops.cacheToTmpSurface(src, (XRSurfaceData) dst, w, h, sx, sy);
+            pmToSurfaceBlit.Transform(vImgSurface, dst, comp, clip, xform, hint, 0, 0, dstx, dsty, w, h);
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRPaints.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import java.awt.*;
+import java.awt.MultipleGradientPaint.*;
+import java.awt.geom.*;
+import java.awt.image.*;
+
+import sun.java2d.*;
+import sun.java2d.loops.*;
+import sun.java2d.pipe.*;
+
+abstract class XRPaints {
+    static XRCompositeManager xrCompMan;
+
+    static final XRGradient xrGradient = new XRGradient();
+    static final XRLinearGradient xrLinearGradient = new XRLinearGradient();
+    static final XRRadialGradient xrRadialGradient = new XRRadialGradient();
+    static final XRTexture xrTexture = new XRTexture();
+
+    public static void register(XRCompositeManager xrComp) {
+        xrCompMan = xrComp;
+    }
+
+    private static XRPaints getXRPaint(SunGraphics2D sg2d) {
+        switch (sg2d.paintState) {
+        case SunGraphics2D.PAINT_GRADIENT:
+            return xrGradient;
+
+        case SunGraphics2D.PAINT_LIN_GRADIENT:
+            return xrLinearGradient;
+
+        case SunGraphics2D.PAINT_RAD_GRADIENT:
+            return xrRadialGradient;
+
+        case SunGraphics2D.PAINT_TEXTURE:
+            return xrTexture;
+
+        default:
+            return null;
+        }
+    }
+
+    /**
+     * Attempts to locate an implementation corresponding to the paint state of
+     * the provided SunGraphics2D object. If no implementation can be found, or
+     * if the paint cannot be accelerated under the conditions of the
+     * SunGraphics2D, this method returns false; otherwise, returns true.
+     */
+    static boolean isValid(SunGraphics2D sg2d) {
+        XRPaints impl = getXRPaint(sg2d);
+        return (impl != null && impl.isPaintValid(sg2d));
+    }
+
+    static void setPaint(SunGraphics2D sg2d, Paint paint) {
+        XRPaints impl = getXRPaint(sg2d);
+        if (impl != null) {
+            impl.setXRPaint(sg2d, paint);
+        }
+    }
+
+    /**
+     * Returns true if this implementation is able to accelerate the Paint
+     * object associated with, and under the conditions of, the provided
+     * SunGraphics2D instance; otherwise returns false.
+     */
+    abstract boolean isPaintValid(SunGraphics2D sg2d);
+
+    abstract void setXRPaint(SunGraphics2D sg2d, Paint paint);
+
+    private static class XRGradient extends XRPaints {
+        private XRGradient() {
+        }
+
+        /**
+         * There are no restrictions for accelerating GradientPaint, so this
+         * method always returns true.
+         */
+        @Override
+        boolean isPaintValid(SunGraphics2D sg2d) {
+            return true;
+        }
+
+        void setXRPaint(SunGraphics2D sg2d, Paint pt) {
+            GradientPaint paint = (GradientPaint) pt;
+
+            int[] pixels = convertToIntArgbPixels(new Color[] { paint.getColor1(), paint.getColor2() }, false);
+
+            float fractions[] = new float[2];
+            fractions[0] = 0;
+            fractions[1] = 1;
+
+            Point2D pt1 = paint.getPoint1();
+            Point2D pt2 = paint.getPoint2();
+
+            AffineTransform at = (AffineTransform) sg2d.transform.clone();
+            try {
+                at.invert();
+            } catch (NoninvertibleTransformException ex) {
+                at.setToIdentity();
+            }
+
+            int repeat = paint.isCyclic() ? XRUtils.RepeatReflect : XRUtils.RepeatPad;
+
+            XRBackend con = xrCompMan.getBackend();
+            int gradient = con.createLinearGradient(pt1, pt2, fractions, pixels, repeat, at);
+            xrCompMan.setGradientPaint(new XRSurfaceData.XRInternalSurfaceData(con, gradient, at));
+        }
+    }
+
+    public int getGradientLength(Point2D pt1, Point2D pt2) {
+           double xDiff = Math.max(pt1.getX(), pt2.getX()) - Math.min(pt1.getX(), pt2.getX());
+           double yDiff = Math.max(pt1.getY(), pt2.getY()) - Math.min(pt1.getY(), pt2.getY());
+           return (int) Math.ceil(Math.sqrt(xDiff*xDiff + yDiff*yDiff));
+    }
+
+    private static class XRLinearGradient extends XRPaints {
+
+        @Override
+        boolean isPaintValid(SunGraphics2D sg2d) {
+            return true;
+        }
+
+        @Override
+        void setXRPaint(SunGraphics2D sg2d, Paint pt) {
+            LinearGradientPaint paint = (LinearGradientPaint) pt;
+            boolean linear = (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
+
+            Color[] colors = paint.getColors();
+            Point2D pt1 = paint.getStartPoint();
+            Point2D pt2 = paint.getEndPoint();
+
+
+            AffineTransform at = paint.getTransform();
+            at.preConcatenate(sg2d.transform);
+
+            int repeat = XRUtils.getRepeatForCycleMethod(paint.getCycleMethod());
+            float[] fractions = paint.getFractions();
+            int[] pixels = convertToIntArgbPixels(colors, linear);
+
+            try {
+                at.invert();
+            } catch (NoninvertibleTransformException ex) {
+                ex.printStackTrace();
+            }
+
+            XRBackend con = xrCompMan.getBackend();
+            int gradient = con.createLinearGradient(pt1, pt2, fractions, pixels, repeat, at);
+            xrCompMan.setGradientPaint(new XRSurfaceData.XRInternalSurfaceData(con, gradient, at));
+        }
+    }
+
+    private static class XRRadialGradient extends XRPaints {
+
+        @Override
+        boolean isPaintValid(SunGraphics2D sg2d) {
+            RadialGradientPaint grad = (RadialGradientPaint) sg2d.paint;
+            return grad.getFocusPoint().equals(grad.getCenterPoint());
+        }
+
+        @Override
+        void setXRPaint(SunGraphics2D sg2d, Paint pt) {
+            RadialGradientPaint paint = (RadialGradientPaint) pt;
+            boolean linear = (paint.getColorSpace() == ColorSpaceType.LINEAR_RGB);
+            Color[] colors = paint.getColors();
+            Point2D center = paint.getCenterPoint();
+            Point2D focus = paint.getFocusPoint();
+
+            int repeat = XRUtils.getRepeatForCycleMethod(paint.getCycleMethod());
+            float[] fractions = paint.getFractions();
+            int[] pixels = convertToIntArgbPixels(colors, linear);
+            float radius = paint.getRadius();
+
+            // save original (untransformed) center and focus points
+            double cx = center.getX();
+            double cy = center.getY();
+            double fx = focus.getX();
+            double fy = focus.getY();
+
+            AffineTransform at = paint.getTransform();
+            at.preConcatenate(sg2d.transform);
+            focus = at.transform(focus, focus);
+
+            // transform unit circle to gradient coords; we start with the
+            // unit circle (center=(0,0), focus on positive x-axis, radius=1)
+            // and then transform into gradient space
+            at.translate(cx, cy);
+            at.rotate(fx - cx, fy - cy);
+            // at.scale(radius, radius);
+
+            // invert to get mapping from device coords to unit circle
+            try {
+                at.invert();
+            } catch (Exception e) {
+                at.setToScale(0.0, 0.0);
+            }
+            focus = at.transform(focus, focus);
+
+            // clamp the focus point so that it does not rest on, or outside
+            // of, the circumference of the gradient circle
+            fx = Math.min(focus.getX(), 0.99);
+
+            XRBackend con = xrCompMan.getBackend();
+            int gradient = con.createRadialGradient(new Point2D.Float(0, 0), new Point2D.Float(0, 0), 0, radius, fractions, pixels, repeat, at);
+            xrCompMan.setGradientPaint(new XRSurfaceData.XRInternalSurfaceData(con, gradient, at));
+        }
+    }
+
+    private static class XRTexture extends XRPaints {
+
+        @Override
+        boolean isPaintValid(SunGraphics2D sg2d) {
+            TexturePaint paint = (TexturePaint) sg2d.paint;
+            BufferedImage bi = paint.getImage();
+            XRSurfaceData dstData = (XRSurfaceData) sg2d.getDestSurface();
+
+            SurfaceData srcData = dstData.getSourceSurfaceData(bi, SunGraphics2D.TRANSFORM_ISIDENT, CompositeType.SrcOver, null);
+            if (!(srcData instanceof XRSurfaceData)) {
+                // REMIND: this is a hack that attempts to cache the system
+                // memory image from the TexturePaint instance into an
+                // OpenGL texture...
+                srcData = dstData.getSourceSurfaceData(bi, SunGraphics2D.TRANSFORM_ISIDENT, CompositeType.SrcOver, null);
+                if (!(srcData instanceof XRSurfaceData)) {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        @Override
+        void setXRPaint(SunGraphics2D sg2d, Paint pt) {
+            TexturePaint paint = (TexturePaint) pt;
+
+            BufferedImage bi = paint.getImage();
+            SurfaceData dstData = sg2d.surfaceData;
+            SurfaceData srcData = dstData.getSourceSurfaceData(bi, SunGraphics2D.TRANSFORM_ISIDENT, CompositeType.SrcOver, null);
+
+            // REMIND: this hack tries to ensure that we have a cached texture
+            if (!(srcData instanceof XRSurfaceData)) {
+                srcData = dstData.getSourceSurfaceData(paint.getImage(), SunGraphics2D.TRANSFORM_ISIDENT, CompositeType.SrcOver, null);
+                if (!(srcData instanceof XRSurfaceData)) {
+                    throw new InternalError("Surface not cachable");
+                }
+            }
+
+            XRSurfaceData x11SrcData = (XRSurfaceData) srcData;
+
+            AffineTransform at = (AffineTransform) sg2d.transform.clone();
+            Rectangle2D anchor = paint.getAnchorRect();
+            at.translate(anchor.getX(), anchor.getY());
+            at.scale(anchor.getWidth() / ((double) bi.getWidth()), anchor.getHeight() / ((double) bi.getHeight()));
+
+            try {
+                at.invert();
+            } catch (NoninvertibleTransformException ex) {
+                at.setToIdentity(); /* TODO: Right thing to do in this case? */
+            }
+
+            x11SrcData.validateAsSource(at, XRUtils.RepeatNormal, XRUtils.ATransOpToXRQuality(sg2d.interpolationType));
+            xrCompMan.setTexturePaint(((XRSurfaceData) srcData));
+        }
+    }
+
+    public int[] convertToIntArgbPixels(Color[] colors, boolean linear) {
+        int[] pixels = new int[colors.length];
+        for (int i = 0; i < colors.length; i++) {
+            pixels[i] = colorToIntArgbPixel(colors[i], linear);
+        }
+        return pixels;
+    }
+
+    public int colorToIntArgbPixel(Color c, boolean linear) {
+        int rgb = c.getRGB();
+
+        int a = rgb >>> 24;
+        int r = (rgb >> 16) & 0xff;
+        int g = (rgb >> 8) & 0xff;
+        int b = (rgb) & 0xff;
+        if (linear) {
+            r = BufferedPaints.convertSRGBtoLinearRGB(r);
+            g = BufferedPaints.convertSRGBtoLinearRGB(g);
+            b = BufferedPaints.convertSRGBtoLinearRGB(b);
+        }
+
+        a *= xrCompMan.getExtraAlpha();
+
+        return ((a << 24) | (r << 16) | (g << 8) | (b));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRRenderer.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,331 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+import sun.awt.SunToolkit;
+import sun.java2d.SunGraphics2D;
+import sun.java2d.loops.*;
+import sun.java2d.pipe.Region;
+import sun.java2d.pipe.PixelDrawPipe;
+import sun.java2d.pipe.PixelFillPipe;
+import sun.java2d.pipe.ShapeDrawPipe;
+import sun.java2d.pipe.SpanIterator;
+import sun.java2d.pipe.ShapeSpanIterator;
+import sun.java2d.pipe.LoopPipe;
+
+/**
+ * XRender provides only accalerated rectangles. To emulate higher "order"
+ *  geometry we have to pass everything else to DoPath/FillSpans.
+ *
+ * TODO: DrawRect could be instrified
+ *
+ * @author Clemens Eisserer
+ */
+
+public class XRRenderer implements PixelDrawPipe, PixelFillPipe, ShapeDrawPipe {
+    XRDrawHandler drawHandler;
+    MaskTileManager tileManager;
+
+    public XRRenderer(MaskTileManager tileManager) {
+        this.tileManager = tileManager;
+        this.drawHandler = new XRDrawHandler();
+    }
+
+    /**
+     * Common validate method, used by all XRRender functions to validate the
+     * destination context.
+     */
+    private final void validateSurface(SunGraphics2D sg2d) {
+        XRSurfaceData xrsd = (XRSurfaceData) sg2d.surfaceData;
+        xrsd.validateAsDestination(sg2d, sg2d.getCompClip());
+        xrsd.maskBuffer.validateCompositeState(sg2d.composite, sg2d.transform,
+                                               sg2d.paint, sg2d);
+    }
+
+    public void drawLine(SunGraphics2D sg2d, int x1, int y1, int x2, int y2) {
+        try {
+            SunToolkit.awtLock();
+
+            validateSurface(sg2d);
+            int transx = sg2d.transX;
+            int transy = sg2d.transY;
+
+            XRSurfaceData xrsd = (XRSurfaceData) sg2d.surfaceData;
+
+            tileManager.addLine(x1 + transx, y1 + transy,
+                                x2 + transx, y2 + transy);
+            tileManager.fillMask(xrsd);
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+
+    public void drawRect(SunGraphics2D sg2d,
+                         int x, int y, int width, int height) {
+        draw(sg2d, new Rectangle2D.Float(x, y, width, height));
+    }
+
+    public void drawPolyline(SunGraphics2D sg2d,
+                             int xpoints[], int ypoints[], int npoints) {
+        Path2D.Float p2d = new Path2D.Float();
+        if (npoints > 1) {
+            p2d.moveTo(xpoints[0], ypoints[0]);
+            for (int i = 1; i < npoints; i++) {
+                p2d.lineTo(xpoints[i], ypoints[i]);
+            }
+        }
+
+        draw(sg2d, p2d);
+    }
+
+    public void drawPolygon(SunGraphics2D sg2d,
+                            int xpoints[], int ypoints[], int npoints) {
+        draw(sg2d, new Polygon(xpoints, ypoints, npoints));
+    }
+
+    public synchronized void fillRect(SunGraphics2D sg2d,
+                                      int x, int y, int width, int height) {
+        SunToolkit.awtLock();
+        try {
+            validateSurface(sg2d);
+
+            XRSurfaceData xrsd = (XRSurfaceData) sg2d.surfaceData;
+
+            x += sg2d.transform.getTranslateX();
+            y += sg2d.transform.getTranslateY();
+
+            tileManager.addRect(x, y, width, height);
+            tileManager.fillMask(xrsd);
+
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+
+    public void fillPolygon(SunGraphics2D sg2d,
+                            int xpoints[], int ypoints[], int npoints) {
+        fill(sg2d, new Polygon(xpoints, ypoints, npoints));
+    }
+
+    public void drawRoundRect(SunGraphics2D sg2d,
+                              int x, int y, int width, int height,
+                              int arcWidth, int arcHeight) {
+        draw(sg2d, new RoundRectangle2D.Float(x, y, width, height,
+                                              arcWidth, arcHeight));
+    }
+
+    public void fillRoundRect(SunGraphics2D sg2d, int x, int y,
+                              int width, int height,
+                              int arcWidth, int arcHeight) {
+        fill(sg2d, new RoundRectangle2D.Float(x, y, width, height,
+                                              arcWidth, arcHeight));
+    }
+
+    public void drawOval(SunGraphics2D sg2d,
+                         int x, int y, int width, int height) {
+        draw(sg2d, new Ellipse2D.Float(x, y, width, height));
+    }
+
+    public void fillOval(SunGraphics2D sg2d,
+                         int x, int y, int width, int height) {
+        fill(sg2d, new Ellipse2D.Float(x, y, width, height));
+    }
+
+    public void drawArc(SunGraphics2D sg2d,
+                       int x, int y, int width, int height,
+                        int startAngle, int arcAngle) {
+        draw(sg2d, new Arc2D.Float(x, y, width, height,
+                                   startAngle, arcAngle, Arc2D.OPEN));
+    }
+
+    public void fillArc(SunGraphics2D sg2d,
+                         int x, int y, int width, int height,
+                         int startAngle, int arcAngle) {
+        fill(sg2d, new Arc2D.Float(x, y, width, height,
+             startAngle, arcAngle, Arc2D.PIE));
+    }
+
+    private class XRDrawHandler extends ProcessPath.DrawHandler {
+
+        XRDrawHandler() {
+            // these are bogus values; the caller will use validate()
+            // to ensure that they are set properly prior to each usage
+            super(0, 0, 0, 0);
+        }
+
+        /**
+         * This method needs to be called prior to each draw/fillPath()
+         * operation to ensure the clip bounds are up to date.
+         */
+        void validate(SunGraphics2D sg2d) {
+            Region clip = sg2d.getCompClip();
+            setBounds(clip.getLoX(), clip.getLoY(),
+                      clip.getHiX(), clip.getHiY(), sg2d.strokeHint);
+            validateSurface(sg2d);
+        }
+
+        public void drawLine(int x1, int y1, int x2, int y2) {
+            tileManager.addLine(x1, y1, x2, y2);
+        }
+
+        public void drawPixel(int x, int y) {
+            tileManager.addRect(x, y, 1, 1);
+        }
+
+        public void drawScanline(int x1, int x2, int y) {
+            tileManager.addRect(x1, y, x2 - x1 + 1, 1);
+        }
+    }
+
+    protected void drawPath(SunGraphics2D sg2d, Path2D.Float p2df,
+                            int transx, int transy) {
+        SunToolkit.awtLock();
+        try {
+            validateSurface(sg2d);
+            drawHandler.validate(sg2d);
+            ProcessPath.drawPath(drawHandler, p2df, transx, transy);
+            tileManager.fillMask(((XRSurfaceData) sg2d.surfaceData));
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+
+    protected void fillPath(SunGraphics2D sg2d, Path2D.Float p2df,
+                            int transx, int transy) {
+        SunToolkit.awtLock();
+        try {
+            validateSurface(sg2d);
+            drawHandler.validate(sg2d);
+            ProcessPath.fillPath(drawHandler, p2df, transx, transy);
+            tileManager.fillMask(((XRSurfaceData) sg2d.surfaceData));
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+
+    protected void fillSpans(SunGraphics2D sg2d, SpanIterator si,
+                             int transx, int transy) {
+        SunToolkit.awtLock();
+        try {
+            validateSurface(sg2d);
+            int[] spanBox = new int[4];
+            while (si.nextSpan(spanBox)) {
+                tileManager.addRect(spanBox[0] + transx,
+                                    spanBox[1] + transy,
+                                    spanBox[2] - spanBox[0],
+                                    spanBox[3] - spanBox[1]);
+            }
+            tileManager.fillMask(((XRSurfaceData) sg2d.surfaceData));
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+
+    public void draw(SunGraphics2D sg2d, Shape s) {
+        if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) {
+            Path2D.Float p2df;
+            int transx, transy;
+            if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) {
+                if (s instanceof Path2D.Float) {
+                    p2df = (Path2D.Float) s;
+                } else {
+                    p2df = new Path2D.Float(s);
+                }
+                transx = sg2d.transX;
+                transy = sg2d.transY;
+            } else {
+                p2df = new Path2D.Float(s, sg2d.transform);
+                transx = 0;
+                transy = 0;
+            }
+            drawPath(sg2d, p2df, transx, transy);
+        } else if (sg2d.strokeState < SunGraphics2D.STROKE_CUSTOM) {
+            ShapeSpanIterator si = LoopPipe.getStrokeSpans(sg2d, s);
+            try {
+                fillSpans(sg2d, si, 0, 0);
+            } finally {
+                si.dispose();
+            }
+        } else {
+            fill(sg2d, sg2d.stroke.createStrokedShape(s));
+        }
+    }
+
+    public void fill(SunGraphics2D sg2d, Shape s) {
+        int transx, transy;
+
+        if (sg2d.strokeState == SunGraphics2D.STROKE_THIN) {
+            // Here we are able to use fillPath() for
+            // high-quality fills.
+            Path2D.Float p2df;
+            if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) {
+                if (s instanceof Path2D.Float) {
+                    p2df = (Path2D.Float) s;
+                } else {
+                    p2df = new Path2D.Float(s);
+                }
+                transx = sg2d.transX;
+                transy = sg2d.transY;
+            } else {
+                p2df = new Path2D.Float(s, sg2d.transform);
+                transx = 0;
+                transy = 0;
+            }
+            fillPath(sg2d, p2df, transx, transy);
+            return;
+        }
+
+        AffineTransform at;
+        if (sg2d.transformState <= SunGraphics2D.TRANSFORM_INT_TRANSLATE) {
+            // Transform (translation) will be done by FillSpans
+            at = null;
+            transx = sg2d.transX;
+            transy = sg2d.transY;
+        } else {
+            // Transform will be done by the PathIterator
+            at = sg2d.transform;
+            transx = transy = 0;
+        }
+
+        ShapeSpanIterator ssi = LoopPipe.getFillSSI(sg2d);
+        try {
+            // Subtract transx/y from the SSI clip to match the
+            // (potentially untranslated) geometry fed to it
+            Region clip = sg2d.getCompClip();
+            ssi.setOutputAreaXYXY(clip.getLoX() - transx,
+                                  clip.getLoY() - transy,
+                                  clip.getHiX() - transx,
+                                  clip.getHiY() - transy);
+            ssi.appendPath(s.getPathIterator(at));
+            fillSpans(sg2d, ssi, transx, transy);
+        } finally {
+            ssi.dispose();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,668 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import java.awt.*;
+import java.awt.geom.*;
+import java.awt.image.*;
+import sun.awt.*;
+import sun.java2d.InvalidPipeException;
+import sun.java2d.SunGraphics2D;
+import sun.java2d.SurfaceData;
+import sun.java2d.SurfaceDataProxy;
+import sun.java2d.jules.*;
+import sun.java2d.loops.*;
+import sun.java2d.pipe.*;
+import sun.java2d.x11.*;
+import sun.font.FontManagerNativeLibrary;
+
+public abstract class XRSurfaceData extends XSurfaceData {
+    X11ComponentPeer peer;
+    XRGraphicsConfig graphicsConfig;
+    XRBackend renderQueue;
+
+    private RenderLoops solidloops;
+
+    protected int depth;
+
+    private static native void initIDs();
+
+    protected native void XRInitSurface(int depth, int width, int height,
+                                        long drawable, int pictFormat);
+
+    native void initXRPicture(long xsdo, int pictForm);
+
+    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";
+
+    public static final SurfaceType
+        ByteA8X11 = SurfaceType.ByteGray.deriveSubType(DESC_BYTE_A8_X11);
+    public static final SurfaceType
+        IntRgbX11 = SurfaceType.IntRgb.deriveSubType(DESC_INT_RGB_X11);
+    public static final SurfaceType
+        IntArgbPreX11 = SurfaceType.IntArgbPre.deriveSubType(DESC_INT_ARGB_X11);
+
+    public Raster getRaster(int x, int y, int w, int h) {
+        throw new InternalError("not implemented yet");
+    }
+
+    protected XRRenderer xrpipe;
+    protected PixelToShapeConverter xrtxpipe;
+    protected TextPipe xrtextpipe;
+    protected XRDrawImage xrDrawImage;
+
+    protected ShapeDrawPipe aaShapePipe;
+    protected PixelToShapeConverter aaPixelToShapeConv;
+
+    public static void initXRSurfaceData() {
+        if (!isX11SurfaceDataInitialized()) {
+            FontManagerNativeLibrary.load();
+            initIDs();
+            XRPMBlitLoops.register();
+            XRMaskFill.register();
+            XRMaskBlit.register();
+
+            setX11SurfaceDataInitialized();
+        }
+    }
+
+    /**
+     * Synchronized accessor method for isDrawableValid.
+     */
+    protected boolean isXRDrawableValid() {
+        try {
+            SunToolkit.awtLock();
+            return isDrawableValid();
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+
+    @Override
+    public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {
+        return XRSurfaceDataProxy.createProxy(srcData, graphicsConfig);
+    }
+
+    public void validatePipe(SunGraphics2D sg2d) {
+        TextPipe textpipe;
+        boolean validated = false;
+
+        /*
+         * The textpipe for now can't handle TexturePaint when extra-alpha is
+         * specified nore XOR mode
+         */
+        if (sg2d.compositeState < SunGraphics2D.COMP_XOR &&
+            (sg2d.paintState < SunGraphics2D.PAINT_TEXTURE ||
+             sg2d.composite == null ||
+             !(sg2d.composite instanceof AlphaComposite) ||
+             ((AlphaComposite) sg2d.composite).getAlpha() == 1.0f))
+        {
+            textpipe = xrtextpipe;
+        } else {
+            super.validatePipe(sg2d);
+            textpipe = sg2d.textpipe;
+            validated = true;
+        }
+
+        PixelToShapeConverter txPipe = null;
+        XRRenderer nonTxPipe = null;
+
+        /*
+         * TODO: Can we rely on the GC for ARGB32 surfaces?
+         */
+        if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) {
+            if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) {
+                if (sg2d.compositeState <= SunGraphics2D.COMP_XOR) {
+                    txPipe = xrtxpipe;
+                    nonTxPipe = xrpipe;
+                }
+            } else if (sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) {
+                if (XRPaints.isValid(sg2d)) {
+                    txPipe = xrtxpipe;
+                    nonTxPipe = xrpipe;
+                }
+                // custom paints handled by super.validatePipe() below
+            }
+        }
+
+        if (sg2d.antialiasHint == SunHints.INTVAL_ANTIALIAS_ON &&
+            JulesPathBuf.isCairoAvailable())
+        {
+            sg2d.shapepipe = aaShapePipe;
+            sg2d.drawpipe = aaPixelToShapeConv;
+            sg2d.fillpipe = aaPixelToShapeConv;
+        } else {
+            if (txPipe != null) {
+                if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {
+                    sg2d.drawpipe = txPipe;
+                    sg2d.fillpipe = txPipe;
+                } else if (sg2d.strokeState != SunGraphics2D.STROKE_THIN) {
+                    sg2d.drawpipe = txPipe;
+                    sg2d.fillpipe = nonTxPipe;
+                } else {
+                    sg2d.drawpipe = nonTxPipe;
+                    sg2d.fillpipe = nonTxPipe;
+                }
+                sg2d.shapepipe = nonTxPipe;
+            } else {
+                if (!validated) {
+                    super.validatePipe(sg2d);
+                }
+            }
+        }
+
+        // install the text pipe based on our earlier decision
+        sg2d.textpipe = textpipe;
+
+        // always override the image pipe with the specialized XRender pipe
+        sg2d.imagepipe = xrDrawImage;
+    }
+
+    protected MaskFill getMaskFill(SunGraphics2D sg2d) {
+        if (sg2d.paintState > SunGraphics2D.PAINT_ALPHACOLOR &&
+            !XRPaints.isValid(sg2d))
+        {
+            return null;
+        }
+        return super.getMaskFill(sg2d);
+    }
+
+    public RenderLoops getRenderLoops(SunGraphics2D sg2d) {
+        if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&
+            sg2d.compositeState <= SunGraphics2D.COMP_ALPHA)
+        {
+            return solidloops;
+        }
+
+        return super.getRenderLoops(sg2d);
+    }
+
+    public GraphicsConfiguration getDeviceConfiguration() {
+        return graphicsConfig;
+    }
+
+    /**
+     * Method for instantiating a Window SurfaceData
+     */
+    public static XRWindowSurfaceData createData(X11ComponentPeer peer) {
+        XRGraphicsConfig gc = getGC(peer);
+        return new XRWindowSurfaceData(peer, gc, gc.getSurfaceType());
+    }
+
+    /**
+     * Method for instantiating a Pixmap SurfaceData (offscreen).
+     * If the surface * is opaque a 24-bit/RGB surface is chosen,
+     * otherwise a 32-bit ARGB surface.
+     */
+    public static XRPixmapSurfaceData createData(XRGraphicsConfig gc,
+                                                 int width, int height,
+                                                 ColorModel cm, Image image,
+                                                 long drawable,
+                                                 int transparency) {
+        int depth = transparency > Transparency.OPAQUE ? 32 : 24;
+        if (depth == 24) {
+            cm = new DirectColorModel(depth,
+                                      0x00FF0000, 0x0000FF00, 0x000000FF);
+        } else {
+            cm = new DirectColorModel(depth, 0x00FF0000, 0x0000FF00,
+                                      0x000000FF, 0xFF000000);
+        }
+
+        return new XRPixmapSurfaceData
+            (gc, width, height, image, getSurfaceType(gc, transparency),
+             cm, drawable, transparency,
+             XRUtils.getPictureFormatForTransparency(transparency), depth);
+    }
+
+    protected XRSurfaceData(X11ComponentPeer peer, XRGraphicsConfig gc,
+        SurfaceType sType, ColorModel cm, int depth, int transparency)
+    {
+        super(sType, cm);
+        this.peer = peer;
+        this.graphicsConfig = gc;
+        this.solidloops = graphicsConfig.getSolidLoops(sType);
+        this.depth = depth;
+        initOps(peer, graphicsConfig, depth);
+
+        setBlitProxyKey(gc.getProxyKey());
+    }
+
+    protected XRSurfaceData(XRBackend renderQueue) {
+        super(XRSurfaceData.IntRgbX11,
+              new DirectColorModel(24, 0x00FF0000, 0x0000FF00, 0x000000FF));
+        this.renderQueue = renderQueue;
+    }
+
+    /**
+     * Inits the XRender-data-structures which belong to the XRSurfaceData.
+     *
+     * @param pictureFormat
+     */
+    public void initXRender(int pictureFormat) {
+        try {
+            SunToolkit.awtLock();
+            initXRPicture(getNativeOps(), pictureFormat);
+            renderQueue = XRCompositeManager.getInstance(this).getBackend();
+            maskBuffer = XRCompositeManager.getInstance(this);
+        } catch (Throwable ex) {
+            ex.printStackTrace();
+        } finally {
+            SunToolkit.awtUnlock();
+        }
+    }
+
+    public static XRGraphicsConfig getGC(X11ComponentPeer peer) {
+        if (peer != null) {
+            return (XRGraphicsConfig) peer.getGraphicsConfiguration();
+        } else {
+            GraphicsEnvironment env =
+                GraphicsEnvironment.getLocalGraphicsEnvironment();
+            GraphicsDevice gd = env.getDefaultScreenDevice();
+            return (XRGraphicsConfig) gd.getDefaultConfiguration();
+        }
+    }
+
+    /**
+     * Returns a boolean indicating whether or not a copyArea from the given
+     * rectangle source coordinates might be incomplete and result in X11
+     * GraphicsExposure events being generated from XCopyArea. This method
+     * allows the SurfaceData copyArea method to determine if it needs to set
+     * the GraphicsExposures attribute of the X11 GC to True or False to receive
+     * or avoid the events.
+     *
+     * @return true if there is any chance that an XCopyArea from the given
+     *         source coordinates could produce any X11 Exposure events.
+     */
+    public abstract boolean canSourceSendExposures(int x, int y, int w, int h);
+
+    /**
+     * CopyArea is implemented using the "old" X11 GC, therefor clip and
+     * needExposures have to be validated against that GC. Pictures and GCs
+     * don't share state.
+     */
+    public void validateCopyAreaGC(Region gcClip, boolean needExposures) {
+        if (validatedGCClip != gcClip) {
+            if (gcClip != null)
+                renderQueue.setGCClipRectangles(xgc, gcClip);
+            validatedGCClip = gcClip;
+        }
+
+        if (validatedExposures != needExposures) {
+            validatedExposures = needExposures;
+            renderQueue.setGCExposures(xgc, needExposures);
+        }
+
+        if (validatedXorComp != null) {
+            renderQueue.setGCMode(xgc, true);
+            renderQueue.setGCForeground(xgc, validatedGCForegroundPixel);
+            validatedXorComp = null;
+        }
+    }
+
+    public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h,
+                            int dx, int dy) {
+        if (xrpipe == null) {
+            if (!isXRDrawableValid()) {
+                return true;
+            }
+            makePipes();
+        }
+        CompositeType comptype = sg2d.imageComp;
+        if (sg2d.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE &&
+            (CompositeType.SrcOverNoEa.equals(comptype) ||
+             CompositeType.SrcNoEa.equals(comptype)))
+        {
+            x += sg2d.transX;
+            y += sg2d.transY;
+            try {
+                SunToolkit.awtLock();
+                boolean needExposures = canSourceSendExposures(x, y, w, h);
+                validateCopyAreaGC(sg2d.getCompClip(), needExposures);
+                renderQueue.copyArea(xid, xid, xgc, x, y, w, h, x + dx, y + dy);
+            } finally {
+                SunToolkit.awtUnlock();
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns the XRender SurfaceType which is able to fullfill the specified
+     * transparency requirement.
+     */
+    public static SurfaceType getSurfaceType(XRGraphicsConfig gc,
+                                             int transparency) {
+        SurfaceType sType = null;
+
+        switch (transparency) {
+        case Transparency.OPAQUE:
+            sType = XRSurfaceData.IntRgbX11;
+            break;
+
+        case Transparency.BITMASK:
+        case Transparency.TRANSLUCENT:
+            sType = XRSurfaceData.IntArgbPreX11;
+            break;
+        }
+
+        return sType;
+    }
+
+    public void invalidate() {
+        if (isValid()) {
+            setInvalid();
+            super.invalidate();
+        }
+    }
+
+    private long xgc; // GC is still used for copyArea
+    private int validatedGCForegroundPixel = 0;
+    private XORComposite validatedXorComp;
+    private int xid;
+    public int picture;
+    public XRCompositeManager maskBuffer;
+
+    private Region validatedClip;
+    private Region validatedGCClip;
+    private boolean validatedExposures = true;
+
+    boolean transformInUse = false;
+    AffineTransform validatedSourceTransform = new AffineTransform();
+    int validatedRepeat = XRUtils.RepeatNone;
+    int validatedFilter = XRUtils.FAST;
+
+    /**
+     * Validates an XRSurfaceData when used as source. Note that the clip is
+     * applied when used as source as well as destination.
+     */
+    void validateAsSource(AffineTransform sxForm, int repeat, int filter) {
+
+        if (validatedClip != null) {
+            validatedClip = null;
+            renderQueue.setClipRectangles(picture, null);
+        }
+
+        if (validatedRepeat != repeat && repeat != -1) {
+            validatedRepeat = repeat;
+            renderQueue.setPictureRepeat(picture, repeat);
+        }
+
+        if (sxForm == null) {
+            if (transformInUse) {
+                validatedSourceTransform.setToIdentity();
+                renderQueue.setPictureTransform(picture,
+                                                validatedSourceTransform);
+                transformInUse = false;
+            }
+        } else if (!transformInUse ||
+                   (transformInUse && !sxForm.equals(validatedSourceTransform))) {
+            validatedSourceTransform.setTransform(sxForm.getScaleX(),
+                                                  sxForm.getShearY(),
+                                                  sxForm.getShearX(),
+                                                  sxForm.getScaleY(),
+                                                  sxForm.getTranslateX(),
+                                                  sxForm.getTranslateY());
+            renderQueue.setPictureTransform(picture, validatedSourceTransform);
+            transformInUse = true;
+        }
+
+        if (filter != validatedFilter && filter != -1) {
+            renderQueue.setFilter(picture, filter);
+            validatedFilter = filter;
+        }
+    }
+
+    /**
+     * Validates the Surface when used as destination.
+     */
+    public void validateAsDestination(SunGraphics2D sg2d, Region clip) {
+        if (!isValid()) {
+            throw new InvalidPipeException("bounds changed");
+        }
+
+        boolean updateGCClip = false;
+        if (clip != validatedClip) {
+            renderQueue.setClipRectangles(picture, clip);
+            validatedClip = clip;
+            updateGCClip = true;
+        }
+
+        if (sg2d != null && sg2d.compositeState == SunGraphics2D.COMP_XOR) {
+            if (validatedXorComp != sg2d.getComposite()) {
+                validatedXorComp = (XORComposite) sg2d.getComposite();
+                int xorpixelmod = validatedXorComp.getXorPixel();
+                renderQueue.setGCMode(xgc, false);
+
+                // validate pixel
+                int pixel = sg2d.pixel;
+                if (validatedGCForegroundPixel != pixel) {
+                    renderQueue.setGCForeground(xgc, pixel ^ xorpixelmod);
+                    validatedGCForegroundPixel = pixel;
+                }
+            }
+
+            if (updateGCClip) {
+                renderQueue.setGCClipRectangles(xgc, clip);
+            }
+        }
+    }
+
+    public synchronized void makePipes() { /*
+                                            * TODO: Why is this synchronized,
+                                            * but access not?
+                                            */
+        if (xrpipe == null) {
+            try {
+                SunToolkit.awtLock();
+                xgc = renderQueue.createGC(xid); // TODO: GC leak? where to
+                // clean up?
+
+                xrpipe = new XRRenderer(maskBuffer.getMaskBuffer());
+                xrtxpipe = new PixelToShapeConverter(xrpipe);
+                xrtextpipe = maskBuffer.getTextRenderer();
+                xrDrawImage = new XRDrawImage();
+
+                if (JulesPathBuf.isCairoAvailable()) {
+                    aaShapePipe =
+                       new JulesShapePipe(XRCompositeManager.getInstance(this));
+                    aaPixelToShapeConv = new PixelToShapeConverter(aaShapePipe);
+                }
+            } finally {
+                SunToolkit.awtUnlock();
+            }
+        }
+    }
+
+    public static class XRWindowSurfaceData extends XRSurfaceData {
+        public XRWindowSurfaceData(X11ComponentPeer peer,
+                                   XRGraphicsConfig gc, SurfaceType sType) {
+            super(peer, gc, sType, peer.getColorModel(),
+                  peer.getColorModel().getPixelSize(), Transparency.OPAQUE);
+
+            if (isXRDrawableValid()) {
+                initXRender(XRUtils.
+                    getPictureFormatForTransparency(Transparency.OPAQUE));
+                makePipes();
+            }
+        }
+
+        public SurfaceData getReplacement() {
+            return peer.getSurfaceData();
+        }
+
+        public Rectangle getBounds() {
+            Rectangle r = peer.getBounds();
+            r.x = r.y = 0;
+            return r;
+        }
+
+        @Override
+        public boolean canSourceSendExposures(int x, int y, int w, int h) {
+            return true;
+        }
+
+        /**
+         * Returns destination Component associated with this SurfaceData.
+         */
+        public Object getDestination() {
+            return peer.getTarget();
+        }
+    }
+
+    public static class XRInternalSurfaceData extends XRSurfaceData {
+        public XRInternalSurfaceData(XRBackend renderQueue, int pictXid,
+                                     AffineTransform transform) {
+          super(renderQueue);
+          this.picture = pictXid;
+          this.validatedSourceTransform = transform;
+
+          if (validatedSourceTransform != null) {
+              transformInUse = true;
+          }
+        }
+
+        public boolean canSourceSendExposures(int x, int y, int w, int h) {
+            return false;
+        }
+
+        public Rectangle getBounds() {
+            return null;
+        }
+
+        public Object getDestination() {
+            return null;
+        }
+
+        public SurfaceData getReplacement() {
+            return null;
+        }
+    }
+
+    public static class XRPixmapSurfaceData extends XRSurfaceData {
+        Image offscreenImage;
+        int width;
+        int height;
+        int transparency;
+
+        public XRPixmapSurfaceData(XRGraphicsConfig gc, int width, int height,
+                                   Image image, SurfaceType sType,
+                                   ColorModel cm, long drawable,
+                                   int transparency, int pictFormat,
+                                   int depth) {
+            super(null, gc, sType, cm, depth, transparency);
+            this.width = width;
+            this.height = height;
+            offscreenImage = image;
+            this.transparency = transparency;
+            initSurface(depth, width, height, drawable, pictFormat);
+
+            initXRender(pictFormat);
+            makePipes();
+        }
+
+        public void initSurface(int depth, int width, int height,
+                                long drawable, int pictFormat) {
+            try {
+                SunToolkit.awtLock();
+                XRInitSurface(depth, width, height, drawable, pictFormat);
+            } finally {
+                SunToolkit.awtUnlock();
+            }
+        }
+
+        public SurfaceData getReplacement() {
+            return restoreContents(offscreenImage);
+        }
+
+        /**
+         * Need this since the surface data is created with the color model of
+         * the target GC, which is always opaque. But in SunGraphics2D.blitSD we
+         * choose loops based on the transparency on the source SD, so it could
+         * choose wrong loop (blit instead of blitbg, for example).
+         */
+        public int getTransparency() {
+            return transparency;
+        }
+
+        public Rectangle getBounds() {
+            return new Rectangle(width, height);
+        }
+
+        @Override
+        public boolean canSourceSendExposures(int x, int y, int w, int h) {
+            return (x < 0 || y < 0 || (x + w) > width || (y + h) > height);
+        }
+
+        public void flush() {
+            /*
+             * We need to invalidate the surface before disposing the native
+             * Drawable and Picture. This way if an application tries to render
+             * to an already flushed XRSurfaceData, we will notice in the
+             * validate() method above that it has been invalidated, and we will
+             * avoid using those native resources that have already been
+             * disposed.
+             */
+            invalidate();
+            flushNativeSurface();
+        }
+
+        /**
+         * Returns destination Image associated with this SurfaceData.
+         */
+        public Object getDestination() {
+            return offscreenImage;
+        }
+    }
+
+    public long getGC() {
+        return xgc;
+    }
+
+    public static class LazyPipe extends ValidatePipe {
+        public boolean validate(SunGraphics2D sg2d) {
+            XRSurfaceData xsd = (XRSurfaceData) sg2d.surfaceData;
+            if (!xsd.isXRDrawableValid()) {
+                return false;
+            }
+            xsd.makePipes();
+            return super.validate(sg2d);
+        }
+    }
+
+    public int getPicture() {
+        return picture;
+    }
+
+    public int getXid() {
+        return xid;
+    }
+
+    public XRGraphicsConfig getGraphicsConfig() {
+        return graphicsConfig;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRSurfaceDataProxy.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import java.awt.Color;
+import java.awt.Transparency;
+import sun.java2d.SurfaceData;
+import sun.java2d.SurfaceDataProxy;
+import sun.java2d.loops.CompositeType;
+
+/**
+ * The proxy class contains the logic if to replace a SurfaceData with a
+ * cached X11 Pixmap and the code to create the accelerated surfaces.
+ */
+public class XRSurfaceDataProxy extends SurfaceDataProxy implements Transparency {
+
+    public static SurfaceDataProxy createProxy(SurfaceData srcData,
+            XRGraphicsConfig dstConfig) {
+
+        /*Don't cache already native surfaces*/
+        if (srcData instanceof XRSurfaceData) {
+            return UNCACHED;
+        }
+
+        return new XRSurfaceDataProxy(dstConfig, srcData.getTransparency());
+    }
+
+    XRGraphicsConfig xrgc;
+    int transparency;
+
+    public XRSurfaceDataProxy(XRGraphicsConfig x11gc) {
+        this.xrgc = x11gc;
+    }
+
+    @Override
+    public SurfaceData validateSurfaceData(SurfaceData srcData,
+            SurfaceData cachedData, int w, int h) {
+        if (cachedData == null) {
+            cachedData = XRSurfaceData.createData(xrgc, w, h, xrgc
+                    .getColorModel(), null, 0, getTransparency());
+        }
+        return cachedData;
+    }
+
+    public XRSurfaceDataProxy(XRGraphicsConfig x11gc, int transparency) {
+        this.xrgc = x11gc;
+        this.transparency = transparency;
+    }
+
+    //TODO: Is that really ok?
+    @Override
+    public boolean isSupportedOperation(SurfaceData srcData, int txtype,
+            CompositeType comp, Color bgColor) {
+        return (bgColor == null || transparency == Transparency.TRANSLUCENT);
+    }
+
+    public int getTransparency() {
+        return transparency;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRUtils.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import java.awt.*;
+import java.awt.MultipleGradientPaint.*;
+import java.awt.image.*;
+import sun.java2d.loops.*;
+import static java.awt.AlphaComposite.*;
+
+/**
+ * XRender constants and utility methods.
+ *
+ * @author Clemens Eisserer
+ */
+
+public class XRUtils {
+    public static final int None = 0;
+
+    /* Composition Operators */
+    public static final byte PictOpClear = 0;
+    public static final byte PictOpSrc = 1;
+    public static final byte PictOpDst = 2;
+    public static final byte PictOpOver = 3;
+    public static final byte PictOpOverReverse = 4;
+    public static final byte PictOpIn = 5;
+    public static final byte PictOpInReverse = 6;
+    public static final byte PictOpOut = 7;
+    public static final byte PictOpOutReverse = 8;
+    public static final byte PictOpAtop = 9;
+    public static final byte PictOpAtopReverse = 10;
+    public static final byte PictOpXor = 11;
+    public static final byte PictOpAdd = 12;
+    public static final byte PictOpSaturate = 13;
+
+    /* Repeats */
+    public static final int RepeatNone = 0;
+    public static final int RepeatNormal = 1;
+    public static final int RepeatPad = 2;
+    public static final int RepeatReflect = 3;
+
+    /* Interpolation qualities */
+    public static final int FAST = 0;
+    public static final int GOOD = 1;
+    public static final int BEST = 2;
+    public static final byte[] FAST_NAME = "fast".getBytes();
+    public static final byte[] GOOD_NAME = "good".getBytes();
+    public static final byte[] BEST_NAME = "best".getBytes();
+
+    /* PictFormats */
+    public static final int PictStandardARGB32 = 0;
+    public static final int PictStandardRGB24 = 1;
+    public static final int PictStandardA8 = 2;
+    public static final int PictStandardA4 = 3;
+    public static final int PictStandardA1 = 4;
+
+    /**
+     * Maps the specified affineTransformOp to the corresponding XRender image
+     * filter.
+     */
+    public static int ATransOpToXRQuality(int affineTranformOp) {
+
+        switch (affineTranformOp) {
+        case AffineTransformOp.TYPE_NEAREST_NEIGHBOR:
+            return FAST;
+
+        case AffineTransformOp.TYPE_BILINEAR:
+            return GOOD;
+
+        case AffineTransformOp.TYPE_BICUBIC:
+            return BEST;
+        }
+
+        return -1;
+    }
+
+    /**
+     * Maps the specified affineTransformOp to the corresponding XRender image
+     * filter.
+     */
+    public static byte[] ATransOpToXRQualityName(int affineTranformOp) {
+
+        switch (affineTranformOp) {
+        case AffineTransformOp.TYPE_NEAREST_NEIGHBOR:
+            return FAST_NAME;
+
+        case AffineTransformOp.TYPE_BILINEAR:
+            return GOOD_NAME;
+
+        case AffineTransformOp.TYPE_BICUBIC:
+            return BEST_NAME;
+        }
+
+        return null;
+    }
+
+
+    public static byte[] getFilterName(int filterType) {
+        switch (filterType) {
+        case FAST:
+            return FAST_NAME;
+        case GOOD:
+            return GOOD_NAME;
+        case BEST:
+            return BEST_NAME;
+        }
+
+        return null;
+    }
+
+
+    /**
+     * Returns the XRender picture Format which is required to fullfill the
+     * Java2D transparency requirement.
+     */
+    public static int getPictureFormatForTransparency(int transparency) {
+        switch (transparency) {
+        case Transparency.OPAQUE:
+            return PictStandardRGB24;
+
+        case Transparency.BITMASK:
+        case Transparency.TRANSLUCENT:
+            return PictStandardARGB32;
+        }
+
+        return -1;
+    }
+
+
+    public static SurfaceType getXRSurfaceTypeForTransparency(int transparency) {
+        if (transparency == Transparency.OPAQUE) {
+            return SurfaceType.IntRgb;
+        }else {
+            return SurfaceType.IntArgbPre;
+        }
+    }
+
+    /**
+     * Maps Java2D CycleMethod to XRender's Repeat property.
+     */
+    public static int getRepeatForCycleMethod(CycleMethod cycleMethod) {
+        if (cycleMethod.equals(CycleMethod.NO_CYCLE)) {
+            return RepeatPad;
+        } else if (cycleMethod.equals(CycleMethod.REFLECT)) {
+            return RepeatReflect;
+        } else if (cycleMethod.equals(CycleMethod.REPEAT)) {
+            return RepeatNormal;
+        }
+
+        return RepeatNone;
+    }
+
+    /**
+     * Converts a double into an XFixed.
+     */
+    public static int XDoubleToFixed(double dbl) {
+        return (int) (dbl * 65536);
+    }
+
+    public static double XFixedToDouble(int fixed) {
+        return ((double) fixed) / 65536;
+    }
+
+    public static int[] convertFloatsToFixed(float[] values) {
+        int[] fixed = new int[values.length];
+
+        for (int i = 0; i < values.length; i++) {
+            fixed[i] = XDoubleToFixed(values[i]);
+        }
+
+        return fixed;
+    }
+
+    public static long intToULong(int signed) {
+        if (signed < 0) {
+            return ((long) signed) + (((long) Integer.MAX_VALUE) -
+                    ((long) Integer.MIN_VALUE) + 1);
+        }
+
+        return signed;
+    }
+
+    /**
+     * Maps the specified Java2D composition rule, to the corresponding XRender
+     * composition rule.
+     */
+    public static byte j2dAlphaCompToXR(int j2dRule) {
+        switch (j2dRule) {
+        case CLEAR:
+            return PictOpClear;
+
+        case SRC:
+            return PictOpSrc;
+
+        case DST:
+            return PictOpDst;
+
+        case SRC_OVER:
+            return PictOpOver;
+
+        case DST_OVER:
+            return PictOpOverReverse;
+
+        case SRC_IN:
+            return PictOpIn;
+
+        case DST_IN:
+            return PictOpInReverse;
+
+        case SRC_OUT:
+            return PictOpOut;
+
+        case DST_OUT:
+            return PictOpOutReverse;
+
+        case SRC_ATOP:
+            return PictOpAtop;
+
+        case DST_ATOP:
+            return PictOpAtopReverse;
+
+        case XOR:
+            return PictOpXor;
+        }
+
+        throw new InternalError("No XRender equivalent available for requested java2d composition rule: "+j2dRule);
+    }
+
+    public static short clampToShort(int x) {
+        return (short) (x > Short.MAX_VALUE
+                           ? Short.MAX_VALUE
+                           : (x < Short.MIN_VALUE ? Short.MIN_VALUE : x));
+    }
+
+    public static short clampToUShort(int x) {
+        return (short) (x > 65535 ? 65535 : (x < 0) ? 0 : x);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRVolatileSurfaceManager.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+import java.awt.GraphicsConfiguration;
+import java.awt.ImageCapabilities;
+import java.awt.image.ColorModel;
+import sun.awt.image.SunVolatileImage;
+import sun.awt.image.VolatileSurfaceManager;
+import sun.java2d.SurfaceData;
+
+/**
+ * XRender platform implementation of the VolatileSurfaceManager class.
+ */
+public class XRVolatileSurfaceManager extends VolatileSurfaceManager {
+
+    public XRVolatileSurfaceManager(SunVolatileImage vImg, Object context) {
+        super(vImg, context);
+    }
+
+    protected boolean isAccelerationEnabled() {
+        return true;
+    }
+
+    /**
+     * Create a pixmap-based SurfaceData object
+     */
+    protected SurfaceData initAcceleratedSurface() {
+        SurfaceData sData;
+
+        try {
+            XRGraphicsConfig gc = (XRGraphicsConfig) vImg.getGraphicsConfig();
+            ColorModel cm = gc.getColorModel();
+            long drawable = 0;
+            if (context instanceof Long) {
+                drawable = ((Long)context).longValue();
+            }
+            sData = XRSurfaceData.createData(gc,
+                                              vImg.getWidth(),
+                                              vImg.getHeight(),
+                                              cm, vImg, drawable,
+                                              vImg.getTransparency());
+        } catch (NullPointerException ex) {
+            sData = null;
+        } catch (OutOfMemoryError er) {
+            sData = null;
+        }
+
+        return sData;
+    }
+
+   /**
+    * XRender should allow copies between different formats and depths.
+    * TODO: verify that this assumption is correct.
+    */
+    protected boolean isConfigValid(GraphicsConfiguration gc) {
+        return true;
+    }
+
+    /**
+     * Need to override the default behavior because Pixmaps-based
+     * images are accelerated but not volatile.
+     */
+    @Override
+    public ImageCapabilities getCapabilities(GraphicsConfiguration gc) {
+        if (isConfigValid(gc) && isAccelerationEnabled()) {
+            return new ImageCapabilities(true);
+        }
+        return new ImageCapabilities(false);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XcbRequestCounter.java	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.java2d.xr;
+
+/**
+ * UInt32 "emulation", mimics the behaviour of xcb's request counter.
+ * In order to be compatible with xcb we have to wrap exactly when xcb would do.
+ * @author Clemens Eisserer
+ */
+
+public class XcbRequestCounter {
+    private final static long MAX_UINT = 4294967295L;
+
+    long value;
+
+    public XcbRequestCounter(long value) {
+        this.value = value;
+    }
+
+    public void setValue(long value) {
+        this.value = value;
+    }
+
+    public long getValue() {
+        return value;
+    }
+
+    public void add(long v) {
+        value += v;
+
+        /*Handle 32-bit unsigned int overflow*/
+        if (value > MAX_UINT) {
+            value = 0; //-= MAX_UINT; //Shouldn't that be zero?!?!
+        }
+    }
+}
--- a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.c	Fri May 28 11:37:44 2010 -0700
@@ -71,7 +71,7 @@
 extern AwtGraphicsConfigDataPtr
     getGraphicsConfigFromComponentPeer(JNIEnv *env, jobject this);
 extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
-static jint X11SD_InitWindow(JNIEnv *env, X11SDOps *xsdo);
+
 static int X11SD_FindClip(SurfaceDataBounds *b, SurfaceDataBounds *bounds,
                           X11SDOps *xsdo);
 static int X11SD_ClipToRoot(SurfaceDataBounds *b, SurfaceDataBounds *bounds,
@@ -97,6 +97,54 @@
 
 #endif /* !HEADLESS */
 
+jboolean XShared_initIDs(JNIEnv *env, jboolean allowShmPixmaps)
+{
+#ifndef HEADLESS
+   union {
+        char c[4];
+        int i;
+    } endian;
+
+    endian.i = 0xff000000;
+    nativeByteOrder = (endian.c[0]) ? MSBFirst : LSBFirst;
+
+    dgaAvailable = JNI_FALSE;
+
+    cachedXImage = NULL;
+
+    if (sizeof(X11RIPrivate) > SD_RASINFO_PRIVATE_SIZE) {
+        JNU_ThrowInternalError(env, "Private RasInfo structure too large!");
+        return JNI_FALSE;
+    }
+
+#ifdef MITSHM
+    if (getenv("NO_AWT_MITSHM") == NULL &&
+        getenv("NO_J2D_MITSHM") == NULL) {
+        char * force;
+        TryInitMITShm(env, &useMitShmExt, &useMitShmPixmaps);
+
+        if(allowShmPixmaps) {
+          useMitShmPixmaps = (useMitShmPixmaps == CAN_USE_MITSHM);
+          force = getenv("J2D_PIXMAPS");
+          if (force != NULL) {
+              if (useMitShmPixmaps && (strcmp(force, "shared") == 0)) {
+                  forceSharedPixmaps = JNI_TRUE;
+              } else if (strcmp(force, "server") == 0) {
+                  useMitShmPixmaps = JNI_FALSE;
+              }
+          }
+        }else {
+          useMitShmPixmaps = JNI_FALSE;
+        }
+    }
+
+    return JNI_TRUE;
+#endif /* MITSHM */
+
+#endif /* !HEADLESS */
+}
+
+
 /*
  * Class:     sun_java2d_x11_X11SurfaceData
  * Method:    initIDs
@@ -107,30 +155,17 @@
                                            jclass XORComp, jboolean tryDGA)
 {
 #ifndef HEADLESS
+  if(XShared_initIDs(env, JNI_TRUE))
+  {
     void *lib = 0;
 
-    union {
-        char c[4];
-        int i;
-    } endian;
-
-    endian.i = 0xff000000;
-    nativeByteOrder = (endian.c[0]) ? MSBFirst : LSBFirst;
-
-    cachedXImage = NULL;
-
-    if (sizeof(X11RIPrivate) > SD_RASINFO_PRIVATE_SIZE) {
-        JNU_ThrowInternalError(env, "Private RasInfo structure too large!");
-        return;
-    }
-
     xorCompClass = (*env)->NewGlobalRef(env, XORComp);
 
     if (tryDGA && (getenv("NO_J2D_DGA") == NULL)) {
     /* we use RTLD_NOW because of bug 4032715 */
         lib = dlopen("libsunwjdga.so", RTLD_NOW);
     }
-    dgaAvailable = JNI_FALSE;
+
     if (lib != NULL) {
         JDgaStatus ret = JDGA_FAILED;
         void *sym = dlsym(lib, "JDgaLibInit");
@@ -149,24 +184,7 @@
             lib = NULL;
         }
     }
-
-#ifdef MITSHM
-    if (getenv("NO_AWT_MITSHM") == NULL &&
-        getenv("NO_J2D_MITSHM") == NULL) {
-        char * force;
-        TryInitMITShm(env, &useMitShmExt, &useMitShmPixmaps);
-        useMitShmPixmaps = (useMitShmPixmaps == CAN_USE_MITSHM);
-        force = getenv("J2D_PIXMAPS");
-        if (force != NULL) {
-            if (useMitShmPixmaps && (strcmp(force, "shared") == 0)) {
-                forceSharedPixmaps = JNI_TRUE;
-            } else if (strcmp(force, "server") == 0) {
-                useMitShmPixmaps = JNI_FALSE;
-            }
-        }
-    }
-#endif /* MITSHM */
-
+  }
 #endif /* !HEADLESS */
 }
 
@@ -176,7 +194,7 @@
  * Signature: ()Z
  */
 JNIEXPORT jboolean JNICALL
-Java_sun_java2d_x11_X11SurfaceData_isDrawableValid(JNIEnv *env, jobject this)
+Java_sun_java2d_x11_XSurfaceData_isDrawableValid(JNIEnv *env, jobject this)
 {
     jboolean ret = JNI_FALSE;
 
@@ -194,6 +212,21 @@
 }
 
 /*
+ * Class: sun_java2d_x11_X11SurfaceData
+ * Method: isShmPMAvailable
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_sun_java2d_x11_X11SurfaceData_isShmPMAvailable(JNIEnv *env, jobject this)
+{
+#if defined(HEADLESS) || !defined(MITSHM)
+    return JNI_FALSE;
+#else
+    return useMitShmPixmaps;
+#endif /* HEADLESS, MITSHM */
+}
+
+/*
  * Class:     sun_java2d_x11_X11SurfaceData
  * Method:    isDgaAvailable
  * Signature: ()Z
@@ -208,30 +241,13 @@
 #endif /* HEADLESS */
 }
 
-
-/*
- * Class:     sun_java2d_x11_X11SurfaceData
- * Method:    isShmPMAvailable
- * Signature: ()Z
- */
-JNIEXPORT jboolean JNICALL
-Java_sun_java2d_x11_X11SurfaceData_isShmPMAvailable(JNIEnv *env, jobject this)
-{
-#if defined(HEADLESS) || !defined(MITSHM)
-    return JNI_FALSE;
-#else
-    return useMitShmPixmaps;
-#endif /* HEADLESS, MITSHM */
-}
-
-
 /*
  * Class:     sun_java2d_x11_X11SurfaceData
  * Method:    initOps
  * Signature: (Ljava/lang/Object;I)V
  */
 JNIEXPORT void JNICALL
-Java_sun_java2d_x11_X11SurfaceData_initOps(JNIEnv *env, jobject xsd,
+Java_sun_java2d_x11_XSurfaceData_initOps(JNIEnv *env, jobject xsd,
                                            jobject peer,
                                            jobject graphicsConfig, jint depth)
 {
@@ -304,6 +320,8 @@
     } else {
         xsdo->pixelmask = 0xff;
     }
+
+    xsdo->xrPic = None;
 #endif /* !HEADLESS */
 }
 
@@ -313,7 +331,7 @@
  * Signature: ()V
  */
 JNIEXPORT void JNICALL
-Java_sun_java2d_x11_X11SurfaceData_flushNativeSurface(JNIEnv *env, jobject xsd)
+Java_sun_java2d_x11_XSurfaceData_flushNativeSurface(JNIEnv *env, jobject xsd)
 {
 #ifndef HEADLESS
     SurfaceDataOps *ops = SurfaceData_GetOps(env, xsd);
@@ -384,6 +402,11 @@
         XFreeGC(awt_display, xsdo->cachedGC);
         xsdo->cachedGC = NULL;
     }
+
+    if(xsdo->xrPic != None) {
+      XRenderFreePicture(awt_display, xsdo->xrPic);
+    }
+
     AWT_UNLOCK();
 #endif /* !HEADLESS */
 }
@@ -393,7 +416,7 @@
  * Signature: ()V
  */
 JNIEXPORT void JNICALL
-Java_sun_java2d_x11_X11SurfaceData_setInvalid(JNIEnv *env, jobject xsd)
+Java_sun_java2d_x11_XSurfaceData_setInvalid(JNIEnv *env, jobject xsd)
 {
 #ifndef HEADLESS
     X11SDOps *xsdo = (X11SDOps *) SurfaceData_GetOps(env, xsd);
@@ -404,6 +427,63 @@
 #endif /* !HEADLESS */
 }
 
+
+jboolean XShared_initSurface(JNIEnv *env, X11SDOps *xsdo, jint depth, jint width, jint height, jlong drawable)
+{
+#ifndef HEADLESS
+
+    if (drawable != (jlong)0) {
+        /* Double-buffering */
+        xsdo->drawable = drawable;
+        xsdo->isPixmap = JNI_FALSE;
+    } else {
+        xsdo->isPixmap = JNI_TRUE;
+        /* REMIND: workaround for bug 4420220 on pgx32 boards:
+           don't use DGA with pixmaps unless USE_DGA_PIXMAPS is set.
+         */
+        xsdo->dgaAvailable = useDGAWithPixmaps;
+
+        xsdo->pmWidth = width;
+        xsdo->pmHeight = height;
+
+#ifdef MITSHM
+        xsdo->shmPMData.pmSize = width * height * depth;
+        xsdo->shmPMData.pixelsReadThreshold = width * height / 8;
+        if (forceSharedPixmaps) {
+            AWT_LOCK();
+            xsdo->drawable = X11SD_CreateSharedPixmap(xsdo);
+            AWT_UNLOCK();
+            if (xsdo->drawable) {
+                xsdo->shmPMData.usingShmPixmap = JNI_TRUE;
+                xsdo->shmPMData.shmPixmap = xsdo->drawable;
+                return JNI_TRUE;
+            }
+        }
+#endif /* MITSHM */
+
+        AWT_LOCK();
+        xsdo->drawable =
+            XCreatePixmap(awt_display,
+                          RootWindow(awt_display,
+                                     xsdo->configData->awt_visInfo.screen),
+                          width, height, depth);
+        AWT_UNLOCK();
+#ifdef MITSHM
+        xsdo->shmPMData.usingShmPixmap = JNI_FALSE;
+        xsdo->shmPMData.pixmap = xsdo->drawable;
+#endif /* MITSHM */
+    }
+    if (xsdo->drawable == 0) {
+        JNU_ThrowOutOfMemoryError(env,
+                                  "Can't create offscreen surface");
+        return JNI_FALSE;
+    }
+
+    return JNI_TRUE;
+#endif /* !HEADLESS */
+}
+
+
 /*
  * Class:     sun_java2d_x11_X11SurfaceData
  * Method:    initSurface
@@ -428,51 +508,8 @@
        8-bit visuals */
     xsdo->cData = xsdo->configData->color_data;
 
-    if (drawable != (jlong)0) {
-        /* Double-buffering */
-        xsdo->drawable = drawable;
-        xsdo->isPixmap = JNI_FALSE;
-    } else {
-        xsdo->isPixmap = JNI_TRUE;
-        /* REMIND: workaround for bug 4420220 on pgx32 boards:
-           don't use DGA with pixmaps unless USE_DGA_PIXMAPS is set.
-         */
-        xsdo->dgaAvailable = useDGAWithPixmaps;
-
-        xsdo->pmWidth = width;
-        xsdo->pmHeight = height;
-
-#ifdef MITSHM
-        xsdo->shmPMData.pmSize = width * height * depth;
-        xsdo->shmPMData.pixelsReadThreshold = width * height / 8;
-        if (forceSharedPixmaps) {
-            AWT_LOCK();
-            xsdo->drawable = X11SD_CreateSharedPixmap(xsdo);
-            AWT_UNLOCK();
-            if (xsdo->drawable) {
-                xsdo->shmPMData.usingShmPixmap = JNI_TRUE;
-                xsdo->shmPMData.shmPixmap = xsdo->drawable;
-                return;
-            }
-        }
-#endif /* MITSHM */
-
-        AWT_LOCK();
-        xsdo->drawable =
-            XCreatePixmap(awt_display,
-                          RootWindow(awt_display,
-                                     xsdo->configData->awt_visInfo.screen),
-                          width, height, depth);
-        AWT_UNLOCK();
-#ifdef MITSHM
-        xsdo->shmPMData.usingShmPixmap = JNI_FALSE;
-        xsdo->shmPMData.pixmap = xsdo->drawable;
-#endif /* MITSHM */
-    }
-    if (xsdo->drawable == 0) {
-        JNU_ThrowOutOfMemoryError(env,
-                                  "Can't create offscreen surface");
-    }
+    XShared_initSurface(env, xsdo, depth, width, height, drawable);
+    xsdo->xrPic = NULL;
 #endif /* !HEADLESS */
 }
 
@@ -718,7 +755,7 @@
 }
 #endif /* MITSHM */
 
-static jint X11SD_InitWindow(JNIEnv *env, X11SDOps *xsdo)
+jint X11SD_InitWindow(JNIEnv *env, X11SDOps *xsdo)
 {
     if (xsdo->isPixmap == JNI_TRUE) {
         return SD_FAILURE;
@@ -1568,7 +1605,7 @@
  * Signature: (I)J
  */
 JNIEXPORT jlong JNICALL
-Java_sun_java2d_x11_X11SurfaceData_XCreateGC
+Java_sun_java2d_x11_XSurfaceData_XCreateGC
     (JNIEnv *env, jclass xsd, jlong pXSData)
 {
     jlong ret;
@@ -1598,7 +1635,7 @@
  * Signature: (JIIIILsun/java2d/pipe/Region;)V
  */
 JNIEXPORT void JNICALL
-Java_sun_java2d_x11_X11SurfaceData_XResetClip
+Java_sun_java2d_x11_XSurfaceData_XResetClip
     (JNIEnv *env, jclass xsd, jlong xgc)
 {
 #ifndef HEADLESS
@@ -1613,7 +1650,7 @@
  * Signature: (JIIIILsun/java2d/pipe/Region;)V
  */
 JNIEXPORT void JNICALL
-Java_sun_java2d_x11_X11SurfaceData_XSetClip
+Java_sun_java2d_x11_XSurfaceData_XSetClip
     (JNIEnv *env, jclass xsd, jlong xgc,
      jint x1, jint y1, jint x2, jint y2,
      jobject complexclip)
@@ -1688,7 +1725,7 @@
  * Signature: (JZ)V
  */
 JNIEXPORT void JNICALL
-Java_sun_java2d_x11_X11SurfaceData_XSetGraphicsExposures
+Java_sun_java2d_x11_XSurfaceData_XSetGraphicsExposures
     (JNIEnv *env, jclass xsd, jlong xgc, jboolean needExposures)
 {
 #ifndef HEADLESS
--- a/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.h	Thu May 27 08:53:45 2010 -0700
+++ b/jdk/src/solaris/native/sun/java2d/x11/X11SurfaceData.h	Fri May 28 11:37:44 2010 -0700
@@ -30,6 +30,8 @@
 
 #include <jdga.h>
 
+#include <X11/extensions/Xrender.h>
+
 /**
  * This include file contains support declarations for loops using the
  * X11 extended SurfaceData interface to talk to an X11 drawable from
@@ -110,6 +112,7 @@
     jboolean            isBgInitialized; /* whether the bg pixel is valid */
     jint                pmWidth;       /* width, height of the */
     jint                pmHeight;      /* pixmap */
+    Picture             xrPic;
 #ifdef MITSHM
     ShmPixmapData       shmPMData;     /* data for switching between shm/nonshm pixmaps*/
 #endif /* MITSHM */
@@ -136,6 +139,9 @@
 void     X11SD_DirectRenderNotify(JNIEnv *env, X11SDOps *xsdo);
 #endif /* !HEADLESS */
 
+jboolean XShared_initIDs(JNIEnv *env, jboolean allowShmPixmaps);
+jboolean XShared_initSurface(JNIEnv *env, X11SDOps *xsdo, jint depth, jint width, jint height, jlong drawable);
+
 /*
  * This function returns a pointer to a native X11SDOps structure
  * for accessing the indicated X11 SurfaceData Java object.  It
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/native/sun/java2d/x11/XRBackendNative.c	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,784 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#include "X11SurfaceData.h"
+#include <jni.h>
+#include <math.h>
+#include "Region.h"
+#include "fontscalerdefs.h"
+
+#include <X11/extensions/Xrender.h>
+
+#ifndef X_RenderCreateLinearGradient
+typedef struct _XLinearGradient {
+    XPointFixed p1;
+    XPointFixed p2;
+} XLinearGradient;
+#endif
+
+#ifndef X_RenderCreateRadialGradient
+typedef struct _XCircle {
+    XFixed x;
+    XFixed y;
+    XFixed radius;
+} XCircle;
+
+typedef struct _XRadialGradient {
+    XCircle inner;
+    XCircle outer;
+} XRadialGradient;
+#endif
+
+#ifdef __solaris__
+/* Solaris 10 will not have these symbols at runtime */
+#include <dlfcn.h>
+#include <link.h>
+
+typedef Picture (*XRenderCreateLinearGradientFuncType)
+                                     (Display *dpy,
+                                     const XLinearGradient *gradient,
+                                     const XFixed *stops,
+                                     const XRenderColor *colors,
+                                     int nstops);
+
+typedef Picture (*XRenderCreateRadialGradientFuncType)
+                                     (Display *dpy,
+                                     const XRadialGradient *gradient,
+                                     const XFixed *stops,
+                                     const XRenderColor *colors,
+                                     int nstops);
+
+static
+XRenderCreateLinearGradientFuncType XRenderCreateLinearGradientFunc = NULL;
+static
+ XRenderCreateRadialGradientFuncType XRenderCreateRadialGradientFunc = NULL;
+#endif
+
+#define BUILD_TRANSFORM_MATRIX(TRANSFORM, M00, M01, M02, M10, M11, M12)                        \
+    {                                                                                          \
+      TRANSFORM.matrix[0][0] = M00;                                                            \
+      TRANSFORM.matrix[0][1] = M01;                                                            \
+      TRANSFORM.matrix[0][2] = M02;                                                            \
+      TRANSFORM.matrix[1][0] = M10;                                                            \
+      TRANSFORM.matrix[1][1] = M11;                                                            \
+      TRANSFORM.matrix[1][2] = M12;                                                            \
+      TRANSFORM.matrix[2][0] = 0;                                                              \
+      TRANSFORM.matrix[2][1] = 0;                                                              \
+      TRANSFORM.matrix[2][2] = 1<<16;                                                          \
+    }
+
+
+static jboolean IsXRenderAvailable() {
+
+    void *xrenderlib;
+
+    int major_opcode, first_event, first_error;
+
+    if (!XQueryExtension(awt_display, "RENDER",
+                         &major_opcode, &first_event, &first_error)) {
+        return JNI_FALSE;
+    }
+
+#ifdef __solaris__
+    xrenderlib = dlopen("libXrender.so",RTLD_GLOBAL|RTLD_LAZY);
+    if (xrenderlib != NULL) {
+
+        XRenderCreateLinearGradientFunc =
+            (XRenderCreateLinearGradientFuncType)
+            dlsym(xrenderlib, "XRenderCreateLinearGradient");
+
+        XRenderCreateRadialGradientFunc =
+            (XRenderCreateRadialGradientFuncType)
+            dlsym(xrenderlib, "XRenderCreateRadialGradient");
+
+        if (XRenderCreateLinearGradientFunc == NULL ||
+            XRenderCreateRadialGradientFunc == NULL)
+        {
+            dlclose(xrenderlib);
+            return JNI_FALSE;
+        }
+    }
+#endif
+    return JNI_TRUE;
+}
+/*
+ * Class:     sun_awt_X11GraphicsEnvironment
+ * Method:    initGLX
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_sun_awt_X11GraphicsEnvironment_initXRender
+ (JNIEnv *env, jclass x11ge)
+{
+#ifndef HEADLESS
+    static jboolean xrenderAvailable = JNI_FALSE;
+    static jboolean firstTime = JNI_TRUE;
+
+    if (firstTime) {
+        AWT_LOCK();
+        xrenderAvailable = IsXRenderAvailable();
+        AWT_UNLOCK();
+        firstTime = JNI_FALSE;
+    }
+    return xrenderAvailable;
+#else
+    return JNI_FALSE;
+#endif /* !HEADLESS */
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_initIDs(JNIEnv *env, jclass cls) {
+    char *maskData;
+    XImage* defaultImg;
+    jfieldID maskImgID;
+    jlong fmt8 =
+        ptr_to_jlong(XRenderFindStandardFormat(awt_display, PictStandardA8));
+    jlong fmt32 =
+       ptr_to_jlong(XRenderFindStandardFormat(awt_display, PictStandardARGB32));
+    jfieldID a8ID = (*env)->GetStaticFieldID(env, cls, "FMTPTR_A8", "J");
+    jfieldID argb32ID = (*env)->GetStaticFieldID(env, cls, "FMTPTR_ARGB32", "J");
+
+    (*env)->SetStaticLongField(env, cls, a8ID, fmt8);
+    (*env)->SetStaticLongField(env, cls, argb32ID, fmt32);
+
+    maskData = (char *) malloc(32*32);
+    if (maskData == NULL) {
+       return;
+    }
+
+    defaultImg = XCreateImage(awt_display, NULL, 8, ZPixmap, 0, maskData, 32, 32, 8, 0);
+    defaultImg->data = maskData; //required?
+    maskImgID = (*env)->GetStaticFieldID(env, cls, "MASK_XIMG", "J");
+    (*env)->SetStaticLongField(env, cls, maskImgID, ptr_to_jlong(defaultImg));
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_freeGC
+ (JNIEnv *env, jobject this, jlong gc) {
+    XFreeGC(awt_display, (GC) jlong_to_ptr(gc));
+}
+
+JNIEXPORT jlong JNICALL
+Java_sun_java2d_xr_XRBackendNative_createGC
+ (JNIEnv *env, jobject this, jint drawable) {
+  GC xgc = XCreateGC(awt_display, (Drawable) drawable, 0L, NULL);
+  return ptr_to_jlong(xgc);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_java2d_xr_XRBackendNative_createPixmap(JNIEnv *env, jobject this,
+                                                jint drawable, jint depth,
+                                                jint width, jint height) {
+    return (jint) XCreatePixmap(awt_display, (Drawable) drawable,
+                                width, height, depth);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_java2d_xr_XRBackendNative_createPictureNative
+ (JNIEnv *env, jclass cls, jint drawable, jlong formatPtr) {
+  XRenderPictureAttributes pict_attr;
+  return XRenderCreatePicture(awt_display, (Drawable) drawable,
+                              (XRenderPictFormat *) jlong_to_ptr(formatPtr),
+                               0, &pict_attr);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_freePicture
+ (JNIEnv *env, jobject this, jint picture) {
+      XRenderFreePicture(awt_display, (Picture) picture);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_freePixmap
+ (JNIEnv *env, jobject this, jint pixmap) {
+   XFreePixmap(awt_display, (Pixmap) pixmap);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_setPictureRepeat
+ (JNIEnv *env, jobject this, jint picture, jint repeat) {
+    XRenderPictureAttributes pict_attr;
+    pict_attr.repeat = repeat;
+    XRenderChangePicture (awt_display, (Picture) picture, CPRepeat, &pict_attr);
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_setGCExposures
+ (JNIEnv *env, jobject this, jlong gc, jboolean exposure) {
+    XSetGraphicsExposures(awt_display,
+                         (GC) jlong_to_ptr(gc), exposure ? True : False); //TODO: ????
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_setGCForeground
+ (JNIEnv *env, jobject this, jlong gc, jint pixel) {
+    XSetForeground(awt_display, (GC) jlong_to_ptr(gc), (unsigned long) pixel);
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_copyArea
+ (JNIEnv *env, jobject this, jint src, jint dst, jlong gc,
+  jint srcx, jint srcy, jint width, jint height, jint dstx, jint dsty) {
+    XCopyArea(awt_display, (Drawable) src, (Drawable) dst,
+             (GC) jlong_to_ptr(gc), srcx, srcy, width, height, dstx, dsty);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_renderComposite
+ (JNIEnv *env, jobject this, jbyte op, jint src, jint mask, jint dst,
+  jint srcX, jint srcY, jint maskX, jint maskY,
+  jint dstX, jint dstY, jint width, jint height) {
+    XRenderComposite (awt_display, op,
+                      (Picture)src, (Picture)mask, (Picture)dst,
+                       srcX, srcY, maskX, maskY, dstX, dstY, width, height);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_renderRectangle
+ (JNIEnv *env, jobject this, jint dst, jbyte op,
+  jshort red, jshort green, jshort blue, jshort alpha,
+  jint x, jint y, jint width, jint height) {
+    XRenderColor color;
+    color.alpha = alpha;
+    color.red = red;
+    color.green = green;
+    color.blue = blue;
+    XRenderFillRectangle(awt_display, op, (Picture) dst, &color,
+                         x, y, width, height);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_XRenderRectanglesNative
+ (JNIEnv *env, jclass xsd, jint dst, jbyte op,
+  jshort red, jshort green, jshort blue, jshort alpha,
+  jintArray rectArray, jint rectCnt) {
+    int i;
+    jint* rects;
+    XRectangle *xRects;
+    XRectangle sRects[256];
+
+    XRenderColor color;
+    color.alpha = alpha;
+    color.red = red;
+    color.green = green;
+    color.blue = blue;
+
+    if (rectCnt <= 256) {
+      xRects = &sRects[0];
+    } else {
+      xRects = (XRectangle *) malloc(sizeof(XRectangle) * rectCnt);
+      if (xRects == NULL) {
+        return;
+      }
+    }
+
+    if ((rects = (jint *) (*env)->GetPrimitiveArrayCritical(env, rectArray, NULL)) == NULL) {
+      return;
+    }
+
+    for (i=0; i < rectCnt; i++) {
+      xRects[i].x = rects[i*4 + 0];
+      xRects[i].y = rects[i*4 + 1];
+      xRects[i].width = rects[i*4 + 2];
+      xRects[i].height = rects[i*4 + 3];
+    }
+
+    XRenderFillRectangles(awt_display, op,
+                          (Picture) dst, &color, xRects, rectCnt);
+
+    (*env)->ReleasePrimitiveArrayCritical(env, rectArray, rects, JNI_ABORT);
+    if (xRects != &sRects[0]) {
+      free(xRects);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_XRSetTransformNative
+ (JNIEnv *env, jclass xsd, jint pic,
+  jint m00, jint m01, jint m02, jint m10, jint m11, jint m12) {
+
+  XTransform tr;
+  BUILD_TRANSFORM_MATRIX(tr, m00, m01, m02, m10, m11, m12);
+  XRenderSetPictureTransform (awt_display, (Picture) pic, &tr);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_java2d_xr_XRBackendNative_XRCreateLinearGradientPaintNative
+    (JNIEnv *env, jclass xsd, jfloatArray fractionsArray,
+     jshortArray pixelsArray, jint x1, jint y1, jint x2, jint y2,
+     jint numStops, jint repeat,
+     jint m00, jint m01, jint m02, jint m10, jint m11, jint m12) {
+   jint i;
+   jshort* pixels;
+   jfloat* fractions;
+   XTransform tr;
+   XRenderPictureAttributes pict_attr;
+   Picture gradient = 0;
+   XRenderColor *colors;
+   XFixed *stops;
+   XLinearGradient grad;
+
+   if ((pixels = (jshort *)
+        (*env)->GetPrimitiveArrayCritical(env, pixelsArray, NULL)) == NULL) {
+       return -1;
+   }
+   if ((fractions = (jfloat *)
+       (*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL)) == NULL) {
+       (*env)->ReleasePrimitiveArrayCritical(env,
+                                              pixelsArray, pixels, JNI_ABORT);
+       return -1;
+   }
+
+    grad.p1.x = x1;
+    grad.p1.y = y1;
+    grad.p2.x = x2;
+    grad.p2.y = y2;
+
+    /*TODO optimized & malloc check*/
+    colors = (XRenderColor *) malloc(numStops * sizeof(XRenderColor));
+    stops =  (XFixed *) malloc(numStops * sizeof(XFixed));
+
+    for (i=0; i < numStops; i++) {
+      stops[i] = XDoubleToFixed(fractions[i]);
+      colors[i].alpha = pixels[i*4 + 0];
+      colors[i].red = pixels[i*4 + 1];
+      colors[i].green = pixels[i*4 + 2];
+      colors[i].blue = pixels[i*4 + 3];
+    }
+#ifdef __solaris__
+    if (XRenderCreateLinearGradientFunc!=NULL) {
+      gradient = (*XRenderCreateLinearGradientFunc)(awt_display, &grad, stops, colors, numStops);
+    }
+#else
+    gradient = XRenderCreateLinearGradient(awt_display, &grad, stops, colors, numStops);
+#endif
+    free(colors);
+    free(stops);
+
+   (*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT);
+   (*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT);
+
+    if (gradient != 0) {
+        BUILD_TRANSFORM_MATRIX(tr, m00, m01, m02, m10, m11, m12);
+        XRenderSetPictureTransform (awt_display, gradient, &tr);
+        pict_attr.repeat = repeat;
+        XRenderChangePicture (awt_display, gradient, CPRepeat, &pict_attr);
+    }
+
+   return (jint) gradient;
+}
+
+
+JNIEXPORT jint JNICALL
+Java_sun_java2d_xr_XRBackendNative_XRCreateRadialGradientPaintNative
+    (JNIEnv *env, jclass xsd, jfloatArray fractionsArray,
+     jshortArray pixelsArray, jint numStops,
+     jint innerRadius, jint outerRadius, jint repeat,
+     jint m00, jint m01, jint m02, jint m10, jint m11, jint m12) {
+   jint i;
+   jshort* pixels;
+   jfloat* fractions;
+   XTransform tr;
+   XRenderPictureAttributes pict_attr;
+   Picture gradient = 0;
+   XRenderColor *colors;
+   XFixed *stops;
+   XRadialGradient grad;
+
+
+   if ((pixels =
+       (jshort *)(*env)->GetPrimitiveArrayCritical(env, pixelsArray, NULL)) == NULL) {
+       return -1;
+   }
+   if ((fractions = (jfloat *)
+        (*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL)) == NULL) {
+       (*env)->ReleasePrimitiveArrayCritical(env,
+                                             pixelsArray, pixels, JNI_ABORT);
+       return -1; //TODO release pixels first
+   }
+
+    grad.inner.x = 0;
+    grad.inner.y = 0;
+    grad.inner.radius = innerRadius;
+    grad.outer.x = 0;
+    grad.outer.y = 0;
+    grad.outer.radius = outerRadius;
+
+    /*TODO optimized & malloc check*/
+    colors = (XRenderColor *) malloc(numStops * sizeof(XRenderColor));
+    stops =  (XFixed *) malloc(numStops * sizeof(XFixed));
+
+    for (i=0; i < numStops; i++) {
+      stops[i] = XDoubleToFixed(fractions[i]);
+      colors[i].alpha = pixels[i*4 + 0];
+      colors[i].red = pixels[i*4 + 1];
+      colors[i].green = pixels[i*4 + 2];
+      colors[i].blue = pixels[i*4 + 3];
+    }
+#ifdef __solaris__
+    if (XRenderCreateRadialGradientFunc != NULL) {
+        gradient = (jint) (*XRenderCreateRadialGradientFunc)(awt_display, &grad, stops, colors, numStops);
+    }
+#else
+    gradient = (jint) XRenderCreateRadialGradient(awt_display, &grad, stops, colors, numStops);
+#endif
+    free(colors);
+    free(stops);
+
+   (*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT);
+   (*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT);
+
+
+    if (gradient != 0) {
+        BUILD_TRANSFORM_MATRIX(tr, m00, m01, m02, m10, m11, m12);
+        XRenderSetPictureTransform (awt_display, gradient, &tr);
+        pict_attr.repeat = repeat;
+        XRenderChangePicture (awt_display, gradient, CPRepeat, &pict_attr);
+    }
+
+   return (jint) gradient;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_setFilter
+ (JNIEnv *env, jobject this, jint picture, jint filter) {
+
+  char * filterName = "fast";
+
+  switch(filter) {
+    case 0:
+      filterName = "fast";
+      break;
+
+    case 1:
+      filterName = "good";
+      break;
+
+    case 2:
+      filterName = "best";
+      break;
+  }
+
+    XRenderSetPictureFilter(awt_display, (Picture) picture, filterName, NULL, 0);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_XRSetClipNative
+    (JNIEnv *env, jclass xsd, jlong dst,
+     jint x1, jint y1, jint x2, jint y2,
+     jobject complexclip, jboolean isGC)
+{
+    int numrects;
+    XRectangle rects[256];
+    XRectangle *pRect = rects;
+
+    numrects = RegionToYXBandedRectangles(env,
+            x1, y1, x2, y2, complexclip,
+            &pRect, 256);
+
+    if (isGC == JNI_TRUE) {
+      if (dst != (jlong) 0) {
+          XSetClipRectangles(awt_display, (GC) jlong_to_ptr(dst), 0, 0, pRect, numrects, YXBanded);
+      }
+    } else {
+       XRenderSetPictureClipRectangles (awt_display, (Picture) dst, 0, 0, pRect, numrects);
+    }
+
+    if (pRect != rects) {
+        free(pRect);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_putMaskNative
+ (JNIEnv *env, jclass cls, jint drawable, jlong gc, jbyteArray imageData,
+  jint sx, jint sy, jint dx, jint dy, jint width, jint height,
+  jint maskOff, jint maskScan, jfloat ea, jlong imgPtr) {
+
+    int line, pix;
+    char *mask;
+    char *defaultData;
+    XImage *defaultImg, *img;
+    jboolean imageFits;
+
+    if ((mask = (char *)
+         (*env)->GetPrimitiveArrayCritical(env, imageData, NULL)) == NULL) {
+        return;
+     }
+
+    defaultImg = (XImage *) jlong_to_ptr(imgPtr);
+
+    if (ea != 1.0f) {
+        for (line=0; line < height; line++) {
+            for (pix=0; pix < width; pix++) {
+                int index = maskScan*line + pix + maskOff;
+                mask[index] = (((unsigned char) mask[index])*ea);
+            }
+        }
+    }
+
+    /*
+    * 1. If existing XImage and supplied buffer match, only adjust the data pointer
+    * 2. If existing XImage is large enough to hold the data but does not match in
+    *    scan the data is copied to fit the XImage.
+    * 3. If data is larger than the existing XImage a new temporary XImage is
+    *    allocated.
+    * The default XImage is optimized for the AA tiles, which are currently 32x32.
+    */
+    defaultData = defaultImg->data;
+    img = defaultImg;
+    imageFits = defaultImg->width >= width && defaultImg->height >= height;
+
+    if (imageFits &&
+        maskOff == defaultImg->xoffset && maskScan == defaultImg->bytes_per_line) {
+        defaultImg->data = mask;
+    } else {
+        if (imageFits) {
+            for (line=0; line < height; line++) {
+                for (pix=0; pix < width; pix++) {
+                    img->data[line*img->bytes_per_line + pix] =
+                        (unsigned char) (mask[maskScan*line + pix + maskOff]);
+                }
+            }
+        } else {
+            img = XCreateImage(awt_display, NULL, 8, ZPixmap,
+                               maskOff, mask, maskScan, height, 8, 0);
+        }
+    }
+
+    XPutImage(awt_display, (Pixmap) drawable, (GC) jlong_to_ptr(gc),
+              img, 0, 0, 0, 0, width, height);
+    (*env)->ReleasePrimitiveArrayCritical(env, imageData, mask, JNI_ABORT);
+
+    if (img != defaultImg) {
+        img->data = NULL;
+        XDestroyImage(img);
+    }
+    defaultImg->data = defaultData;
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_XRAddGlyphsNative
+ (JNIEnv *env, jclass cls, jint glyphSet,
+  jlongArray glyphInfoPtrsArray, jint glyphCnt,
+  jbyteArray pixelDataArray, int pixelDataLength) {
+    jlong *glyphInfoPtrs;
+    unsigned char *pixelData;
+    int i;
+
+    XGlyphInfo *xginfo = (XGlyphInfo *) malloc(sizeof(XGlyphInfo) * glyphCnt);
+    Glyph *gid = (Glyph *) malloc(sizeof(Glyph) * glyphCnt);
+
+    if (xginfo == NULL || gid == NULL) {
+      return;
+    }
+
+    if ((glyphInfoPtrs = (jlong *) (*env)->GetPrimitiveArrayCritical(env, glyphInfoPtrsArray, NULL)) == NULL) {
+        return;
+    }
+
+    if ((pixelData = (unsigned char *)
+        (*env)->GetPrimitiveArrayCritical(env, pixelDataArray, NULL)) == NULL) {
+        (*env)->ReleasePrimitiveArrayCritical(env,
+                                  glyphInfoPtrsArray, glyphInfoPtrs, JNI_ABORT);
+        return;
+    }
+
+    for (i=0; i < glyphCnt; i++) {
+      GlyphInfo *jginfo = (GlyphInfo *) jlong_to_ptr(glyphInfoPtrs[i]);
+
+      gid[i] = (Glyph) (0xffffffff & ((unsigned int) jginfo->cellInfo));
+      xginfo[i].x = (-jginfo->topLeftX);
+      xginfo[i].y = (-jginfo->topLeftY);
+      xginfo[i].width = jginfo->width;
+      xginfo[i].height = jginfo->height;
+      xginfo[i].xOff = round(jginfo->advanceX);
+      xginfo[i].yOff = round(jginfo->advanceY);
+    }
+
+    XRenderAddGlyphs(awt_display, glyphSet, &gid[0], &xginfo[0], glyphCnt,
+                     pixelData, pixelDataLength);
+
+    (*env)->ReleasePrimitiveArrayCritical(env, glyphInfoPtrsArray, glyphInfoPtrs, JNI_ABORT);
+    (*env)->ReleasePrimitiveArrayCritical(env, pixelDataArray, pixelData, JNI_ABORT);
+
+    free(xginfo);
+    free(gid);
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_XRFreeGlyphsNative
+ (JNIEnv *env, jclass cls, jint glyphSet, jintArray gidArray, jint glyphCnt) {
+    jint *gids;
+    int i;
+
+    if ((gids = (jint *) (*env)->GetPrimitiveArrayCritical(env, gidArray, NULL)) == NULL) {
+        return;
+    }
+
+    XRenderFreeGlyphs (awt_display, (GlyphSet) glyphSet, (Glyph *) gids, glyphCnt);
+
+    (*env)->ReleasePrimitiveArrayCritical(env, gidArray, gids, JNI_ABORT);
+}
+
+JNIEXPORT jint JNICALL
+Java_sun_java2d_xr_XRBackendNative_XRenderCreateGlyphSetNative
+ (JNIEnv *env, jclass cls, jlong format) {
+  return XRenderCreateGlyphSet(awt_display, (XRenderPictFormat *) jlong_to_ptr(format));
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_XRenderCompositeTextNative
+ (JNIEnv *env, jclass cls, jint op, jint src, jint dst, jlong maskFmt,
+  jintArray eltArray, jintArray  glyphIDArray, jint eltCnt, jint glyphCnt) {
+    jint i;
+    jint *ids;
+    jint *elts;
+    XGlyphElt32 *xelts;
+    Glyph *xids;
+    XGlyphElt32 selts[24];
+    Glyph sids[256];
+    int charCnt = 0;
+
+    if (eltCnt <= 24) {
+      xelts = &selts[0];
+    }else {
+      xelts = (XGlyphElt32 *) malloc(sizeof(XGlyphElt32) * eltCnt);
+    }
+
+    if (glyphCnt <= 256) {
+      xids = &sids[0];
+    }else {
+      xids = (Glyph *) malloc(sizeof(Glyph) * glyphCnt);
+    }
+
+    if ((ids = (jint *) (*env)->GetPrimitiveArrayCritical(env, glyphIDArray, NULL)) == NULL) {
+      return;
+    }
+    if ((elts = (jint *)
+          (*env)->GetPrimitiveArrayCritical(env, eltArray, NULL)) == NULL) {
+        (*env)->ReleasePrimitiveArrayCritical(env,
+                                              glyphIDArray, ids, JNI_ABORT);
+      return;
+    }
+
+    for (i=0; i < glyphCnt; i++) {
+      xids[i] = (Glyph) ids[i];
+    }
+
+    for (i=0; i < eltCnt; i++) {
+      xelts[i].nchars = elts[i*4 + 0];
+      xelts[i].xOff = elts[i*4 + 1];
+      xelts[i].yOff = elts[i*4 + 2];
+      xelts[i].glyphset = (GlyphSet) elts[i*4 + 3];
+      xelts[i].chars = (unsigned int *) &xids[charCnt];
+
+      charCnt += xelts[i].nchars;
+    }
+
+    XRenderCompositeText32(awt_display, op, (Picture) src, (Picture) dst,
+                           (XRenderPictFormat *) jlong_to_ptr(maskFmt),
+                            0, 0, 0, 0, xelts, eltCnt);
+
+    (*env)->ReleasePrimitiveArrayCritical(env, glyphIDArray, ids, JNI_ABORT);
+    (*env)->ReleasePrimitiveArrayCritical(env, eltArray, elts, JNI_ABORT);
+
+    if (xelts != &selts[0]) {
+      free(xelts);
+    }
+
+    if (xids != &sids[0]) {
+      free(xids);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_setGCMode
+ (JNIEnv *env, jobject this, jlong gc, jboolean copy) {
+  GC xgc = (GC) jlong_to_ptr(gc);
+
+  if (copy == JNI_TRUE) {
+    XSetFunction(awt_display, xgc, GXcopy);
+  } else {
+    XSetFunction(awt_display, xgc, GXxor);
+  }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_GCRectanglesNative
+ (JNIEnv *env, jclass xsd, jint dst, jlong gc,
+  jintArray rectArray, jint rectCnt) {
+    int i;
+    jint* rects;
+    XRectangle *xRects;
+    XRectangle sRects[256];
+
+    if (rectCnt <= 256) {
+      xRects = &sRects[0];
+    } else {
+      xRects = (XRectangle *) malloc(sizeof(XRectangle) * rectCnt);
+      if (xRects == NULL) {
+        return;
+      }
+    }
+
+    if ((rects = (jint *) (*env)->GetPrimitiveArrayCritical(env, rectArray, NULL)) == NULL) {
+      return;
+    }
+
+    for (i=0; i < rectCnt; i++) {
+      xRects[i].x = rects[i*4 + 0];
+      xRects[i].y = rects[i*4 + 1];
+      xRects[i].width = rects[i*4 + 2];
+      xRects[i].height = rects[i*4 + 3];
+    }
+
+    XFillRectangles(awt_display, (Drawable) dst, (GC) jlong_to_ptr(gc), xRects, rectCnt);
+
+    (*env)->ReleasePrimitiveArrayCritical(env, rectArray, rects, JNI_ABORT);
+    if (xRects != &sRects[0]) {
+      free(xRects);
+    }
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRBackendNative_renderCompositeTrapezoidsNative
+ (JNIEnv *env, jclass cls, jbyte op, jint src, jlong maskFmt,
+ jint dst, jint srcX, jint srcY, jintArray  trapArray) {
+    jint *traps;
+
+    if ((traps = (jint *) (*env)->GetPrimitiveArrayCritical(env, trapArray, NULL)) == NULL) {
+      return;
+    }
+
+    XRenderCompositeTrapezoids(awt_display, op, (Picture) src, (Picture) dst,
+                               (XRenderPictFormat *) jlong_to_ptr(maskFmt),
+                               srcX, srcY, (XTrapezoid *) (traps+5), traps[0]);
+
+    (*env)->ReleasePrimitiveArrayCritical(env, trapArray, traps, JNI_ABORT);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/native/sun/java2d/x11/XRSurfaceData.c	Fri May 28 11:37:44 2010 -0700
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2010 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#include "GraphicsPrimitiveMgr.h"
+#include "Region.h"
+#include "Trace.h"
+#include "X11SurfaceData.h"
+
+/*#include <xcb/xcb.h>*/
+#include <Xrender.h>
+
+#ifndef RepeatNone  /* added in 0.10 */
+#define RepeatNone    0
+#define RepeatNormal  1
+#define RepeatPad     2
+#define RepeatReflect 3
+#endif
+
+
+#include <sys/uio.h>
+#include <dlfcn.h>
+#include <setjmp.h>
+
+#ifndef HEADLESS
+jfieldID pictID;
+jfieldID xidID;
+jfieldID blitMaskPMID;
+jfieldID blitMaskPictID;
+#endif /* !HEADLESS */
+
+JNIEXPORT void JNICALL
+   Java_sun_java2d_xr_XRSurfaceData_initXRPicture(JNIEnv *env, jobject xsd,
+                                                  jlong pXSData,
+                                                  jint pictFormat)
+{
+#ifndef HEADLESS
+
+  X11SDOps *xsdo;
+  XRenderPictFormat *fmt;
+
+  J2dTraceLn(J2D_TRACE_INFO, "in XRSurfaceData_initXRender");
+
+  xsdo = (X11SDOps *) jlong_to_ptr(pXSData);
+  if (xsdo == NULL) {
+      return;
+  }
+
+  if (xsdo->xrPic == None) {
+      XRenderPictureAttributes pict_attr;
+      pict_attr.repeat = RepeatNone;
+      fmt = XRenderFindStandardFormat(awt_display, pictFormat);
+      xsdo->xrPic =
+         XRenderCreatePicture(awt_display, xsdo->drawable, fmt,
+                              CPRepeat, &pict_attr);
+  }
+
+  (*env)->SetIntField (env, xsd, pictID, xsdo->xrPic);
+  (*env)->SetIntField (env, xsd, xidID, xsdo->drawable);
+#endif /* !HEADLESS */
+}
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRSurfaceData_initIDs(JNIEnv *env, jclass xsd)
+{
+#ifndef HEADLESS
+  J2dTraceLn(J2D_TRACE_INFO, "in XRSurfaceData_initIDs");
+
+  pictID = (*env)->GetFieldID(env, xsd, "picture", "I");
+  xidID = (*env)->GetFieldID(env, xsd, "xid", "I");
+
+  XShared_initIDs(env, JNI_FALSE);
+#endif /* !HEADLESS */
+}
+
+
+JNIEXPORT void JNICALL
+Java_sun_java2d_xr_XRSurfaceData_XRInitSurface(JNIEnv *env, jclass xsd,
+                                               jint depth,
+                                               jint width, jint height,
+                                               jlong drawable, jint pictFormat)
+{
+#ifndef HEADLESS
+    X11SDOps *xsdo;
+
+    J2dTraceLn(J2D_TRACE_INFO, "in XRSurfaceData_initSurface");
+
+    xsdo = X11SurfaceData_GetOps(env, xsd);
+    if (xsdo == NULL) {
+        return;
+    }
+
+    XShared_initSurface(env, xsdo, depth, width, height, drawable);
+#endif /* !HEADLESS */
+}