aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorceisserer <none@none>2010-05-28 11:37:44 -0700
committerceisserer <none@none>2010-05-28 11:37:44 -0700
commit15e677fe29164e1d11f364eba1c541587ddb239e (patch)
tree4b6071c16cc574276e56e03df5af421a9036fbd4
parentcd0377f26ab30e5455bb31546b2609c56e2eaa01 (diff)
6307603: [X11] Use RENDER extension for complex operations done in software
Reviewed-by: bae, igor, prr
-rw-r--r--make/common/Defs-solaris.gmk17
-rw-r--r--make/sun/awt/mapfile-mawt-vers50
-rw-r--r--make/sun/awt/mapfile-vers-linux1
-rw-r--r--make/sun/headless/mapfile-vers15
-rw-r--r--make/sun/jawt/Makefile2
-rw-r--r--make/sun/xawt/FILES_c_unix.gmk4
-rw-r--r--make/sun/xawt/Makefile9
-rw-r--r--make/sun/xawt/mapfile-vers52
-rw-r--r--src/share/classes/sun/font/GlyphDisposedListener.java32
-rw-r--r--src/share/classes/sun/font/StrikeCache.java89
-rw-r--r--src/share/classes/sun/java2d/pipe/BufferedPaints.java2
-rw-r--r--src/share/classes/sun/java2d/pipe/RenderBuffer.java5
-rw-r--r--src/share/classes/sun/java2d/pisces/META-INF/services/sun.java2d.pipe.RenderingEngine5
-rw-r--r--src/share/native/sun/font/AccelGlyphCache.c1
-rw-r--r--src/share/native/sun/font/fontscalerdefs.h13
-rw-r--r--src/share/native/sun/font/freetypeScaler.c3
-rw-r--r--src/share/native/sun/font/sunFont.c11
-rw-r--r--src/share/native/sun/java2d/opengl/OGLTextRenderer.c10
-rw-r--r--src/solaris/classes/sun/awt/X11GraphicsDevice.java31
-rw-r--r--src/solaris/classes/sun/awt/X11GraphicsEnvironment.java40
-rw-r--r--src/solaris/classes/sun/font/XRGlyphCache.java301
-rw-r--r--src/solaris/classes/sun/font/XRGlyphCacheEntry.java206
-rw-r--r--src/solaris/classes/sun/font/XRTextRenderer.java152
-rw-r--r--src/solaris/classes/sun/java2d/UnixSurfaceManagerFactory.java6
-rw-r--r--src/solaris/classes/sun/java2d/jules/IdleTileCache.java109
-rw-r--r--src/solaris/classes/sun/java2d/jules/JulesAATileGenerator.java349
-rw-r--r--src/solaris/classes/sun/java2d/jules/JulesPathBuf.java271
-rw-r--r--src/solaris/classes/sun/java2d/jules/JulesRenderingEngine.java54
-rw-r--r--src/solaris/classes/sun/java2d/jules/JulesShapePipe.java102
-rw-r--r--src/solaris/classes/sun/java2d/jules/JulesTile.java67
-rw-r--r--src/solaris/classes/sun/java2d/jules/TileWorker.java146
-rw-r--r--src/solaris/classes/sun/java2d/jules/TrapezoidList.java110
-rw-r--r--src/solaris/classes/sun/java2d/x11/X11SurfaceData.java29
-rw-r--r--src/solaris/classes/sun/java2d/x11/XSurfaceData.java40
-rw-r--r--src/solaris/classes/sun/java2d/xr/DirtyRegion.java133
-rw-r--r--src/solaris/classes/sun/java2d/xr/GrowableByteArray.java127
-rw-r--r--src/solaris/classes/sun/java2d/xr/GrowableEltArray.java84
-rw-r--r--src/solaris/classes/sun/java2d/xr/GrowableIntArray.java114
-rw-r--r--src/solaris/classes/sun/java2d/xr/GrowablePointArray.java62
-rw-r--r--src/solaris/classes/sun/java2d/xr/GrowableRectArray.java79
-rw-r--r--src/solaris/classes/sun/java2d/xr/MaskTile.java166
-rw-r--r--src/solaris/classes/sun/java2d/xr/MaskTileManager.java327
-rw-r--r--src/solaris/classes/sun/java2d/xr/MutableInteger.java57
-rw-r--r--src/solaris/classes/sun/java2d/xr/XIDGenerator.java53
-rw-r--r--src/solaris/classes/sun/java2d/xr/XRBackend.java117
-rw-r--r--src/solaris/classes/sun/java2d/xr/XRBackendNative.java343
-rw-r--r--src/solaris/classes/sun/java2d/xr/XRColor.java141
-rw-r--r--src/solaris/classes/sun/java2d/xr/XRCompositeManager.java334
-rw-r--r--src/solaris/classes/sun/java2d/xr/XRDrawImage.java67
-rw-r--r--src/solaris/classes/sun/java2d/xr/XRGraphicsConfig.java61
-rw-r--r--src/solaris/classes/sun/java2d/xr/XRMaskBlit.java94
-rw-r--r--src/solaris/classes/sun/java2d/xr/XRMaskFill.java115
-rw-r--r--src/solaris/classes/sun/java2d/xr/XRMaskImage.java129
-rw-r--r--src/solaris/classes/sun/java2d/xr/XRPMBlitLoops.java400
-rw-r--r--src/solaris/classes/sun/java2d/xr/XRPaints.java314
-rw-r--r--src/solaris/classes/sun/java2d/xr/XRRenderer.java331
-rw-r--r--src/solaris/classes/sun/java2d/xr/XRSurfaceData.java668
-rw-r--r--src/solaris/classes/sun/java2d/xr/XRSurfaceDataProxy.java83
-rw-r--r--src/solaris/classes/sun/java2d/xr/XRUtils.java261
-rw-r--r--src/solaris/classes/sun/java2d/xr/XRVolatileSurfaceManager.java94
-rw-r--r--src/solaris/classes/sun/java2d/xr/XcbRequestCounter.java59
-rw-r--r--src/solaris/native/sun/java2d/x11/X11SurfaceData.c189
-rw-r--r--src/solaris/native/sun/java2d/x11/X11SurfaceData.h6
-rw-r--r--src/solaris/native/sun/java2d/x11/XRBackendNative.c784
-rw-r--r--src/solaris/native/sun/java2d/x11/XRSurfaceData.c116
65 files changed, 8078 insertions, 164 deletions
diff --git a/make/common/Defs-solaris.gmk b/make/common/Defs-solaris.gmk
index 5b1d237ca..9d752cc94 100644
--- a/make/common/Defs-solaris.gmk
+++ b/make/common/Defs-solaris.gmk
@@ -639,21 +639,8 @@ AWT_RUNPATH = -R/usr/dt/lib$(ISA_DIR) -R$(OPENWIN_RUNTIME_LIB)
# 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
diff --git a/make/sun/awt/mapfile-mawt-vers b/make/sun/awt/mapfile-mawt-vers
index d47675d7f..c33a0be17 100644
--- a/make/sun/awt/mapfile-mawt-vers
+++ b/make/sun/awt/mapfile-mawt-vers
@@ -312,6 +312,7 @@ SUNWprivate_1.1 {
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 @@ SUNWprivate_1.1 {
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;
diff --git a/make/sun/awt/mapfile-vers-linux b/make/sun/awt/mapfile-vers-linux
index e56dba34e..be582a5b1 100644
--- a/make/sun/awt/mapfile-vers-linux
+++ b/make/sun/awt/mapfile-vers-linux
@@ -425,6 +425,7 @@ SUNWprivate_1.1 {
Java_sun_awt_X11GraphicsEnvironment_initDisplay;
Java_sun_awt_X11GraphicsEnvironment_pRunningXinerama;
Java_sun_awt_X11GraphicsEnvironment_getXineramaCenterPoint;
+ Java_sun_awt_X11GraphicsEnvironment_initXRender;
diff --git a/make/sun/headless/mapfile-vers b/make/sun/headless/mapfile-vers
index cd838a66a..578ef7e67 100644
--- a/make/sun/headless/mapfile-vers
+++ b/make/sun/headless/mapfile-vers
@@ -46,17 +46,20 @@ SUNWprivate_1.1 {
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;
diff --git a/make/sun/jawt/Makefile b/make/sun/jawt/Makefile
index 424a20d1c..fccdc15a0 100644
--- a/make/sun/jawt/Makefile
+++ b/make/sun/jawt/Makefile
@@ -113,7 +113,7 @@ CPPFLAGS += -I$(OPENWIN_HOME)/include \
# 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)
diff --git a/make/sun/xawt/FILES_c_unix.gmk b/make/sun/xawt/FILES_c_unix.gmk
index 5edc18738..352427f0a 100644
--- a/make/sun/xawt/FILES_c_unix.gmk
+++ b/make/sun/xawt/FILES_c_unix.gmk
@@ -80,4 +80,6 @@ FILES_c = \
swing_GTKEngine.c \
swing_GTKStyle.c \
rect.c \
- sun_awt_X11_GtkFileDialogPeer.c
+ sun_awt_X11_GtkFileDialogPeer.c \
+ XRSurfaceData.c \
+ XRBackendNative.c
diff --git a/make/sun/xawt/Makefile b/make/sun/xawt/Makefile
index f9636cd3e..394e9cc8b 100644
--- a/make/sun/xawt/Makefile
+++ b/make/sun/xawt/Makefile
@@ -49,6 +49,11 @@ AUTO_JAVA_PRUNE = WrapperGenerator.java
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 $(SHARE_SRC)/native/sun/java2d/opengl
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 @@ CPPFLAGS += -DXAWT -DXAWT_HACK \
-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
diff --git a/make/sun/xawt/mapfile-vers b/make/sun/xawt/mapfile-vers
index aee09457f..ea4eb40ac 100644
--- a/make/sun/xawt/mapfile-vers
+++ b/make/sun/xawt/mapfile-vers
@@ -192,6 +192,7 @@ SUNWprivate_1.1 {
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 @@ SUNWprivate_1.1 {
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 @@ SUNWprivate_1.1 {
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;
diff --git a/src/share/classes/sun/font/GlyphDisposedListener.java b/src/share/classes/sun/font/GlyphDisposedListener.java
new file mode 100644
index 000000000..41a38380c
--- /dev/null
+++ b/src/share/classes/sun/font/GlyphDisposedListener.java
@@ -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);
+}
diff --git a/src/share/classes/sun/font/StrikeCache.java b/src/share/classes/sun/font/StrikeCache.java
index 9e5b02a86..dd9b1b6da 100644
--- a/src/share/classes/sun/font/StrikeCache.java
+++ b/src/share/classes/sun/font/StrikeCache.java
@@ -31,6 +31,7 @@ import java.lang.ref.Reference;
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 @@ public final class StrikeCache {
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 @@ public final class StrikeCache {
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 @@ public final class StrikeCache {
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 @@ public final class StrikeCache {
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 @@ public final class StrikeCache {
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 @@ public final class StrikeCache {
*/
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 @@ public final class StrikeCache {
* 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 @@ public final class StrikeCache {
* 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 @@ public final class StrikeCache {
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);
diff --git a/src/share/classes/sun/java2d/pipe/BufferedPaints.java b/src/share/classes/sun/java2d/pipe/BufferedPaints.java
index 604590ff6..3ff1b3b15 100644
--- a/src/share/classes/sun/java2d/pipe/BufferedPaints.java
+++ b/src/share/classes/sun/java2d/pipe/BufferedPaints.java
@@ -307,7 +307,7 @@ public class BufferedPaints {
* 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;
diff --git a/src/share/classes/sun/java2d/pipe/RenderBuffer.java b/src/share/classes/sun/java2d/pipe/RenderBuffer.java
index f0b8069a5..cf4e56918 100644
--- a/src/share/classes/sun/java2d/pipe/RenderBuffer.java
+++ b/src/share/classes/sun/java2d/pipe/RenderBuffer.java
@@ -117,6 +117,11 @@ public class RenderBuffer {
curAddress = baseAddress;
}
+ public final RenderBuffer skip(long numBytes) {
+ curAddress += numBytes;
+ return this;
+ }
+
/**
* putByte() methods...
*/
diff --git a/src/share/classes/sun/java2d/pisces/META-INF/services/sun.java2d.pipe.RenderingEngine b/src/share/classes/sun/java2d/pisces/META-INF/services/sun.java2d.pipe.RenderingEngine
index 607ff5905..66b2ae9c6 100644
--- a/src/share/classes/sun/java2d/pisces/META-INF/services/sun.java2d.pipe.RenderingEngine
+++ b/src/share/classes/sun/java2d/pisces/META-INF/services/sun.java2d.pipe.RenderingEngine
@@ -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
diff --git a/src/share/native/sun/font/AccelGlyphCache.c b/src/share/native/sun/font/AccelGlyphCache.c
index 73e94a91c..7d293fd7a 100644
--- a/src/share/native/sun/font/AccelGlyphCache.c
+++ b/src/share/native/sun/font/AccelGlyphCache.c
@@ -325,6 +325,7 @@ AccelGlyphCache_AddCellInfo(GlyphInfo *glyph, CacheCellInfo *cellInfo)
cellInfo->glyphInfo = glyph;
cellInfo->nextGCI = glyph->cellInfo;
glyph->cellInfo = cellInfo;
+ glyph->managed = MANAGED_GLYPH;
}
/**
diff --git a/src/share/native/sun/font/fontscalerdefs.h b/src/share/native/sun/font/fontscalerdefs.h
index d7fd1fbe6..b83f7e00e 100644
--- a/src/share/native/sun/font/fontscalerdefs.h
+++ b/src/share/native/sun/font/fontscalerdefs.h
@@ -84,15 +84,26 @@ typedef float t2kScalar;
#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;
diff --git a/src/share/native/sun/font/freetypeScaler.c b/src/share/native/sun/font/freetypeScaler.c
index 93baaea47..66ec606af 100644
--- a/src/share/native/sun/font/freetypeScaler.c
+++ b/src/share/native/sun/font/freetypeScaler.c
@@ -782,6 +782,7 @@ Java_sun_font_FreetypeFontScaler_getGlyphImageNative(
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 @@ static void addToGP(GPData* gpdata, FT_Outline*outline) {
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;
diff --git a/src/share/native/sun/font/sunFont.c b/src/share/native/sun/font/sunFont.c
index 3bd914518..84fa28f08 100644
--- a/src/share/native/sun/font/sunFont.c
+++ b/src/share/native/sun/font/sunFont.c
@@ -233,7 +233,8 @@ JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeIntMemory
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 @@ JNIEXPORT void JNICALL Java_sun_font_StrikeCache_freeLongMemory
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 @@ Java_sun_font_StrikeCache_getGlyphCacheDescription
GlyphInfo *info;
size_t baseAddr;
- if ((*env)->GetArrayLength(env, results) < 10) {
+ if ((*env)->GetArrayLength(env, results) < 13) {
return;
}
@@ -310,6 +312,9 @@ Java_sun_font_StrikeCache_getGlyphCacheDescription
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);
}
diff --git a/src/share/native/sun/java2d/opengl/OGLTextRenderer.c b/src/share/native/sun/java2d/opengl/OGLTextRenderer.c
index b709be3cc..fa98114f7 100644
--- a/src/share/native/sun/java2d/opengl/OGLTextRenderer.c
+++ b/src/share/native/sun/java2d/opengl/OGLTextRenderer.c
@@ -244,6 +244,7 @@ static void
OGLTR_AddToGlyphCache(GlyphInfo *glyph, jboolean rgbOrder)
{
GLenum pixelFormat;
+ CacheCellInfo *ccinfo;
J2dTraceLn(J2D_TRACE_INFO, "OGLTR_AddToGlyphCache");
@@ -258,11 +259,12 @@ OGLTR_AddToGlyphCache(GlyphInfo *glyph, jboolean rgbOrder)
}
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 @@ OGLTR_DrawGrayscaleGlyphViaCache(OGLContext *oglc,
}
}
- cell = ginfo->cellInfo;
+ cell = (CacheCellInfo *) (ginfo->cellInfo);
cell->timesRendered++;
x1 = (jfloat)x;
@@ -871,7 +873,7 @@ OGLTR_DrawLCDGlyphViaCache(OGLContext *oglc, OGLSDOps *dstOps,
}
}
- cell = ginfo->cellInfo;
+ cell = (CacheCellInfo *) (ginfo->cellInfo);
cell->timesRendered++;
// location of the glyph in the destination's coordinate space
diff --git a/src/solaris/classes/sun/awt/X11GraphicsDevice.java b/src/solaris/classes/sun/awt/X11GraphicsDevice.java
index cd4763033..9be492d66 100644
--- a/src/solaris/classes/sun/awt/X11GraphicsDevice.java
+++ b/src/solaris/classes/sun/awt/X11GraphicsDevice.java
@@ -39,6 +39,7 @@ import java.util.HashSet;
import java.util.HashMap;
import sun.java2d.opengl.GLXGraphicsConfig;
+import sun.java2d.xr.XRGraphicsConfig;
import sun.java2d.loops.SurfaceType;
/**
@@ -152,6 +153,8 @@ public class X11GraphicsDevice
}
boolean glxSupported = X11GraphicsEnvironment.isGLXAvailable();
+ boolean xrenderSupported = X11GraphicsEnvironment.isXRenderAvailable();
+
boolean dbeSupported = isDBESupported();
if (dbeSupported && doubleBufferVisuals == null) {
doubleBufferVisuals = new HashSet();
@@ -167,9 +170,15 @@ public class X11GraphicsDevice
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 @@ public class X11GraphicsDevice
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);
+ }
}
}
}
diff --git a/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java b/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java
index 6ea0756dd..356beb15f 100644
--- a/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java
+++ b/src/solaris/classes/sun/awt/X11GraphicsEnvironment.java
@@ -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.SunGraphicsEnvironment;
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 @@ public class X11GraphicsEnvironment
}
}
+ // 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 @@ public class X11GraphicsEnvironment
"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 @@ public class X11GraphicsEnvironment
}
+
private static boolean glxAvailable;
private static boolean glxVerbose;
@@ -128,6 +156,18 @@ public class X11GraphicsEnvironment
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:
diff --git a/src/solaris/classes/sun/font/XRGlyphCache.java b/src/solaris/classes/sun/font/XRGlyphCache.java
new file mode 100644
index 000000000..82c7c6a87
--- /dev/null
+++ b/src/solaris/classes/sun/font/XRGlyphCache.java
@@ -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());
+ }
+ }
+}
diff --git a/src/solaris/classes/sun/font/XRGlyphCacheEntry.java b/src/solaris/classes/sun/font/XRGlyphCacheEntry.java
new file mode 100644
index 000000000..e7f6281ca
--- /dev/null
+++ b/src/solaris/classes/sun/font/XRGlyphCacheEntry.java
@@ -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;
+ }
+}
diff --git a/src/solaris/classes/sun/font/XRTextRenderer.java b/src/solaris/classes/sun/font/XRTextRenderer.java
new file mode 100644
index 000000000..2787160a5
--- /dev/null
+++ b/src/solaris/classes/sun/font/XRTextRenderer.java
@@ -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();
+ }
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/UnixSurfaceManagerFactory.java b/src/solaris/classes/sun/java2d/UnixSurfaceManagerFactory.java
index 719ae69c1..4a777fb1f 100644
--- a/src/solaris/classes/sun/java2d/UnixSurfaceManagerFactory.java
+++ b/src/solaris/classes/sun/java2d/UnixSurfaceManagerFactory.java
@@ -33,6 +33,7 @@ import sun.awt.image.VolatileSurfaceManager;
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 @@ public class UnixSurfaceManagerFactory extends SurfaceManagerFactory {
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);
}
}
diff --git a/src/solaris/classes/sun/java2d/jules/IdleTileCache.java b/src/solaris/classes/sun/java2d/jules/IdleTileCache.java
new file mode 100644
index 000000000..2ea09a308
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/jules/IdleTileCache.java
@@ -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();
+ }
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/jules/JulesAATileGenerator.java b/src/solaris/classes/sun/java2d/jules/JulesAATileGenerator.java
new file mode 100644
index 000000000..218386ffe
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/jules/JulesAATileGenerator.java
@@ -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;
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/jules/JulesPathBuf.java b/src/solaris/classes/sun/java2d/jules/JulesPathBuf.java
new file mode 100644
index 000000000..00c9407e7
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/jules/JulesPathBuf.java
@@ -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");
+ }
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/jules/JulesRenderingEngine.java b/src/solaris/classes/sun/java2d/jules/JulesRenderingEngine.java
new file mode 100644
index 000000000..c65e1761a
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/jules/JulesRenderingEngine.java
@@ -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;
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/jules/JulesShapePipe.java b/src/solaris/classes/sun/java2d/jules/JulesShapePipe.java
new file mode 100644
index 000000000..22e56d186
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/jules/JulesShapePipe.java
@@ -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();
+ }
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/jules/JulesTile.java b/src/solaris/classes/sun/java2d/jules/JulesTile.java
new file mode 100644
index 000000000..dc973d1d3
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/jules/JulesTile.java
@@ -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;
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/jules/TileWorker.java b/src/solaris/classes/sun/java2d/jules/TileWorker.java
new file mode 100644
index 000000000..8410261f4
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/jules/TileWorker.java
@@ -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);
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/jules/TrapezoidList.java b/src/solaris/classes/sun/java2d/jules/TrapezoidList.java
new file mode 100644
index 000000000..00368f004
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/jules/TrapezoidList.java
@@ -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];
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/x11/X11SurfaceData.java b/src/solaris/classes/sun/java2d/x11/X11SurfaceData.java
index 943f6e73a..8a5647d51 100644
--- a/src/solaris/classes/sun/java2d/x11/X11SurfaceData.java
+++ b/src/solaris/classes/sun/java2d/x11/X11SurfaceData.java
@@ -46,6 +46,7 @@ import sun.awt.SunHints;
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.PixelToShapeConverter;
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 @@ public abstract class X11SurfaceData extends SurfaceData {
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 @@ public abstract class X11SurfaceData extends SurfaceData {
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 @@ public abstract class X11SurfaceData extends SurfaceData {
X11PMBlitLoops.register();
X11PMBlitBgLoops.register();
}
- }
+ }
}
/**
@@ -432,11 +432,11 @@ public abstract class X11SurfaceData extends SurfaceData {
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 @@ public abstract class X11SurfaceData extends SurfaceData {
return sType;
}
- public native void setInvalid();
-
public void invalidate() {
if (isValid()) {
setInvalid();
@@ -628,16 +626,9 @@ public abstract class X11SurfaceData extends SurfaceData {
* 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;
diff --git a/src/solaris/classes/sun/java2d/x11/XSurfaceData.java b/src/solaris/classes/sun/java2d/x11/XSurfaceData.java
new file mode 100644
index 000000000..8e71a80a0
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/x11/XSurfaceData.java
@@ -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);
+}
diff --git a/src/solaris/classes/sun/java2d/xr/DirtyRegion.java b/src/solaris/classes/sun/java2d/xr/DirtyRegion.java
new file mode 100644
index 000000000..2866055b6
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/DirtyRegion.java
@@ -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;
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/GrowableByteArray.java b/src/solaris/classes/sun/java2d/xr/GrowableByteArray.java
new file mode 100644
index 000000000..a8e22fa49
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/GrowableByteArray.java
@@ -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);
+ }
+
+}
diff --git a/src/solaris/classes/sun/java2d/xr/GrowableEltArray.java b/src/solaris/classes/sun/java2d/xr/GrowableEltArray.java
new file mode 100644
index 000000000..88128614a
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/GrowableEltArray.java
@@ -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();
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/GrowableIntArray.java b/src/solaris/classes/sun/java2d/xr/GrowableIntArray.java
new file mode 100644
index 000000000..12c03622c
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/GrowableIntArray.java
@@ -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);
+ }
+
+}
diff --git a/src/solaris/classes/sun/java2d/xr/GrowablePointArray.java b/src/solaris/classes/sun/java2d/xr/GrowablePointArray.java
new file mode 100644
index 000000000..241bff3bb
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/GrowablePointArray.java
@@ -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;
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/GrowableRectArray.java b/src/solaris/classes/sun/java2d/xr/GrowableRectArray.java
new file mode 100644
index 000000000..01a8a6954
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/GrowableRectArray.java
@@ -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);
+ }
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/MaskTile.java b/src/solaris/classes/sun/java2d/xr/MaskTile.java
new file mode 100644
index 000000000..4937b339f
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/MaskTile.java
@@ -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;
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/MaskTileManager.java b/src/solaris/classes/sun/java2d/xr/MaskTileManager.java
new file mode 100644
index 000000000..535e648f4
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/MaskTileManager.java
@@ -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);
+ }
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/MutableInteger.java b/src/solaris/classes/sun/java2d/xr/MutableInteger.java
new file mode 100644
index 000000000..c18894f87
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/MutableInteger.java
@@ -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;
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XIDGenerator.java b/src/solaris/classes/sun/java2d/xr/XIDGenerator.java
new file mode 100644
index 000000000..ffbea0eb0
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XIDGenerator.java
@@ -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);
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XRBackend.java b/src/solaris/classes/sun/java2d/xr/XRBackend.java
new file mode 100644
index 000000000..9589e9429
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XRBackend.java
@@ -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);
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XRBackendNative.java b/src/solaris/classes/sun/java2d/xr/XRBackendNative.java
new file mode 100644
index 000000000..3108b1224
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XRBackendNative.java
@@ -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);
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XRColor.java b/src/solaris/classes/sun/java2d/xr/XRColor.java
new file mode 100644
index 000000000..29200de4b
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XRColor.java
@@ -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;
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java b/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java
new file mode 100644
index 000000000..8a6d4f65f
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java
@@ -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;
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XRDrawImage.java b/src/solaris/classes/sun/java2d/xr/XRDrawImage.java
new file mode 100644
index 000000000..6db898741
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XRDrawImage.java
@@ -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);
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XRGraphicsConfig.java b/src/solaris/classes/sun/java2d/xr/XRGraphicsConfig.java
new file mode 100644
index 000000000..a2c9dac26
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XRGraphicsConfig.java
@@ -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;
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XRMaskBlit.java b/src/solaris/classes/sun/java2d/xr/XRMaskBlit.java
new file mode 100644
index 000000000..ed6a6412a
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XRMaskBlit.java
@@ -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();
+ }
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XRMaskFill.java b/src/solaris/classes/sun/java2d/xr/XRMaskFill.java
new file mode 100644
index 000000000..5ec6c28a4
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XRMaskFill.java
@@ -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();
+ }
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XRMaskImage.java b/src/solaris/classes/sun/java2d/xr/XRMaskImage.java
new file mode 100644
index 000000000..555adcc9e
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XRMaskImage.java
@@ -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);
+ }
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XRPMBlitLoops.java b/src/solaris/classes/sun/java2d/xr/XRPMBlitLoops.java
new file mode 100644
index 000000000..40536066f
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XRPMBlitLoops.java
@@ -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();
+ }
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XRPaints.java b/src/solaris/classes/sun/java2d/xr/XRPaints.java
new file mode 100644
index 000000000..42dec990f
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XRPaints.java
@@ -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));
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XRRenderer.java b/src/solaris/classes/sun/java2d/xr/XRRenderer.java
new file mode 100644
index 000000000..f6333e5e7
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XRRenderer.java
@@ -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();
+ }
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java b/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java
new file mode 100644
index 000000000..8bfbd1098
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java
@@ -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;
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XRSurfaceDataProxy.java b/src/solaris/classes/sun/java2d/xr/XRSurfaceDataProxy.java
new file mode 100644
index 000000000..83c30656e
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XRSurfaceDataProxy.java
@@ -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;
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XRUtils.java b/src/solaris/classes/sun/java2d/xr/XRUtils.java
new file mode 100644
index 000000000..0565b89ec
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XRUtils.java
@@ -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);
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XRVolatileSurfaceManager.java b/src/solaris/classes/sun/java2d/xr/XRVolatileSurfaceManager.java
new file mode 100644
index 000000000..ef8c00987
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XRVolatileSurfaceManager.java
@@ -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);
+ }
+}
diff --git a/src/solaris/classes/sun/java2d/xr/XcbRequestCounter.java b/src/solaris/classes/sun/java2d/xr/XcbRequestCounter.java
new file mode 100644
index 000000000..b6d407f23
--- /dev/null
+++ b/src/solaris/classes/sun/java2d/xr/XcbRequestCounter.java
@@ -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?!?!
+ }
+ }
+}
diff --git a/src/solaris/native/sun/java2d/x11/X11SurfaceData.c b/src/solaris/native/sun/java2d/x11/X11SurfaceData.c
index 8423f1eee..77bc65d2c 100644
--- a/src/solaris/native/sun/java2d/x11/X11SurfaceData.c
+++ b/src/solaris/native/sun/java2d/x11/X11SurfaceData.c
@@ -71,7 +71,7 @@ extern int J2DXErrHandler(Display *display, XErrorEvent *xerr);
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,19 +97,10 @@ static XImage * cachedXImage;
#endif /* !HEADLESS */
-/*
- * Class: sun_java2d_x11_X11SurfaceData
- * Method: initIDs
- * Signature: (Ljava/lang/Class;Z)V
- */
-JNIEXPORT void JNICALL
-Java_sun_java2d_x11_X11SurfaceData_initIDs(JNIEnv *env, jclass xsd,
- jclass XORComp, jboolean tryDGA)
+jboolean XShared_initIDs(JNIEnv *env, jboolean allowShmPixmaps)
{
#ifndef HEADLESS
- void *lib = 0;
-
- union {
+ union {
char c[4];
int i;
} endian;
@@ -117,20 +108,64 @@ Java_sun_java2d_x11_X11SurfaceData_initIDs(JNIEnv *env, jclass xsd,
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;
+ 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
+ * Signature: (Ljava/lang/Class;Z)V
+ */
+JNIEXPORT void JNICALL
+Java_sun_java2d_x11_X11SurfaceData_initIDs(JNIEnv *env, jclass xsd,
+ jclass XORComp, jboolean tryDGA)
+{
+#ifndef HEADLESS
+ if(XShared_initIDs(env, JNI_TRUE))
+ {
+ void *lib = 0;
+
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 @@ Java_sun_java2d_x11_X11SurfaceData_initIDs(JNIEnv *env, jclass xsd,
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 @@ Java_sun_java2d_x11_X11SurfaceData_initIDs(JNIEnv *env, jclass xsd,
* 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,44 +212,42 @@ Java_sun_java2d_x11_X11SurfaceData_isDrawableValid(JNIEnv *env, jobject this)
}
/*
- * Class: sun_java2d_x11_X11SurfaceData
- * Method: isDgaAvailable
+ * Class: sun_java2d_x11_X11SurfaceData
+ * Method: isShmPMAvailable
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL
-Java_sun_java2d_x11_X11SurfaceData_isDgaAvailable(JNIEnv *env, jobject this)
+Java_sun_java2d_x11_X11SurfaceData_isShmPMAvailable(JNIEnv *env, jobject this)
{
-#if defined(HEADLESS) || defined(__linux__)
+#if defined(HEADLESS) || !defined(MITSHM)
return JNI_FALSE;
#else
- return dgaAvailable;
-#endif /* HEADLESS */
+ return useMitShmPixmaps;
+#endif /* HEADLESS, MITSHM */
}
-
/*
* Class: sun_java2d_x11_X11SurfaceData
- * Method: isShmPMAvailable
+ * Method: isDgaAvailable
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL
-Java_sun_java2d_x11_X11SurfaceData_isShmPMAvailable(JNIEnv *env, jobject this)
+Java_sun_java2d_x11_X11SurfaceData_isDgaAvailable(JNIEnv *env, jobject this)
{
-#if defined(HEADLESS) || !defined(MITSHM)
+#if defined(HEADLESS) || defined(__linux__)
return JNI_FALSE;
#else
- return useMitShmPixmaps;
-#endif /* HEADLESS, MITSHM */
+ return dgaAvailable;
+#endif /* HEADLESS */
}
-
/*
* 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 @@ Java_sun_java2d_x11_X11SurfaceData_initOps(JNIEnv *env, jobject xsd,
} else {
xsdo->pixelmask = 0xff;
}
+
+ xsdo->xrPic = None;
#endif /* !HEADLESS */
}
@@ -313,7 +331,7 @@ Java_sun_java2d_x11_X11SurfaceData_initOps(JNIEnv *env, jobject xsd,
* 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 @@ X11SD_Dispose(JNIEnv *env, SurfaceDataOps *ops)
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 @@ X11SD_Dispose(JNIEnv *env, SurfaceDataOps *ops)
* 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,29 +427,10 @@ Java_sun_java2d_x11_X11SurfaceData_setInvalid(JNIEnv *env, jobject xsd)
#endif /* !HEADLESS */
}
-/*
- * Class: sun_java2d_x11_X11SurfaceData
- * Method: initSurface
- * Signature: ()V
- */
-JNIEXPORT void JNICALL
-Java_sun_java2d_x11_X11SurfaceData_initSurface(JNIEnv *env, jclass xsd,
- jint depth,
- jint width, jint height,
- jlong drawable)
+
+jboolean XShared_initSurface(JNIEnv *env, X11SDOps *xsdo, jint depth, jint width, jint height, jlong drawable)
{
#ifndef HEADLESS
- X11SDOps *xsdo = X11SurfaceData_GetOps(env, xsd);
- if (xsdo == NULL) {
- return;
- }
-
- if (xsdo->configData->awt_cmap == (Colormap)NULL) {
- awtJNI_CreateColorData(env, xsdo->configData, 1);
- }
- /* color_data will be initialized in awtJNI_CreateColorData for
- 8-bit visuals */
- xsdo->cData = xsdo->configData->color_data;
if (drawable != (jlong)0) {
/* Double-buffering */
@@ -452,7 +456,7 @@ Java_sun_java2d_x11_X11SurfaceData_initSurface(JNIEnv *env, jclass xsd,
if (xsdo->drawable) {
xsdo->shmPMData.usingShmPixmap = JNI_TRUE;
xsdo->shmPMData.shmPixmap = xsdo->drawable;
- return;
+ return JNI_TRUE;
}
}
#endif /* MITSHM */
@@ -472,7 +476,40 @@ Java_sun_java2d_x11_X11SurfaceData_initSurface(JNIEnv *env, jclass xsd,
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
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_sun_java2d_x11_X11SurfaceData_initSurface(JNIEnv *env, jclass xsd,
+ jint depth,
+ jint width, jint height,
+ jlong drawable)
+{
+#ifndef HEADLESS
+ X11SDOps *xsdo = X11SurfaceData_GetOps(env, xsd);
+ if (xsdo == NULL) {
+ return;
+ }
+
+ if (xsdo->configData->awt_cmap == (Colormap)NULL) {
+ awtJNI_CreateColorData(env, xsdo->configData, 1);
+ }
+ /* color_data will be initialized in awtJNI_CreateColorData for
+ 8-bit visuals */
+ xsdo->cData = xsdo->configData->color_data;
+
+ XShared_initSurface(env, xsdo, depth, width, height, drawable);
+ xsdo->xrPic = NULL;
#endif /* !HEADLESS */
}
@@ -718,7 +755,7 @@ jboolean X11SD_CachedXImageFits(jint width, jint height, jint depth,
}
#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 @@ X11SD_ReleasePixmapWithBg(JNIEnv *env, X11SDOps *xsdo)
* 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 @@ Java_sun_java2d_x11_X11SurfaceData_XCreateGC
* 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 @@ Java_sun_java2d_x11_X11SurfaceData_XResetClip
* 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 @@ Java_sun_java2d_x11_X11SurfaceData_XSetForeground
* 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
diff --git a/src/solaris/native/sun/java2d/x11/X11SurfaceData.h b/src/solaris/native/sun/java2d/x11/X11SurfaceData.h
index d45bbed5e..720f945a0 100644
--- a/src/solaris/native/sun/java2d/x11/X11SurfaceData.h
+++ b/src/solaris/native/sun/java2d/x11/X11SurfaceData.h
@@ -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 @@ struct _X11SDOps {
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_DisposeXImage(XImage * image);
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
diff --git a/src/solaris/native/sun/java2d/x11/XRBackendNative.c b/src/solaris/native/sun/java2d/x11/XRBackendNative.c
new file mode 100644
index 000000000..32cd20a32
--- /dev/null
+++ b/src/solaris/native/sun/java2d/x11/XRBackendNative.c
@@ -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);
+}
diff --git a/src/solaris/native/sun/java2d/x11/XRSurfaceData.c b/src/solaris/native/sun/java2d/x11/XRSurfaceData.c
new file mode 100644
index 000000000..d6d468efb
--- /dev/null
+++ b/src/solaris/native/sun/java2d/x11/XRSurfaceData.c
@@ -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 */
+}