From 15e677fe29164e1d11f364eba1c541587ddb239e Mon Sep 17 00:00:00 2001 From: ceisserer Date: Fri, 28 May 2010 11:37:44 -0700 Subject: 6307603: [X11] Use RENDER extension for complex operations done in software Reviewed-by: bae, igor, prr --- .../classes/sun/font/GlyphDisposedListener.java | 32 + src/share/classes/sun/font/StrikeCache.java | 89 ++- .../classes/sun/java2d/pipe/BufferedPaints.java | 2 +- .../classes/sun/java2d/pipe/RenderBuffer.java | 5 + .../services/sun.java2d.pipe.RenderingEngine | 5 +- src/share/native/sun/font/AccelGlyphCache.c | 1 + src/share/native/sun/font/fontscalerdefs.h | 13 +- src/share/native/sun/font/freetypeScaler.c | 3 +- src/share/native/sun/font/sunFont.c | 11 +- .../native/sun/java2d/opengl/OGLTextRenderer.c | 10 +- src/solaris/classes/sun/awt/X11GraphicsDevice.java | 31 +- .../classes/sun/awt/X11GraphicsEnvironment.java | 40 ++ src/solaris/classes/sun/font/XRGlyphCache.java | 301 ++++++++ .../classes/sun/font/XRGlyphCacheEntry.java | 206 ++++++ src/solaris/classes/sun/font/XRTextRenderer.java | 152 ++++ .../sun/java2d/UnixSurfaceManagerFactory.java | 6 +- .../classes/sun/java2d/jules/IdleTileCache.java | 109 +++ .../sun/java2d/jules/JulesAATileGenerator.java | 349 +++++++++ .../classes/sun/java2d/jules/JulesPathBuf.java | 271 +++++++ .../sun/java2d/jules/JulesRenderingEngine.java | 54 ++ .../classes/sun/java2d/jules/JulesShapePipe.java | 102 +++ .../classes/sun/java2d/jules/JulesTile.java | 67 ++ .../classes/sun/java2d/jules/TileWorker.java | 146 ++++ .../classes/sun/java2d/jules/TrapezoidList.java | 110 +++ .../classes/sun/java2d/x11/X11SurfaceData.java | 29 +- .../classes/sun/java2d/x11/XSurfaceData.java | 40 ++ src/solaris/classes/sun/java2d/xr/DirtyRegion.java | 133 ++++ .../classes/sun/java2d/xr/GrowableByteArray.java | 127 ++++ .../classes/sun/java2d/xr/GrowableEltArray.java | 84 +++ .../classes/sun/java2d/xr/GrowableIntArray.java | 114 +++ .../classes/sun/java2d/xr/GrowablePointArray.java | 62 ++ .../classes/sun/java2d/xr/GrowableRectArray.java | 79 +++ src/solaris/classes/sun/java2d/xr/MaskTile.java | 166 +++++ .../classes/sun/java2d/xr/MaskTileManager.java | 327 +++++++++ .../classes/sun/java2d/xr/MutableInteger.java | 57 ++ .../classes/sun/java2d/xr/XIDGenerator.java | 53 ++ src/solaris/classes/sun/java2d/xr/XRBackend.java | 117 +++ .../classes/sun/java2d/xr/XRBackendNative.java | 343 +++++++++ src/solaris/classes/sun/java2d/xr/XRColor.java | 141 ++++ .../classes/sun/java2d/xr/XRCompositeManager.java | 334 +++++++++ src/solaris/classes/sun/java2d/xr/XRDrawImage.java | 67 ++ .../classes/sun/java2d/xr/XRGraphicsConfig.java | 61 ++ src/solaris/classes/sun/java2d/xr/XRMaskBlit.java | 94 +++ src/solaris/classes/sun/java2d/xr/XRMaskFill.java | 115 +++ src/solaris/classes/sun/java2d/xr/XRMaskImage.java | 129 ++++ .../classes/sun/java2d/xr/XRPMBlitLoops.java | 400 +++++++++++ src/solaris/classes/sun/java2d/xr/XRPaints.java | 314 +++++++++ src/solaris/classes/sun/java2d/xr/XRRenderer.java | 331 +++++++++ .../classes/sun/java2d/xr/XRSurfaceData.java | 668 ++++++++++++++++++ .../classes/sun/java2d/xr/XRSurfaceDataProxy.java | 83 +++ src/solaris/classes/sun/java2d/xr/XRUtils.java | 261 +++++++ .../sun/java2d/xr/XRVolatileSurfaceManager.java | 94 +++ .../classes/sun/java2d/xr/XcbRequestCounter.java | 59 ++ src/solaris/native/sun/java2d/x11/X11SurfaceData.c | 189 +++-- src/solaris/native/sun/java2d/x11/X11SurfaceData.h | 6 + .../native/sun/java2d/x11/XRBackendNative.c | 784 +++++++++++++++++++++ src/solaris/native/sun/java2d/x11/XRSurfaceData.c | 116 +++ 57 files changed, 7970 insertions(+), 122 deletions(-) create mode 100644 src/share/classes/sun/font/GlyphDisposedListener.java create mode 100644 src/solaris/classes/sun/font/XRGlyphCache.java create mode 100644 src/solaris/classes/sun/font/XRGlyphCacheEntry.java create mode 100644 src/solaris/classes/sun/font/XRTextRenderer.java create mode 100644 src/solaris/classes/sun/java2d/jules/IdleTileCache.java create mode 100644 src/solaris/classes/sun/java2d/jules/JulesAATileGenerator.java create mode 100644 src/solaris/classes/sun/java2d/jules/JulesPathBuf.java create mode 100644 src/solaris/classes/sun/java2d/jules/JulesRenderingEngine.java create mode 100644 src/solaris/classes/sun/java2d/jules/JulesShapePipe.java create mode 100644 src/solaris/classes/sun/java2d/jules/JulesTile.java create mode 100644 src/solaris/classes/sun/java2d/jules/TileWorker.java create mode 100644 src/solaris/classes/sun/java2d/jules/TrapezoidList.java create mode 100644 src/solaris/classes/sun/java2d/x11/XSurfaceData.java create mode 100644 src/solaris/classes/sun/java2d/xr/DirtyRegion.java create mode 100644 src/solaris/classes/sun/java2d/xr/GrowableByteArray.java create mode 100644 src/solaris/classes/sun/java2d/xr/GrowableEltArray.java create mode 100644 src/solaris/classes/sun/java2d/xr/GrowableIntArray.java create mode 100644 src/solaris/classes/sun/java2d/xr/GrowablePointArray.java create mode 100644 src/solaris/classes/sun/java2d/xr/GrowableRectArray.java create mode 100644 src/solaris/classes/sun/java2d/xr/MaskTile.java create mode 100644 src/solaris/classes/sun/java2d/xr/MaskTileManager.java create mode 100644 src/solaris/classes/sun/java2d/xr/MutableInteger.java create mode 100644 src/solaris/classes/sun/java2d/xr/XIDGenerator.java create mode 100644 src/solaris/classes/sun/java2d/xr/XRBackend.java create mode 100644 src/solaris/classes/sun/java2d/xr/XRBackendNative.java create mode 100644 src/solaris/classes/sun/java2d/xr/XRColor.java create mode 100644 src/solaris/classes/sun/java2d/xr/XRCompositeManager.java create mode 100644 src/solaris/classes/sun/java2d/xr/XRDrawImage.java create mode 100644 src/solaris/classes/sun/java2d/xr/XRGraphicsConfig.java create mode 100644 src/solaris/classes/sun/java2d/xr/XRMaskBlit.java create mode 100644 src/solaris/classes/sun/java2d/xr/XRMaskFill.java create mode 100644 src/solaris/classes/sun/java2d/xr/XRMaskImage.java create mode 100644 src/solaris/classes/sun/java2d/xr/XRPMBlitLoops.java create mode 100644 src/solaris/classes/sun/java2d/xr/XRPaints.java create mode 100644 src/solaris/classes/sun/java2d/xr/XRRenderer.java create mode 100644 src/solaris/classes/sun/java2d/xr/XRSurfaceData.java create mode 100644 src/solaris/classes/sun/java2d/xr/XRSurfaceDataProxy.java create mode 100644 src/solaris/classes/sun/java2d/xr/XRUtils.java create mode 100644 src/solaris/classes/sun/java2d/xr/XRVolatileSurfaceManager.java create mode 100644 src/solaris/classes/sun/java2d/xr/XcbRequestCounter.java create mode 100644 src/solaris/native/sun/java2d/x11/XRBackendNative.c create mode 100644 src/solaris/native/sun/java2d/x11/XRSurfaceData.c (limited to 'src') 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 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 disposeListeners = new ArrayList(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 0) { + ArrayList 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(); + } + 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 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(); + } + 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 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 cacheMap = new HashMap(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 freeGlyphIDs = new ArrayList(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 glyphPtrList) { + try { + SunToolkit.awtLock(); + + ArrayList glyphIDList = new ArrayList(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 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(); + } + 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 uncachedGlyphs, GlyphList gl, int[] glIndices) { + for (XRGlyphCacheEntry glyph : uncachedGlyphs) { + cachedPixels += glyph.getPixelCnt(); + } + + if (cachedPixels > MAX_CACHED_PIXELS) { + clearCache(glyphs); + } + + boolean containsLCDGlyphs = containsLCDGlyphs(uncachedGlyphs); + List[] seperatedGlyphList = seperateGlyphTypes(uncachedGlyphs, containsLCDGlyphs); + List grayGlyphList = seperatedGlyphList[0]; + List 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 tmpList = new ArrayList(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[] seperateGlyphTypes(List glyphList, boolean containsLCDGlyphs) { + ArrayList lcdGlyphs = null; + ArrayList grayGlyphs = null; + + for (XRGlyphCacheEntry cacheEntry : glyphList) { + if (cacheEntry.isGrayscale(containsLCDGlyphs)) { + if (grayGlyphs == null) { + grayGlyphs = new ArrayList(glyphList.size()); + } + cacheEntry.setGlyphSet(grayGlyphSet); + grayGlyphs.add(cacheEntry); + } else { + if (lcdGlyphs == null) { + lcdGlyphs = new ArrayList(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 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 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 cacheList = new ArrayList(cacheMap.values()); + Collections.sort(cacheList, new Comparator() { + public int compare(XRGlyphCacheEntry e1, XRGlyphCacheEntry e2) { + return e2.getLastUsed() - e1.getLastUsed(); + } + }); + + for (XRGlyphCacheEntry glyph : glyps) { + glyph.setPinned(); + } + + ArrayList deleteGlyphList = new ArrayList(); + 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 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 idleBuffers = new ArrayList(); + + ArrayList idleTileWorkerCacheList = new ArrayList(); + ArrayList idleTileConsumerCacheList = + new ArrayList(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 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() { + 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 rasterizedTileConsumerCache = + new ArrayList(); + final LinkedList rasterizedBuffers = new LinkedList(); + + 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 tiles = new ArrayList(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 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 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(); + 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 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 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 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 argbTmpPM = new WeakReference(null); + static WeakReference rgbTmpPM = new WeakReference(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(vImg); + } else { + argbTmpPM = new WeakReference(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 +#include + /** * 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 +#include +#include "Region.h" +#include "fontscalerdefs.h" + +#include + +#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 +#include + +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 */ +#include + +#ifndef RepeatNone /* added in 0.10 */ +#define RepeatNone 0 +#define RepeatNormal 1 +#define RepeatPad 2 +#define RepeatReflect 3 +#endif + + +#include +#include +#include + +#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 */ +} -- cgit v1.2.3