6307603: [X11] Use RENDER extension for complex operations done in software

Reviewed-by: bae, igor, prr
This commit is contained in:
Clemens Eisserer 2010-05-28 11:37:44 -07:00
parent 8b69138923
commit 1771e20459
65 changed files with 8085 additions and 171 deletions

View file

@ -639,21 +639,8 @@ AWT_RUNPATH = -R/usr/dt/lib$(ISA_DIR) -R$(OPENWIN_RUNTIME_LIB)
# in general this is ok to continue to do.
LIBCXX = /usr/lib$(ISA_DIR)/libCrun.so.1
# Math Library (libm.so), do not use -lm.
# There might be two versions of libm.so on the build system:
# libm.so.1 and libm.so.2, and we want libm.so.1.
# Depending on the Solaris release being used to build with,
# /usr/lib/libm.so could point at a libm.so.2, so we are
# explicit here so that the libjvm.so you have built will work on an
# older Solaris release that might not have libm.so.2.
# This is a critical factor in allowing builds on Solaris 10 or newer
# to run on Solaris 8 or 9.
#
# Note: Historically there was also a problem picking up a static version
# of libm.a from the compiler area, but that problem has gone away
# with the newer compilers. Use of libm.a would cause .so bloat.
#
LIBM = /usr/lib$(ISA_DIR)/libm.so.1
# JDK now requires Solaris 10, so pick up libm.so.2
LIBM = /usr/lib$(ISA_DIR)/libm.so.2
# Socket library
LIBSOCKET = -lsocket

View file

@ -312,6 +312,7 @@ SUNWprivate_1.1 {
Java_sun_awt_X11GraphicsEnvironment_initGLX;
Java_sun_awt_X11GraphicsEnvironment_pRunningXinerama;
Java_sun_awt_X11GraphicsEnvironment_getXineramaCenterPoint;
Java_sun_awt_X11GraphicsEnvironment_initXRender;
#Java_sun_awt_motif_MEmbedCanvasPeer_initXEmbedServer;
#Java_sun_awt_motif_MEmbedCanvasPeer_destroyXEmbedServer;
#Java_sun_awt_motif_MEmbedCanvasPeer_isXEmbedActive;
@ -406,18 +407,53 @@ SUNWprivate_1.1 {
Java_sun_java2d_x11_X11SurfaceData_initIDs;
Java_sun_java2d_x11_X11SurfaceData_initOps;
Java_sun_java2d_x11_X11SurfaceData_initSurface;
Java_sun_java2d_x11_X11SurfaceData_isDrawableValid;
Java_sun_java2d_x11_X11SurfaceData_isDgaAvailable;
Java_sun_java2d_x11_X11SurfaceData_isShmPMAvailable;
Java_sun_java2d_x11_X11SurfaceData_setInvalid;
Java_sun_java2d_x11_X11SurfaceData_flushNativeSurface;
Java_sun_java2d_x11_X11SurfaceData_XCreateGC;
Java_sun_java2d_x11_X11SurfaceData_XResetClip;
Java_sun_java2d_x11_X11SurfaceData_XSetClip;
Java_sun_java2d_x11_X11SurfaceData_XSetCopyMode;
Java_sun_java2d_x11_X11SurfaceData_XSetXorMode;
Java_sun_java2d_x11_X11SurfaceData_XSetForeground;
Java_sun_java2d_x11_X11SurfaceData_XSetGraphicsExposures;
Java_sun_java2d_x11_XSurfaceData_initOps;
Java_sun_java2d_x11_XSurfaceData_XCreateGC;
Java_sun_java2d_x11_XSurfaceData_XResetClip;
Java_sun_java2d_x11_XSurfaceData_XSetClip;
Java_sun_java2d_x11_XSurfaceData_flushNativeSurface;
Java_sun_java2d_x11_XSurfaceData_isDrawableValid;
Java_sun_java2d_x11_XSurfaceData_setInvalid;
Java_sun_java2d_x11_XSurfaceData_XSetGraphicsExposures;
Java_sun_java2d_xr_XRSurfaceData_initXRPicture;
Java_sun_java2d_xr_XRSurfaceData_initIDs;
Java_sun_java2d_xr_XRSurfaceData_XRInitSurface;
Java_sun_java2d_xr_XRBackendNative_initIDs;
Java_sun_java2d_xr_XIDGenerator_bufferXIDs;
Java_sun_java2d_xr_XRBackendNative_freeGC;
Java_sun_java2d_xr_XRBackendNative_createGC;
Java_sun_java2d_xr_XRBackendNative_createPixmap;
Java_sun_java2d_xr_XRBackendNative_createPictureNative;
Java_sun_java2d_xr_XRBackendNative_freePicture;
Java_sun_java2d_xr_XRBackendNative_freePixmap;
Java_sun_java2d_xr_XRBackendNative_setPictureRepeat;
Java_sun_java2d_xr_XRBackendNative_setGCExposures;
Java_sun_java2d_xr_XRBackendNative_setGCForeground;
Java_sun_java2d_xr_XRBackendNative_copyArea;
Java_sun_java2d_xr_XRBackendNative_renderComposite;
Java_sun_java2d_xr_XRBackendNative_renderRectangle;
Java_sun_java2d_xr_XRBackendNative_XRenderRectanglesNative;
Java_sun_java2d_xr_XRBackendNative_XRSetTransformNative;
Java_sun_java2d_xr_XRBackendNative_XRCreateLinearGradientPaintNative;
Java_sun_java2d_xr_XRBackendNative_XRCreateRadialGradientPaintNative;
Java_sun_java2d_xr_XRBackendNative_setFilter;
Java_sun_java2d_xr_XRBackendNative_XRSetClipNative;
Java_sun_java2d_xr_XRBackendNative_putMaskNative;
Java_sun_java2d_xr_XRBackendNative_XRAddGlyphsNative;
Java_sun_java2d_xr_XRBackendNative_XRFreeGlyphsNative;
Java_sun_java2d_xr_XRBackendNative_XRenderCreateGlyphSetNative;
Java_sun_java2d_xr_XRBackendNative_XRenderCompositeTextNative;
Java_sun_java2d_xr_XRBackendNative_setGCMode;
Java_sun_java2d_xr_XRBackendNative_GCRectanglesNative;
Java_sun_java2d_xr_XRUtils_initFormatPtrs;
Java_sun_java2d_xr_XRBackendNative_renderCompositeTrapezoidsNative;
XRT_DrawGlyphList;
Java_sun_java2d_opengl_OGLContext_getOGLIdString;
Java_sun_java2d_opengl_OGLMaskFill_maskFill;

View file

@ -425,6 +425,7 @@ SUNWprivate_1.1 {
Java_sun_awt_X11GraphicsEnvironment_initDisplay;
Java_sun_awt_X11GraphicsEnvironment_pRunningXinerama;
Java_sun_awt_X11GraphicsEnvironment_getXineramaCenterPoint;
Java_sun_awt_X11GraphicsEnvironment_initXRender;

View file

@ -46,17 +46,20 @@ SUNWprivate_1.1 {
Java_sun_java2d_x11_X11Renderer_XFillRoundRect;
Java_sun_java2d_x11_X11Renderer_devCopyArea;
Java_sun_java2d_x11_X11SurfaceData_initIDs;
Java_sun_java2d_x11_X11SurfaceData_initOps;
Java_sun_java2d_x11_X11SurfaceData_isDrawableValid;
Java_sun_java2d_x11_X11SurfaceData_initSurface;
Java_sun_java2d_x11_X11SurfaceData_setInvalid;
Java_sun_java2d_x11_X11SurfaceData_XCreateGC;
Java_sun_java2d_x11_X11SurfaceData_XResetClip;
Java_sun_java2d_x11_X11SurfaceData_XSetClip;
Java_sun_java2d_x11_X11SurfaceData_XSetCopyMode;
Java_sun_java2d_x11_X11SurfaceData_XSetXorMode;
Java_sun_java2d_x11_X11SurfaceData_XSetForeground;
Java_sun_java2d_x11_XSurfaceData_initOps;
Java_sun_java2d_x11_XSurfaceData_XCreateGC;
Java_sun_java2d_x11_XSurfaceData_XResetClip;
Java_sun_java2d_x11_XSurfaceData_XSetClip;
Java_sun_java2d_x11_XSurfaceData_flushNativeSurface;
Java_sun_java2d_x11_XSurfaceData_isDrawableValid;
Java_sun_java2d_x11_XSurfaceData_setInvalid;
Java_sun_java2d_x11_XSurfaceData_XSetGraphicsExposures;
X11SurfaceData_GetOps;
Java_java_awt_Font_initIDs;
Java_sun_font_FontConfigManager_getFontConfig;

View file

@ -113,7 +113,7 @@ CPPFLAGS += -I$(OPENWIN_HOME)/include \
# Libraries to link in.
#
ifeq ($(PLATFORM), solaris)
OTHER_LDLIBS = -L$(LIBDIR)/$(LIBARCH) -L$(OPENWIN_LIB) -L$(LIBDIR)/$(LIBARCH)/xawt -lmawt
OTHER_LDLIBS = -L$(LIBDIR)/$(LIBARCH) -L$(OPENWIN_LIB) -L$(LIBDIR)/$(LIBARCH)/xawt -lmawt -L/usr/openwin/sfw/lib$(ISA_DIR) -lXrender
endif # PLATFORM
ifeq ($(PLATFORM), linux)

View file

@ -80,4 +80,6 @@ FILES_c = \
swing_GTKEngine.c \
swing_GTKStyle.c \
rect.c \
sun_awt_X11_GtkFileDialogPeer.c
sun_awt_X11_GtkFileDialogPeer.c \
XRSurfaceData.c \
XRBackendNative.c

View file

@ -49,6 +49,11 @@ AUTO_JAVA_PRUNE = WrapperGenerator.java
LDFLAGS += -L$(OPENWIN_LIB)
# For Xrender extension.
ifeq ($(PLATFORM), solaris)
LDFLAGS += -L/usr/openwin/sfw/lib$(ISA_DIR) -R/usr/openwin/sfw/lib$(ISA_DIR)
endif
ifeq ($(PLATFORM), linux)
LDFLAGS += -lpthread
dummy := $(shell $(MKDIR) -p $(LIB_LOCATION))
@ -88,7 +93,7 @@ vpath %.c $(SHARE_SRC)/native/sun/java2d/opengl
vpath %.c $(PLATFORM_SRC)/native/sun/java2d/opengl
vpath %.c $(PLATFORM_SRC)/native/sun/java2d/x11
OTHER_LDLIBS = $(LIBM) -lawt -lXext -lX11 -ldl \
OTHER_LDLIBS = $(LIBM) -lawt -lXext -lX11 -lXrender -ldl \
$(LDFLAGS_COMMON) $(AWT_RUNPATH) $(OTHER_LDFLAGS) -lXtst -lXi
ifeq ($(PLATFORM), solaris)

View file

@ -192,6 +192,7 @@ SUNWprivate_1.1 {
Java_sun_font_X11FontManager_setNativeFontPath;
Java_sun_awt_X11GraphicsEnvironment_initDisplay;
Java_sun_awt_X11GraphicsEnvironment_initGLX;
Java_sun_awt_X11GraphicsEnvironment_initXRender;
Java_sun_awt_X11GraphicsEnvironment_checkShmExt;
Java_sun_awt_X11GraphicsEnvironment_getNumScreens;
Java_sun_awt_X11GraphicsEnvironment_getDefaultScreenNum;
@ -355,21 +356,52 @@ SUNWprivate_1.1 {
Java_sun_java2d_x11_X11Renderer_XFillRect;
Java_sun_java2d_x11_X11Renderer_XFillRoundRect;
Java_sun_java2d_x11_X11Renderer_devCopyArea;
Java_sun_java2d_x11_X11SurfaceData_setInvalid;
Java_sun_java2d_x11_X11SurfaceData_initIDs;
Java_sun_java2d_x11_X11SurfaceData_isDrawableValid;
Java_sun_java2d_x11_X11SurfaceData_isDgaAvailable;
Java_sun_java2d_x11_X11SurfaceData_isShmPMAvailable;
Java_sun_java2d_x11_X11SurfaceData_initOps;
Java_sun_java2d_x11_X11SurfaceData_initSurface;
Java_sun_java2d_x11_X11SurfaceData_flushNativeSurface;
Java_sun_java2d_x11_X11SurfaceData_XCreateGC;
Java_sun_java2d_x11_X11SurfaceData_XResetClip;
Java_sun_java2d_x11_X11SurfaceData_XSetClip;
Java_sun_java2d_x11_X11SurfaceData_XSetCopyMode;
Java_sun_java2d_x11_X11SurfaceData_XSetXorMode;
Java_sun_java2d_x11_X11SurfaceData_XSetForeground;
Java_sun_java2d_x11_X11SurfaceData_XSetGraphicsExposures;
Java_sun_java2d_x11_XSurfaceData_initOps;
Java_sun_java2d_x11_XSurfaceData_XCreateGC;
Java_sun_java2d_x11_XSurfaceData_XResetClip;
Java_sun_java2d_x11_XSurfaceData_XSetClip;
Java_sun_java2d_x11_XSurfaceData_flushNativeSurface;
Java_sun_java2d_x11_XSurfaceData_isDrawableValid;
Java_sun_java2d_x11_XSurfaceData_setInvalid;
Java_sun_java2d_x11_XSurfaceData_XSetGraphicsExposures;
Java_sun_java2d_xr_XRSurfaceData_initXRPicture;
Java_sun_java2d_xr_XRSurfaceData_initIDs;
Java_sun_java2d_xr_XRSurfaceData_XRInitSurface;
Java_sun_java2d_xr_XRBackendNative_initIDs;
Java_sun_java2d_xr_XRBackendNative_freeGC;
Java_sun_java2d_xr_XRBackendNative_createGC;
Java_sun_java2d_xr_XRBackendNative_createPixmap;
Java_sun_java2d_xr_XRBackendNative_createPictureNative;
Java_sun_java2d_xr_XRBackendNative_freePicture;
Java_sun_java2d_xr_XRBackendNative_freePixmap;
Java_sun_java2d_xr_XRBackendNative_setPictureRepeat;
Java_sun_java2d_xr_XRBackendNative_setGCExposures;
Java_sun_java2d_xr_XRBackendNative_setGCForeground;
Java_sun_java2d_xr_XRBackendNative_copyArea;
Java_sun_java2d_xr_XRBackendNative_renderComposite;
Java_sun_java2d_xr_XRBackendNative_renderRectangle;
Java_sun_java2d_xr_XRBackendNative_XRenderRectanglesNative;
Java_sun_java2d_xr_XRBackendNative_XRSetTransformNative;
Java_sun_java2d_xr_XRBackendNative_XRCreateLinearGradientPaintNative;
Java_sun_java2d_xr_XRBackendNative_XRCreateRadialGradientPaintNative;
Java_sun_java2d_xr_XRBackendNative_setFilter;
Java_sun_java2d_xr_XRBackendNative_XRSetClipNative;
Java_sun_java2d_xr_XRBackendNative_putMaskNative;
Java_sun_java2d_xr_XRBackendNative_XRAddGlyphsNative;
Java_sun_java2d_xr_XRBackendNative_XRFreeGlyphsNative;
Java_sun_java2d_xr_XRBackendNative_XRenderCreateGlyphSetNative;
Java_sun_java2d_xr_XRBackendNative_XRenderCompositeTextNative;
Java_sun_java2d_xr_XRBackendNative_setGCMode;
Java_sun_java2d_xr_XRBackendNative_GCRectanglesNative;
Java_sun_java2d_xr_XRBackendNative_renderCompositeTrapezoidsNative;
Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1arrow;
Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1box;

View file

@ -0,0 +1,32 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.font;
import java.util.*;
public interface GlyphDisposedListener {
public void glyphDisposed(ArrayList<Long> glyphs);
}

View file

@ -31,6 +31,7 @@ import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.*;
import sun.java2d.Disposer;
import sun.java2d.pipe.BufferedContext;
@ -66,6 +67,9 @@ public final class StrikeCache {
static ReferenceQueue refQueue = Disposer.getQueue();
static ArrayList<GlyphDisposedListener> disposeListeners = new ArrayList<GlyphDisposedListener>(1);
/* Reference objects may have their referents cleared when GC chooses.
* During application client start-up there is typically at least one
* GC which causes the hotspot VM to clear soft (not just weak) references
@ -108,6 +112,8 @@ public final class StrikeCache {
static int topLeftXOffset;
static int topLeftYOffset;
static int pixelDataOffset;
static int cacheCellOffset;
static int managedOffset;
static long invisibleGlyphPtr;
/* Native method used to return information used for unsafe
@ -129,7 +135,7 @@ public final class StrikeCache {
static {
long[] nativeInfo = new long[11];
long[] nativeInfo = new long[13];
getGlyphCacheDescription(nativeInfo);
//Can also get address size from Unsafe class :-
//nativeAddressSize = unsafe.addressSize();
@ -144,6 +150,9 @@ public final class StrikeCache {
topLeftYOffset = (int)nativeInfo[8];
pixelDataOffset = (int)nativeInfo[9];
invisibleGlyphPtr = nativeInfo[10];
cacheCellOffset = (int) nativeInfo[11];
managedOffset = (int) nativeInfo[12];
if (nativeAddressSize < 4) {
throw new InternalError("Unexpected address size for font data: " +
nativeAddressSize);
@ -195,10 +204,10 @@ public final class StrikeCache {
private static final void doDispose(FontStrikeDisposer disposer) {
if (disposer.intGlyphImages != null) {
freeIntMemory(disposer.intGlyphImages,
freeCachedIntMemory(disposer.intGlyphImages,
disposer.pScalerContext);
} else if (disposer.longGlyphImages != null) {
freeLongMemory(disposer.longGlyphImages,
freeCachedLongMemory(disposer.longGlyphImages,
disposer.pScalerContext);
} else if (disposer.segIntGlyphImages != null) {
/* NB Now making multiple JNI calls in this case.
@ -207,7 +216,7 @@ public final class StrikeCache {
*/
for (int i=0; i<disposer.segIntGlyphImages.length; i++) {
if (disposer.segIntGlyphImages[i] != null) {
freeIntMemory(disposer.segIntGlyphImages[i],
freeCachedIntMemory(disposer.segIntGlyphImages[i],
disposer.pScalerContext);
/* native will only free the scaler context once */
disposer.pScalerContext = 0L;
@ -218,19 +227,19 @@ public final class StrikeCache {
* for a strike that never was asked to rasterise a glyph.
*/
if (disposer.pScalerContext != 0L) {
freeIntMemory(new int[0], disposer.pScalerContext);
freeCachedIntMemory(new int[0], disposer.pScalerContext);
}
} else if (disposer.segLongGlyphImages != null) {
for (int i=0; i<disposer.segLongGlyphImages.length; i++) {
if (disposer.segLongGlyphImages[i] != null) {
freeLongMemory(disposer.segLongGlyphImages[i],
freeCachedLongMemory(disposer.segLongGlyphImages[i],
disposer.pScalerContext);
disposer.pScalerContext = 0L;
disposer.segLongGlyphImages[i] = null;
}
}
if (disposer.pScalerContext != 0L) {
freeLongMemory(new long[0], disposer.pScalerContext);
freeCachedLongMemory(new long[0], disposer.pScalerContext);
}
} else if (disposer.pScalerContext != 0L) {
/* Rarely a strike may have been created that never cached
@ -238,9 +247,9 @@ public final class StrikeCache {
* context.
*/
if (longAddresses()) {
freeLongMemory(new long[0], disposer.pScalerContext);
freeCachedLongMemory(new long[0], disposer.pScalerContext);
} else {
freeIntMemory(new int[0], disposer.pScalerContext);
freeCachedIntMemory(new int[0], disposer.pScalerContext);
}
}
}
@ -304,6 +313,68 @@ public final class StrikeCache {
private static native void freeIntMemory(int[] glyphPtrs, long pContext);
private static native void freeLongMemory(long[] glyphPtrs, long pContext);
private static void freeCachedIntMemory(int[] glyphPtrs, long pContext) {
synchronized(disposeListeners) {
if (disposeListeners.size() > 0) {
ArrayList<Long> gids = null;
for (int i = 0; i < glyphPtrs.length; i++) {
if (glyphPtrs[i] != 0 && unsafe.getByte(glyphPtrs[i] + managedOffset) == 0
&& unsafe.getInt(glyphPtrs[i] + cacheCellOffset) != 0) {
if (gids == null) {
gids = new ArrayList<Long>();
}
gids.add((long) glyphPtrs[i]);
}
}
if (gids != null) {
notifyDisposeListeners(gids);
}
}
}
freeIntMemory(glyphPtrs, pContext);
}
private static void freeCachedLongMemory(long[] glyphPtrs, long pContext) {
synchronized(disposeListeners) {
if (disposeListeners.size() > 0) {
ArrayList<Long> gids = null;
for (int i=0; i < glyphPtrs.length; i++) {
if (glyphPtrs[i] != 0
&& unsafe.getByte(glyphPtrs[i] + managedOffset) == 0
&& unsafe.getInt(glyphPtrs[i] + cacheCellOffset) != 0) {
if (gids == null) {
gids = new ArrayList<Long>();
}
gids.add((long) glyphPtrs[i]);
}
}
if (gids != null) {
notifyDisposeListeners(gids);
}
}
}
freeLongMemory(glyphPtrs, pContext);
}
public static void addGlyphDisposedListener(GlyphDisposedListener listener) {
synchronized(disposeListeners) {
disposeListeners.add(listener);
}
}
private static void notifyDisposeListeners(ArrayList<Long> glyphs) {
for (GlyphDisposedListener listener : disposeListeners) {
listener.glyphDisposed(glyphs);
}
}
public static Reference getStrikeRef(FontStrike strike) {
return getStrikeRef(strike, cacheRefTypeWeak);

View file

@ -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;

View file

@ -117,6 +117,11 @@ public class RenderBuffer {
curAddress = baseAddress;
}
public final RenderBuffer skip(long numBytes) {
curAddress += numBytes;
return this;
}
/**
* putByte() methods...
*/

View file

@ -1,2 +1,5 @@
# Jules Rendering Engine module
sun.java2d.jules.JulesRenderingEngine
# Pisces Rendering Engine module
sun.java2d.pisces.PiscesRenderingEngine

View file

@ -325,6 +325,7 @@ AccelGlyphCache_AddCellInfo(GlyphInfo *glyph, CacheCellInfo *cellInfo)
cellInfo->glyphInfo = glyph;
cellInfo->nextGCI = glyph->cellInfo;
glyph->cellInfo = cellInfo;
glyph->managed = MANAGED_GLYPH;
}
/**

View file

@ -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;

View file

@ -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;

View file

@ -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);
}

View file

@ -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

View file

@ -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,11 +170,17 @@ public class X11GraphicsDevice
boolean doubleBuffer =
(dbeSupported &&
doubleBufferVisuals.contains(Integer.valueOf(visNum)));
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,12 +252,22 @@ public class X11GraphicsDevice
doubleBuffer =
doubleBufferVisuals.contains(Integer.valueOf(visNum));
}
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);
}
}
}
}
private static native void enterFullScreenExclusive(long window);
private static native void exitFullScreenExclusive(long window);

View file

@ -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:

View file

@ -0,0 +1,301 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.font;
import java.io.*;
import java.util.*;
import sun.awt.*;
import sun.java2d.xr.*;
/**
* Glyph cache used by the XRender pipeline.
*
* @author Clemens Eisserer
*/
public class XRGlyphCache implements GlyphDisposedListener {
XRBackend con;
XRCompositeManager maskBuffer;
HashMap<MutableInteger, XRGlyphCacheEntry> cacheMap = new HashMap<MutableInteger, XRGlyphCacheEntry>(256);
int nextID = 1;
MutableInteger tmp = new MutableInteger(0);
int grayGlyphSet;
int lcdGlyphSet;
int time = 0;
int cachedPixels = 0;
static final int MAX_CACHED_PIXELS = 100000;
ArrayList<Integer> freeGlyphIDs = new ArrayList<Integer>(255);
static final boolean batchGlyphUpload = true; // Boolean.parseBoolean(System.getProperty("sun.java2d.xrender.batchGlyphUpload"));
public XRGlyphCache(XRCompositeManager maskBuf) {
this.con = maskBuf.getBackend();
this.maskBuffer = maskBuf;
grayGlyphSet = con.XRenderCreateGlyphSet(XRUtils.PictStandardA8);
lcdGlyphSet = con.XRenderCreateGlyphSet(XRUtils.PictStandardARGB32);
StrikeCache.addGlyphDisposedListener(this);
}
public void glyphDisposed(ArrayList<Long> glyphPtrList) {
try {
SunToolkit.awtLock();
ArrayList<Integer> glyphIDList = new ArrayList<Integer>(glyphPtrList.size());
for (long glyphPtr : glyphPtrList) {
glyphIDList.add(XRGlyphCacheEntry.getGlyphID(glyphPtr));
}
freeGlyphs(glyphIDList);
} finally {
SunToolkit.awtUnlock();
}
}
protected int getFreeGlyphID() {
if (freeGlyphIDs.size() > 0) {
int newID = freeGlyphIDs.remove(freeGlyphIDs.size() - 1);
;
return newID;
}
return nextID++;
}
protected XRGlyphCacheEntry getEntryForPointer(long imgPtr) {
int id = XRGlyphCacheEntry.getGlyphID(imgPtr);
if (id == 0) {
return null;
}
tmp.setValue(id);
return cacheMap.get(tmp);
}
public XRGlyphCacheEntry[] cacheGlyphs(GlyphList glyphList) {
time++;
XRGlyphCacheEntry[] entries = new XRGlyphCacheEntry[glyphList.getNumGlyphs()];
long[] imgPtrs = glyphList.getImages();
ArrayList<XRGlyphCacheEntry> uncachedGlyphs = null;
for (int i = 0; i < glyphList.getNumGlyphs(); i++) {
XRGlyphCacheEntry glyph;
// Find uncached glyphs and queue them for upload
if ((glyph = getEntryForPointer(imgPtrs[i])) == null) {
glyph = new XRGlyphCacheEntry(imgPtrs[i], glyphList);
glyph.setGlyphID(getFreeGlyphID());
cacheMap.put(new MutableInteger(glyph.getGlyphID()), glyph);
if (uncachedGlyphs == null) {
uncachedGlyphs = new ArrayList<XRGlyphCacheEntry>();
}
uncachedGlyphs.add(glyph);
}
glyph.setLastUsed(time);
entries[i] = glyph;
}
// Add glyphs to cache
if (uncachedGlyphs != null) {
uploadGlyphs(entries, uncachedGlyphs, glyphList, null);
}
return entries;
}
protected void uploadGlyphs(XRGlyphCacheEntry[] glyphs, ArrayList<XRGlyphCacheEntry> uncachedGlyphs, GlyphList gl, int[] glIndices) {
for (XRGlyphCacheEntry glyph : uncachedGlyphs) {
cachedPixels += glyph.getPixelCnt();
}
if (cachedPixels > MAX_CACHED_PIXELS) {
clearCache(glyphs);
}
boolean containsLCDGlyphs = containsLCDGlyphs(uncachedGlyphs);
List<XRGlyphCacheEntry>[] seperatedGlyphList = seperateGlyphTypes(uncachedGlyphs, containsLCDGlyphs);
List<XRGlyphCacheEntry> grayGlyphList = seperatedGlyphList[0];
List<XRGlyphCacheEntry> lcdGlyphList = seperatedGlyphList[1];
/*
* Some XServers crash when uploading multiple glyphs at once. TODO:
* Implement build-switch in local case for distributors who know their
* XServer is fixed
*/
if (batchGlyphUpload) {
if (grayGlyphList != null && grayGlyphList.size() > 0) {
con.XRenderAddGlyphs(grayGlyphSet, gl, grayGlyphList, generateGlyphImageStream(grayGlyphList));
}
if (lcdGlyphList != null && lcdGlyphList.size() > 0) {
con.XRenderAddGlyphs(lcdGlyphSet, gl, lcdGlyphList, generateGlyphImageStream(lcdGlyphList));
}
} else {
ArrayList<XRGlyphCacheEntry> tmpList = new ArrayList<XRGlyphCacheEntry>(1);
tmpList.add(null);
for (XRGlyphCacheEntry entry : uncachedGlyphs) {
tmpList.set(0, entry);
if (entry.getGlyphSet() == grayGlyphSet) {
con.XRenderAddGlyphs(grayGlyphSet, gl, tmpList, generateGlyphImageStream(tmpList));
} else {
con.XRenderAddGlyphs(lcdGlyphSet, gl, tmpList, generateGlyphImageStream(tmpList));
}
}
}
}
/**
* Seperates lcd and grayscale glyphs queued for upload, and sets the
* appropriate glyphset for the cache entries.
*/
protected List<XRGlyphCacheEntry>[] seperateGlyphTypes(List<XRGlyphCacheEntry> glyphList, boolean containsLCDGlyphs) {
ArrayList<XRGlyphCacheEntry> lcdGlyphs = null;
ArrayList<XRGlyphCacheEntry> grayGlyphs = null;
for (XRGlyphCacheEntry cacheEntry : glyphList) {
if (cacheEntry.isGrayscale(containsLCDGlyphs)) {
if (grayGlyphs == null) {
grayGlyphs = new ArrayList<XRGlyphCacheEntry>(glyphList.size());
}
cacheEntry.setGlyphSet(grayGlyphSet);
grayGlyphs.add(cacheEntry);
} else {
if (lcdGlyphs == null) {
lcdGlyphs = new ArrayList<XRGlyphCacheEntry>(glyphList.size());
}
cacheEntry.setGlyphSet(lcdGlyphSet);
lcdGlyphs.add(cacheEntry);
}
}
return new List[] { grayGlyphs, lcdGlyphs };
}
/**
* Copies the glyph-images into a continous buffer, required for uploading.
*/
protected byte[] generateGlyphImageStream(List<XRGlyphCacheEntry> glyphList) {
boolean isLCDGlyph = glyphList.get(0).getGlyphSet() == lcdGlyphSet;
ByteArrayOutputStream stream = new ByteArrayOutputStream((isLCDGlyph ? 4 : 1) * 48 * glyphList.size());
for (XRGlyphCacheEntry cacheEntry : glyphList) {
cacheEntry.writePixelData(stream, isLCDGlyph);
}
return stream.toByteArray();
}
protected boolean containsLCDGlyphs(List<XRGlyphCacheEntry> entries) {
boolean containsLCDGlyphs = false;
for (XRGlyphCacheEntry entry : entries) {
containsLCDGlyphs = !(entry.getSourceRowBytes() == entry.getWidth());
if (containsLCDGlyphs) {
return true;
}
}
return false;
}
protected void clearCache(XRGlyphCacheEntry[] glyps) {
/*
* Glyph uploading is so slow anyway, we can afford some inefficiency
* here, as the cache should usually be quite small. TODO: Implement
* something not that stupid ;)
*/
ArrayList<XRGlyphCacheEntry> cacheList = new ArrayList<XRGlyphCacheEntry>(cacheMap.values());
Collections.sort(cacheList, new Comparator<XRGlyphCacheEntry>() {
public int compare(XRGlyphCacheEntry e1, XRGlyphCacheEntry e2) {
return e2.getLastUsed() - e1.getLastUsed();
}
});
for (XRGlyphCacheEntry glyph : glyps) {
glyph.setPinned();
}
ArrayList<Integer> deleteGlyphList = new ArrayList<Integer>();
int pixelsToRelease = cachedPixels - MAX_CACHED_PIXELS;
for (int i = cacheList.size() - 1; i >= 0 && pixelsToRelease > 0; i--) {
XRGlyphCacheEntry entry = cacheList.get(i);
if (!entry.isPinned()) {
pixelsToRelease -= entry.getPixelCnt();
deleteGlyphList.add(new Integer(entry.getGlyphID()));
}
}
for (XRGlyphCacheEntry glyph : glyps) {
glyph.setUnpinned();
}
freeGlyphs(deleteGlyphList);
}
private void freeGlyphs(List<Integer> glyphIdList) {
freeGlyphIDs.addAll(glyphIdList);
GrowableIntArray removedLCDGlyphs = new GrowableIntArray(1, 1);
GrowableIntArray removedGrayscaleGlyphs = new GrowableIntArray(1, 1);
for (Integer glyphId : glyphIdList) {
tmp.setValue(glyphId.intValue());
XRGlyphCacheEntry entry = cacheMap.get(tmp);
cachedPixels -= entry.getPixelCnt();
int removedGlyphID = entry.getGlyphID();
tmp.setValue(removedGlyphID);
cacheMap.remove(tmp);
if (entry.getGlyphSet() == grayGlyphSet) {
removedGrayscaleGlyphs.addInt(removedGlyphID);
} else {
removedLCDGlyphs.addInt(removedGlyphID);
}
entry.setGlyphID(0);
}
if (removedGrayscaleGlyphs.getSize() > 0) {
con.XRenderFreeGlyphs(grayGlyphSet, removedGrayscaleGlyphs.getSizedArray());
}
if (removedLCDGlyphs.getSize() > 0) {
con.XRenderFreeGlyphs(lcdGlyphSet, removedLCDGlyphs.getSizedArray());
}
}
}

View file

@ -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;
}
}

View file

@ -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();
}
}
}

View file

@ -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,8 +55,11 @@ public class UnixSurfaceManagerFactory extends SurfaceManagerFactory {
Object context)
{
GraphicsConfiguration gc = vImg.getGraphicsConfig();
if (gc instanceof GLXGraphicsConfig) {
return new GLXVolatileSurfaceManager(vImg, context);
} else if(gc instanceof XRGraphicsConfig) {
return new XRVolatileSurfaceManager(vImg, context);
}else {
return new X11VolatileSurfaceManager(vImg, context);
}

View file

@ -0,0 +1,109 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.java2d.jules;
import java.util.*;
public class IdleTileCache {
final static int IDLE_TILE_SYNC_GRANULARITY = 16;
final static ArrayList<JulesTile> idleBuffers = new ArrayList<JulesTile>();
ArrayList<JulesTile> idleTileWorkerCacheList = new ArrayList<JulesTile>();
ArrayList<JulesTile> idleTileConsumerCacheList =
new ArrayList<JulesTile>(IDLE_TILE_SYNC_GRANULARITY);
/**
* Return a cached Tile, if possible from cache.
* Allowed caller: Rasterizer/Producer-Thread
*
* @param: maxCache - Specify the maximum amount of tiles needed
*/
public JulesTile getIdleTileWorker(int maxCache) {
/* Try to fetch idle tiles from the global cache list */
if (idleTileWorkerCacheList.size() == 0) {
idleTileWorkerCacheList.ensureCapacity(maxCache);
synchronized (idleBuffers) {
for (int i = 0; i < maxCache && idleBuffers.size() > 0; i++) {
idleTileWorkerCacheList.add(
idleBuffers.remove(idleBuffers.size() - 1));
}
}
}
if (idleTileWorkerCacheList.size() > 0) {
return idleTileWorkerCacheList.remove(idleTileWorkerCacheList.size() - 1);
}
return new JulesTile();
}
/**
* Release tile and allow it to be re-used by another thread. Allowed
* Allowed caller: MaskBlit/Consumer-Thread
*/
public void releaseTile(JulesTile tile) {
if (tile != null && tile.hasBuffer()) {
idleTileConsumerCacheList.add(tile);
if (idleTileConsumerCacheList.size() > IDLE_TILE_SYNC_GRANULARITY) {
synchronized (idleBuffers) {
idleBuffers.addAll(idleTileConsumerCacheList);
}
idleTileConsumerCacheList.clear();
}
}
}
/**
* Releases thread-local tiles cached for use by the rasterizing thread.
* Allowed caller: Rasterizer/Producer-Thread
*/
public void disposeRasterizerResources() {
releaseTiles(idleTileWorkerCacheList);
}
/**
* Releases thread-local tiles cached for performance reasons. Allowed
* Allowed caller: MaskBlit/Consumer-Thread
*/
public void disposeConsumerResources() {
releaseTiles(idleTileConsumerCacheList);
}
/**
* Release a list of tiles and allow it to be re-used by another thread.
* Thread safe.
*/
public void releaseTiles(List<JulesTile> tileList) {
if (tileList.size() > 0) {
synchronized (idleBuffers) {
idleBuffers.addAll(tileList);
}
tileList.clear();
}
}
}

View file

@ -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;
}
}

View file

@ -0,0 +1,271 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.java2d.jules;
import java.awt.*;
import java.awt.geom.*;
import sun.awt.X11GraphicsEnvironment;
import sun.java2d.pipe.*;
import sun.java2d.xr.*;
public class JulesPathBuf {
static final double[] emptyDash = new double[0];
private static final byte CAIRO_PATH_OP_MOVE_TO = 0;
private static final byte CAIRO_PATH_OP_LINE_TO = 1;
private static final byte CAIRO_PATH_OP_CURVE_TO = 2;
private static final byte CAIRO_PATH_OP_CLOSE_PATH = 3;
private static final int CAIRO_FILL_RULE_WINDING = 0;
private static final int CAIRO_FILL_RULE_EVEN_ODD = 1;
GrowablePointArray points = new GrowablePointArray(128);
GrowableByteArray ops = new GrowableByteArray(1, 128);
int[] xTrapArray = new int[512];
private static final boolean isCairoAvailable;
static {
isCairoAvailable =
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Boolean>() {
public Boolean run() {
boolean loadSuccess = false;
if (X11GraphicsEnvironment.isXRenderAvailable()) {
try {
System.loadLibrary("jules");
loadSuccess = true;
if (X11GraphicsEnvironment.isXRenderVerbose()) {
System.out.println(
"Xrender: INFO: Jules library loaded");
}
} catch (UnsatisfiedLinkError ex) {
loadSuccess = false;
if (X11GraphicsEnvironment.isXRenderVerbose()) {
System.out.println(
"Xrender: INFO: Jules library not installed.");
}
}
}
return Boolean.valueOf(loadSuccess);
}
});
}
public static boolean isCairoAvailable() {
return isCairoAvailable;
}
public TrapezoidList tesselateFill(Shape s, AffineTransform at, Region clip) {
int windingRule = convertPathData(s, at);
xTrapArray[0] = 0;
xTrapArray = tesselateFillNative(points.getArray(), ops.getArray(),
points.getSize(), ops.getSize(),
xTrapArray, xTrapArray.length,
getCairoWindingRule(windingRule),
clip.getLoX(), clip.getLoY(),
clip.getHiX(), clip.getHiY());
return new TrapezoidList(xTrapArray);
}
public TrapezoidList tesselateStroke(Shape s, BasicStroke bs, boolean thin,
boolean adjust, boolean antialias,
AffineTransform at, Region clip) {
float lw;
if (thin) {
if (antialias) {
lw = 0.5f;
} else {
lw = 1.0f;
}
} else {
lw = bs.getLineWidth();
}
convertPathData(s, at);
double[] dashArray = floatToDoubleArray(bs.getDashArray());
xTrapArray[0] = 0;
xTrapArray =
tesselateStrokeNative(points.getArray(), ops.getArray(),
points.getSize(), ops.getSize(),
xTrapArray, xTrapArray.length, lw,
bs.getEndCap(), bs.getLineJoin(),
bs.getMiterLimit(), dashArray,
dashArray.length, bs.getDashPhase(),
1, 0, 0, 0, 1, 0,
clip.getLoX(), clip.getLoY(),
clip.getHiX(), clip.getHiY());
return new TrapezoidList(xTrapArray);
}
protected double[] floatToDoubleArray(float[] dashArrayFloat) {
double[] dashArrayDouble = emptyDash;
if (dashArrayFloat != null) {
dashArrayDouble = new double[dashArrayFloat.length];
for (int i = 0; i < dashArrayFloat.length; i++) {
dashArrayDouble[i] = dashArrayFloat[i];
}
}
return dashArrayDouble;
}
protected int convertPathData(Shape s, AffineTransform at) {
PathIterator pi = s.getPathIterator(at);
double[] coords = new double[6];
double currX = 0;
double currY = 0;
while (!pi.isDone()) {
int curOp = pi.currentSegment(coords);
int pointIndex;
switch (curOp) {
case PathIterator.SEG_MOVETO:
ops.addByte(CAIRO_PATH_OP_MOVE_TO);
pointIndex = points.getNextIndex();
points.setX(pointIndex, DoubleToCairoFixed(coords[0]));
points.setY(pointIndex, DoubleToCairoFixed(coords[1]));
currX = coords[0];
currY = coords[1];
break;
case PathIterator.SEG_LINETO:
ops.addByte(CAIRO_PATH_OP_LINE_TO);
pointIndex = points.getNextIndex();
points.setX(pointIndex, DoubleToCairoFixed(coords[0]));
points.setY(pointIndex, DoubleToCairoFixed(coords[1]));
currX = coords[0];
currY = coords[1];
break;
/**
* q0 = p0
* q1 = (p0+2*p1)/3
* q2 = (p2+2*p1)/3
* q3 = p2
*/
case PathIterator.SEG_QUADTO:
double x1 = coords[0];
double y1 = coords[1];
double x2, y2;
double x3 = coords[2];
double y3 = coords[3];
x2 = x1 + (x3 - x1) / 3;
y2 = y1 + (y3 - y1) / 3;
x1 = currX + 2 * (x1 - currX) / 3;
y1 =currY + 2 * (y1 - currY) / 3;
ops.addByte(CAIRO_PATH_OP_CURVE_TO);
pointIndex = points.getNextIndex();
points.setX(pointIndex, DoubleToCairoFixed(x1));
points.setY(pointIndex, DoubleToCairoFixed(y1));
pointIndex = points.getNextIndex();
points.setX(pointIndex, DoubleToCairoFixed(x2));
points.setY(pointIndex, DoubleToCairoFixed(y2));
pointIndex = points.getNextIndex();
points.setX(pointIndex, DoubleToCairoFixed(x3));
points.setY(pointIndex, DoubleToCairoFixed(y3));
currX = x3;
currY = y3;
break;
case PathIterator.SEG_CUBICTO:
ops.addByte(CAIRO_PATH_OP_CURVE_TO);
pointIndex = points.getNextIndex();
points.setX(pointIndex, DoubleToCairoFixed(coords[0]));
points.setY(pointIndex, DoubleToCairoFixed(coords[1]));
pointIndex = points.getNextIndex();
points.setX(pointIndex, DoubleToCairoFixed(coords[2]));
points.setY(pointIndex, DoubleToCairoFixed(coords[3]));
pointIndex = points.getNextIndex();
points.setX(pointIndex, DoubleToCairoFixed(coords[4]));
points.setY(pointIndex, DoubleToCairoFixed(coords[5]));
currX = coords[4];
currY = coords[5];
break;
case PathIterator.SEG_CLOSE:
ops.addByte(CAIRO_PATH_OP_CLOSE_PATH);
break;
}
pi.next();
}
return pi.getWindingRule();
}
private static native int[]
tesselateStrokeNative(int[] pointArray, byte[] ops,
int pointCnt, int opCnt,
int[] xTrapArray, int xTrapArrayLength,
double lineWidth, int lineCap, int lineJoin,
double miterLimit, double[] dashArray,
int dashCnt, double offset,
double m00, double m01, double m02,
double m10, double m11, double m12,
int clipLowX, int clipLowY,
int clipWidth, int clipHeight);
private static native int[]
tesselateFillNative(int[] pointArray, byte[] ops, int pointCnt,
int opCnt, int[] xTrapArray, int xTrapArrayLength,
int windingRule, int clipLowX, int clipLowY, int clipWidth, int clipHeight);
public void clear() {
points.clear();
ops.clear();
xTrapArray[0] = 0;
}
private static int DoubleToCairoFixed(double dbl) {
return (int) (dbl * 256);
}
private static int getCairoWindingRule(int j2dWindingRule) {
switch(j2dWindingRule) {
case PathIterator.WIND_EVEN_ODD:
return CAIRO_FILL_RULE_EVEN_ODD;
case PathIterator.WIND_NON_ZERO:
return CAIRO_FILL_RULE_WINDING;
default:
throw new IllegalArgumentException("Illegal Java2D winding rule specified");
}
}
}

View file

@ -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;
}
}

View file

@ -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();
}
}
}

View file

@ -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;
}
}

View file

@ -0,0 +1,146 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.java2d.jules;
import java.util.*;
public class TileWorker implements Runnable {
final static int RASTERIZED_TILE_SYNC_GRANULARITY = 8;
final ArrayList<JulesTile> rasterizedTileConsumerCache =
new ArrayList<JulesTile>();
final LinkedList<JulesTile> rasterizedBuffers = new LinkedList<JulesTile>();
IdleTileCache tileCache;
JulesAATileGenerator tileGenerator;
int workerStartIndex;
volatile int consumerPos = 0;
/* Threading statistics */
int mainThreadCnt = 0;
int workerCnt = 0;
int doubled = 0;
public TileWorker(JulesAATileGenerator tileGenerator, int workerStartIndex, IdleTileCache tileCache) {
this.tileGenerator = tileGenerator;
this.workerStartIndex = workerStartIndex;
this.tileCache = tileCache;
}
public void run() {
ArrayList<JulesTile> tiles = new ArrayList<JulesTile>(16);
for (int i = workerStartIndex; i < tileGenerator.getTileCount(); i++) {
TileTrapContainer tile = tileGenerator.getTrapContainer(i);
if (tile != null && tile.getTileAlpha() == 127) {
JulesTile rasterizedTile =
tileGenerator.rasterizeTile(i,
tileCache.getIdleTileWorker(
tileGenerator.getTileCount() - i - 1));
tiles.add(rasterizedTile);
if (tiles.size() > RASTERIZED_TILE_SYNC_GRANULARITY) {
addRasterizedTiles(tiles);
tiles.clear();
}
}
i = Math.max(i, consumerPos + RASTERIZED_TILE_SYNC_GRANULARITY / 2);
}
addRasterizedTiles(tiles);
tileCache.disposeRasterizerResources();
}
/**
* Returns a rasterized tile for the specified tilePos,
* or null if it isn't available.
* Allowed caller: MaskBlit/Consumer-Thread
*/
public JulesTile getPreRasterizedTile(int tilePos) {
JulesTile tile = null;
if (rasterizedTileConsumerCache.size() == 0 &&
tilePos >= workerStartIndex)
{
synchronized (rasterizedBuffers) {
rasterizedTileConsumerCache.addAll(rasterizedBuffers);
rasterizedBuffers.clear();
}
}
while (tile == null && rasterizedTileConsumerCache.size() > 0) {
JulesTile t = rasterizedTileConsumerCache.get(0);
if (t.getTilePos() > tilePos) {
break;
}
if (t.getTilePos() < tilePos) {
tileCache.releaseTile(t);
doubled++;
}
if (t.getTilePos() <= tilePos) {
rasterizedTileConsumerCache.remove(0);
}
if (t.getTilePos() == tilePos) {
tile = t;
}
}
if (tile == null) {
mainThreadCnt++;
// If there are no tiles left, tell the producer the current
// position. This avoids producing tiles twice.
consumerPos = tilePos;
} else {
workerCnt++;
}
return tile;
}
private void addRasterizedTiles(ArrayList<JulesTile> tiles) {
synchronized (rasterizedBuffers) {
rasterizedBuffers.addAll(tiles);
}
}
/**
* Releases cached tiles.
* Allowed caller: MaskBlit/Consumer-Thread
*/
public void disposeConsumerResources() {
synchronized (rasterizedBuffers) {
tileCache.releaseTiles(rasterizedBuffers);
}
tileCache.releaseTiles(rasterizedTileConsumerCache);
}
}

View file

@ -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];
}
}

View file

@ -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"));
@ -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;

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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();
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}
}

View file

@ -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;
}
}

View file

@ -0,0 +1,327 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.java2d.xr;
import java.awt.*;
import java.util.*;
/**
* We render non-antialiased geometry (consisting of rectangles) into a mask,
* which is later used in a composition step.
* To avoid mask-allocations of large size, MaskTileManager splits
* geometry larger than MASK_SIZE into several tiles,
* and stores the geometry in instances of MaskTile.
*
* @author Clemens Eisserer
*/
public class MaskTileManager {
public static final int MASK_SIZE = 256;
MaskTile mainTile = new MaskTile();
ArrayList<MaskTile> tileList;
int allocatedTiles = 0;
int xTiles, yTiles;
XRCompositeManager xrMgr;
XRBackend con;
int maskPixmap;
int maskPicture;
long maskGC;
int lineMaskPixmap;
int lineMaskPicture;
long drawLineGC;
long clearLineGC;
public MaskTileManager(XRCompositeManager xrMgr, int parentXid) {
tileList = new ArrayList<MaskTile>();
this.xrMgr = xrMgr;
this.con = xrMgr.getBackend();
maskPixmap = con.createPixmap(parentXid, 8, MASK_SIZE, MASK_SIZE);
maskPicture = con.createPicture(maskPixmap, XRUtils.PictStandardA8);
con.renderRectangle(maskPicture, XRUtils.PictOpClear,
new XRColor(Color.black),
0, 0, MASK_SIZE, MASK_SIZE);
maskGC = con.createGC(maskPixmap);
con.setGCExposures(maskGC, false);
lineMaskPixmap = con.createPixmap(parentXid, 8, MASK_SIZE, MASK_SIZE);
lineMaskPicture =
con.createPicture(lineMaskPixmap, XRUtils.PictStandardA8);
con.renderRectangle(lineMaskPicture, XRUtils.PictOpClear,
new XRColor(Color.black), 0, 0, MASK_SIZE, MASK_SIZE);
drawLineGC = con.createGC(lineMaskPixmap);
con.setGCExposures(drawLineGC, false);
con.setGCForeground(drawLineGC, 255);
clearLineGC = con.createGC(lineMaskPixmap);
con.setGCExposures(clearLineGC, false);
con.setGCForeground(clearLineGC, 0);
}
/**
* Adds a rectangle to the mask.
*/
public void addRect(int x, int y, int width, int height) {
mainTile.addRect(x, y, width, height);
}
/**
* Adds a line to the mask.
*/
public void addLine(int x1, int y1, int x2, int y2) {
mainTile.addLine(x1, y1, x2, y2);
}
/**
* Transfers the geometry stored (rectangles, lines) to one or more masks,
* and renders the result to the destination surface.
*/
public void fillMask(XRSurfaceData dst) {
boolean maskRequired = xrMgr.maskRequired();
if (maskRequired) {
mainTile.calculateDirtyAreas();
DirtyRegion dirtyArea = mainTile.getDirtyArea().cloneRegion();
mainTile.translate(-dirtyArea.x, -dirtyArea.y);
XRColor maskColor = xrMgr.getMaskColor();
// We don't need tiling if all geometry fits in a single tile
if (dirtyArea.getWidth() <= MASK_SIZE &&
dirtyArea.getHeight() <= MASK_SIZE)
{
compositeSingleTile(dst, mainTile, dirtyArea,
maskRequired, 0, 0, maskColor);
} else {
allocTiles(dirtyArea);
tileRects();
for (int i = 0; i < yTiles; i++) {
for (int m = 0; m < xTiles; m++) {
MaskTile tile = tileList.get(i * xTiles + m);
int tileStartX = m * MASK_SIZE;
int tileStartY = i * MASK_SIZE;
compositeSingleTile(dst, tile, dirtyArea, maskRequired,
tileStartX, tileStartY, maskColor);
}
}
}
} else {
xrMgr.XRRenderRectangles(dst, mainTile.getRects());
}
mainTile.reset();
}
/**
* Uploads aa geometry generated for maskblit/fill into the mask pixmap.
*/
public int uploadMask(int w, int h, int maskscan, int maskoff, byte[] mask) {
int maskPic = XRUtils.None;
if (mask != null) {
float maskAlpha =
xrMgr.isTexturePaintActive() ? xrMgr.getExtraAlpha() : 1.0f;
con.putMaskImage(maskPixmap, maskGC, mask, 0, 0, 0, 0,
w, h, maskoff, maskscan, maskAlpha);
maskPic = maskPicture;
} else if (xrMgr.isTexturePaintActive()) {
maskPic = xrMgr.getExtraAlphaMask();
}
return maskPic;
}
/**
* Clears the area of the mask-pixmap used for uploading aa coverage values.
*/
public void clearUploadMask(int mask, int w, int h) {
if (mask == maskPicture) {
con.renderRectangle(maskPicture, XRUtils.PictOpClear,
XRColor.NO_ALPHA, 0, 0, w, h);
}
}
/**
* Renders the rectangles provided to the mask, and does a composition
* operation with the properties set inXRCompositeManager.
*/
protected void compositeSingleTile(XRSurfaceData dst, MaskTile tile,
DirtyRegion dirtyArea,
boolean maskRequired,
int tileStartX, int tileStartY,
XRColor maskColor) {
if (tile.rects.getSize() > 0) {
DirtyRegion tileDirtyArea = tile.getDirtyArea();
int x = tileDirtyArea.x + tileStartX + dirtyArea.x;
int y = tileDirtyArea.y + tileStartY + dirtyArea.y;
int width = tileDirtyArea.x2 - tileDirtyArea.x;
int height = tileDirtyArea.y2 - tileDirtyArea.y;
width = Math.min(width, MASK_SIZE);
height = Math.min(height, MASK_SIZE);
int rectCnt = tile.rects.getSize();
if (maskRequired) {
int mask = XRUtils.None;
/*
* Optimization: When the tile only contains one rectangle, the
* composite-operation boundaries can be used as geometry
*/
if (rectCnt > 1) {
con.renderRectangles(maskPicture, XRUtils.PictOpSrc,
maskColor, tile.rects);
mask = maskPicture;
} else {
if (xrMgr.isTexturePaintActive()) {
mask = xrMgr.getExtraAlphaMask();
}
}
xrMgr.XRComposite(XRUtils.None, mask, dst.getPicture(),
x, y, tileDirtyArea.x, tileDirtyArea.y,
x, y, width, height);
/* Clear dirty rectangle of the rect-mask */
if (rectCnt > 1) {
con.renderRectangle(maskPicture, XRUtils.PictOpClear,
XRColor.NO_ALPHA,
tileDirtyArea.x, tileDirtyArea.y,
width, height);
}
tile.reset();
} else if (rectCnt > 0) {
tile.rects.translateRects(tileStartX + dirtyArea.x,
tileStartY + dirtyArea.y);
xrMgr.XRRenderRectangles(dst, tile.rects);
}
}
}
/**
* Allocates enough MaskTile instances, to cover the whole
* mask area, or resets existing ones.
*/
protected void allocTiles(DirtyRegion maskArea) {
xTiles = (maskArea.getWidth() / MASK_SIZE) + 1;
yTiles = (maskArea.getHeight() / MASK_SIZE) + 1;
int tileCnt = xTiles * yTiles;
if (tileCnt > allocatedTiles) {
for (int i = 0; i < tileCnt; i++) {
if (i < allocatedTiles) {
tileList.get(i).reset();
} else {
tileList.add(new MaskTile());
}
}
allocatedTiles = tileCnt;
}
}
/**
* Tiles the stored rectangles, if they are larger than the MASK_SIZE
*/
protected void tileRects() {
GrowableRectArray rects = mainTile.rects;
for (int i = 0; i < rects.getSize(); i++) {
int tileXStartIndex = rects.getX(i) / MASK_SIZE;
int tileYStartIndex = rects.getY(i) / MASK_SIZE;
int tileXLength =
((rects.getX(i) + rects.getWidth(i)) / MASK_SIZE + 1) -
tileXStartIndex;
int tileYLength =
((rects.getY(i) + rects.getHeight(i)) / MASK_SIZE + 1) -
tileYStartIndex;
for (int n = 0; n < tileYLength; n++) {
for (int m = 0; m < tileXLength; m++) {
int tileIndex =
xTiles * (tileYStartIndex + n) + tileXStartIndex + m;
MaskTile tile = tileList.get(tileIndex);
GrowableRectArray rectTileList = tile.getRects();
int tileArrayIndex = rectTileList.getNextIndex();
int tileStartPosX = (tileXStartIndex + m) * MASK_SIZE;
int tileStartPosY = (tileYStartIndex + n) * MASK_SIZE;
rectTileList.setX(tileArrayIndex, rects.getX(i) - tileStartPosX);
rectTileList.setY(tileArrayIndex, rects.getY(i) - tileStartPosY);
rectTileList.setWidth(tileArrayIndex, rects.getWidth(i));
rectTileList.setHeight(tileArrayIndex, rects.getHeight(i));
limitRectCoords(rectTileList, tileArrayIndex);
tile.getDirtyArea().growDirtyRegion
(rectTileList.getX(tileArrayIndex),
rectTileList.getY(tileArrayIndex),
rectTileList.getWidth(tileArrayIndex) +
rectTileList.getX(tileArrayIndex),
rectTileList.getHeight(tileArrayIndex) +
rectTileList.getY(tileArrayIndex));
}
}
}
}
/**
* Limits the rect's coordinates to the mask coordinates. The result is used
* by growDirtyRegion.
*/
private void limitRectCoords(GrowableRectArray rects, int index) {
if ((rects.getX(index) + rects.getWidth(index)) > MASK_SIZE) {
rects.setWidth(index, MASK_SIZE - rects.getX(index));
}
if ((rects.getY(index) + rects.getHeight(index)) > MASK_SIZE) {
rects.setHeight(index, MASK_SIZE - rects.getY(index));
}
if (rects.getX(index) < 0) {
rects.setWidth(index, rects.getWidth(index) + rects.getX(index));
rects.setX(index, 0);
}
if (rects.getY(index) < 0) {
rects.setHeight(index, rects.getHeight(index) + rects.getY(index));
rects.setY(index, 0);
}
}
}

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -0,0 +1,117 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.java2d.xr;
/**
* XRender pipeline backend interface.
* Currently there are two different backends implemented:
* - XRBackendJava: And experimental backend, generating protocol directly using java-code and xcb's socket handoff functionality.
* - XRBackendNative: Native 1:1 binding with libX11.
*/
import java.awt.geom.*;
import java.util.*;
import sun.font.*;
import sun.java2d.jules.*;
import sun.java2d.pipe.*;
public interface XRBackend {
public void freePicture(int picture);
public void freePixmap(int pixmap);
public int createPixmap(int drawable, int depth, int width, int height);
public int createPicture(int drawable, int formatID);
public long createGC(int drawable);
public void freeGC(long gc); /* TODO: Use!! */
public void copyArea(int src, int dst, long gc, int srcx, int srcy,
int width, int height, int dstx, int dsty);
public void putMaskImage(int drawable, long gc, byte[] imageData,
int sx, int sy, int dx, int dy,
int width, int height, int maskOff,
int maskScan, float ea);
public void setGCClipRectangles(long gc, Region clip);
public void GCRectangles(int drawable, long gc, GrowableRectArray rects);
public void setClipRectangles(int picture, Region clip);
public void setGCExposures(long gc, boolean exposure);
public void setGCForeground(long gc, int pixel);
public void setPictureTransform(int picture, AffineTransform transform);
public void setPictureRepeat(int picture, int repeat);
public void setFilter(int picture, int filter);
public void renderRectangle(int dst, byte op, XRColor color,
int x, int y, int width, int height);
public void renderRectangles(int dst, byte op, XRColor color,
GrowableRectArray rects);
public void renderComposite(byte op, int src, int mask, int dst,
int srcX, int srcY, int maskX, int maskY,
int dstX, int dstY, int width, int height);
public int XRenderCreateGlyphSet(int formatID);
public void XRenderAddGlyphs(int glyphSet, GlyphList gl,
List<XRGlyphCacheEntry> cacheEntries,
byte[] pixelData);
public void XRenderFreeGlyphs(int glyphSet, int[] gids);
public void XRenderCompositeText(byte op, int src, int dst,
int maskFormatID,
int xSrc, int ySrc, int xDst, int yDst,
int glyphset, GrowableEltArray elts);
public int createRadialGradient(Point2D inner, Point2D outer,
float innerRadius, float outerRadius,
float[] fractions, int[] pixels,
int repeat, AffineTransform transform);
public int createLinearGradient(Point2D p1, Point2D p2, float[] fractions,
int[] pixels, int repeat,
AffineTransform transform);
public void setGCMode(long gc, boolean copy);
public void renderCompositeTrapezoids(byte op, int src, int maskFormat,
int dst, int srcX, int srcY,
TrapezoidList trapList);
}

View file

@ -0,0 +1,343 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.java2d.xr;
import java.awt.geom.*;
import java.util.*;
import sun.font.*;
import sun.java2d.jules.*;
import sun.java2d.pipe.*;
import static sun.java2d.xr.XRUtils.XDoubleToFixed;
/**
* Native implementation of XRBackend.
* Almost direct 1:1 binding to libX11.
*
* @author Clemens Eisserer
*/
public class XRBackendNative implements XRBackend {
static {
initIDs();
}
private static long FMTPTR_A8;
private static long FMTPTR_ARGB32;
private static long MASK_XIMG;
private static native void initIDs();
public native long createGC(int drawable);
public native void freeGC(long gc);
public native int createPixmap(int drawable, int depth,
int width, int height);
private native int createPictureNative(int drawable, long formatID);
public native void freePicture(int picture);
public native void freePixmap(int pixmap);
public native void setGCExposures(long gc, boolean exposure);
public native void setGCForeground(long gc, int pixel);
public native void setPictureRepeat(int picture, int repeat);
public native void copyArea(int src, int dst, long gc,
int srcx, int srcy, int width, int height,
int dstx, int dsty);
public native void setGCMode(long gc, boolean copy);
private static native void GCRectanglesNative(int drawable, long gc,
int[] rectArray, int rectCnt);
public native void renderComposite(byte op, int src, int mask,
int dst, int srcX, int srcY,
int maskX, int maskY, int dstX, int dstY,
int width, int height);
private native void renderRectangle(int dst, byte op,
short red, short green,
short blue, short alpha,
int x, int y, int width, int height);
private static native void
XRenderRectanglesNative(int dst, byte op,
short red, short green,
short blue, short alpha,
int[] rects, int rectCnt);
private native void XRSetTransformNative(int pic,
int m00, int m01, int m02,
int m10, int m11, int m12);
private static native int
XRCreateLinearGradientPaintNative(float[] fractionsArray,
short[] pixelsArray,
int x1, int y1, int x2, int y2,
int numStops, int repeat,
int m00, int m01, int m02,
int m10, int m11, int m12);
private native static int
XRCreateRadialGradientPaintNative(float[] fractionsArray,
short[] pixelsArray, int numStops,
int innerRadius, int outerRadius,
int repeat,
int m00, int m01, int m02,
int m10, int m11, int m12);
public native void setFilter(int picture, int filter);
private static native void XRSetClipNative(long dst,
int x1, int y1, int x2, int y2,
Region clip, boolean isGC);
public void GCRectangles(int drawable, long gc, GrowableRectArray rects) {
GCRectanglesNative(drawable, gc, rects.getArray(), rects.getSize());
}
public int createPicture(int drawable, int formatID) {
return createPictureNative(drawable, getFormatPtr(formatID));
}
public void setPictureTransform(int picture, AffineTransform transform) {
XRSetTransformNative(picture,
XDoubleToFixed(transform.getScaleX()),
XDoubleToFixed(transform.getShearX()),
XDoubleToFixed(transform.getTranslateX()),
XDoubleToFixed(transform.getShearY()),
XDoubleToFixed(transform.getScaleY()),
XDoubleToFixed(transform.getTranslateY()));
}
public void renderRectangle(int dst, byte op, XRColor color,
int x, int y, int width, int height) {
renderRectangle(dst, op, (short)color.red, (short)color.green,
(short)color.blue, (short)color.alpha,
x, y, width, height);
}
private short[] getRenderColors(int[] pixels) {
short[] renderColors = new short[pixels.length * 4];
XRColor c = new XRColor();
for (int i = 0; i < pixels.length; i++) {
c.setColorValues(pixels[i], true);
renderColors[i * 4 + 0] = (short) c.alpha;
renderColors[i * 4 + 1] = (short) c.red;
renderColors[i * 4 + 2] = (short) c.green;
renderColors[i * 4 + 3] = (short) c.blue;
}
return renderColors;
}
private static long getFormatPtr(int formatID) {
switch (formatID) {
case XRUtils.PictStandardA8:
return FMTPTR_A8;
case XRUtils.PictStandardARGB32:
return FMTPTR_ARGB32;
}
return 0L;
}
public int createLinearGradient(Point2D p1, Point2D p2, float[] fractions,
int[] pixels, int repeat, AffineTransform trx) {
short[] colorValues = getRenderColors(pixels);
int gradient =
XRCreateLinearGradientPaintNative(fractions, colorValues,
XDoubleToFixed(p1.getX()), XDoubleToFixed(p1.getY()),
XDoubleToFixed(p2.getX()), XDoubleToFixed(p2.getY()),
fractions.length, repeat,
XDoubleToFixed(trx.getScaleX()),
XDoubleToFixed(trx.getShearX()),
XDoubleToFixed(trx.getTranslateX()),
XDoubleToFixed(trx.getShearY()),
XDoubleToFixed(trx.getScaleY()),
XDoubleToFixed(trx.getTranslateY()));
return gradient;
}
public int createRadialGradient(Point2D inner, Point2D outer,
float innerRadius, float outerRadius,
float[] fractions, int[] pixels, int repeat,
AffineTransform trx) {
short[] colorValues = getRenderColors(pixels);
return XRCreateRadialGradientPaintNative
(fractions, colorValues, fractions.length,
XDoubleToFixed(innerRadius),
XDoubleToFixed(outerRadius),
repeat,
XDoubleToFixed(trx.getScaleX()),
XDoubleToFixed(trx.getShearX()),
XDoubleToFixed(trx.getTranslateX()),
XDoubleToFixed(trx.getShearY()),
XDoubleToFixed(trx.getScaleY()),
XDoubleToFixed(trx.getTranslateY()));
}
public void setGCClipRectangles(long gc, Region clip) {
XRSetClipNative(gc, clip.getLoX(), clip.getLoY(),
clip.getHiX(), clip.getHiY(),
clip.isRectangular() ? null : clip, true);
}
public void setClipRectangles(int picture, Region clip) {
if (clip != null) {
XRSetClipNative(picture, clip.getLoX(), clip.getLoY(),
clip.getHiX(), clip.getHiY(),
clip.isRectangular() ? null : clip, false);
} else {
XRSetClipNative(picture, 0, 0, 32767, 32767, null, false);
}
}
public void renderRectangles(int dst, byte op, XRColor color,
GrowableRectArray rects) {
XRenderRectanglesNative(dst, op,
(short) color.red, (short) color.green,
(short) color.blue, (short) color.alpha,
rects.getArray(), rects
.getSize());
}
private static long[] getGlyphInfoPtrs(List<XRGlyphCacheEntry> cacheEntries) {
long[] glyphInfoPtrs = new long[cacheEntries.size()];
for (int i = 0; i < cacheEntries.size(); i++) {
glyphInfoPtrs[i] = cacheEntries.get(i).getGlyphInfoPtr();
}
return glyphInfoPtrs;
}
public void XRenderAddGlyphs(int glyphSet, GlyphList gl,
List<XRGlyphCacheEntry> cacheEntries,
byte[] pixelData) {
long[] glyphInfoPtrs = getGlyphInfoPtrs(cacheEntries);
XRAddGlyphsNative(glyphSet, glyphInfoPtrs,
glyphInfoPtrs.length, pixelData, pixelData.length);
}
public void XRenderFreeGlyphs(int glyphSet, int[] gids) {
XRFreeGlyphsNative(glyphSet, gids, gids.length);
}
private static native void XRAddGlyphsNative(int glyphSet,
long[] glyphInfoPtrs,
int glyphCnt,
byte[] pixelData,
int pixelDataLength);
private static native void XRFreeGlyphsNative(int glyphSet,
int[] gids, int idCnt);
private static native void
XRenderCompositeTextNative(int op, int src, int dst,
long maskFormat, int[] eltArray,
int[] glyphIDs, int eltCnt, int glyphCnt);
public int XRenderCreateGlyphSet(int formatID) {
return XRenderCreateGlyphSetNative(getFormatPtr(formatID));
}
private static native int XRenderCreateGlyphSetNative(long format);
public void XRenderCompositeText(byte op, int src, int dst,
int maskFormatID,
int src2, int src3, int dst2, int dst3,
int glyphset, GrowableEltArray elts) {
GrowableIntArray glyphs = elts.getGlyphs();
XRenderCompositeTextNative(op, src, dst, 0, elts.getArray(),
glyphs.getArray(), elts.getSize(),
glyphs.getSize());
}
public void putMaskImage(int drawable, long gc, byte[] imageData,
int sx, int sy, int dx, int dy,
int width, int height, int maskOff,
int maskScan, float ea) {
putMaskNative(drawable, gc, imageData, sx, sy, dx, dy,
width, height, maskOff, maskScan, ea, MASK_XIMG);
}
private static native void putMaskNative(int drawable, long gc,
byte[] imageData,
int sx, int sy, int dx, int dy,
int width, int height,
int maskOff, int maskScan,
float ea, long xImg);
public void padBlit(byte op, int srcPict, int maskPict, int dstPict,
AffineTransform maskTrx, int maskWidth, int maskHeight,
int lastMaskWidth, int lastMaskHeight,
int sx, int sy, int dx, int dy, int w, int h) {
padBlitNative(op, srcPict, maskPict, dstPict,
XDoubleToFixed(maskTrx.getScaleX()),
XDoubleToFixed(maskTrx.getShearX()),
XDoubleToFixed(maskTrx.getTranslateX()),
XDoubleToFixed(maskTrx.getShearY()),
XDoubleToFixed(maskTrx.getScaleY()),
XDoubleToFixed(maskTrx.getTranslateY()),
maskWidth, maskHeight, lastMaskWidth, lastMaskHeight,
sx, sy, dx, dy, w, h);
}
private static native void padBlitNative(byte op, int srcPict,
int maskPict, int dstPict,
int m00, int m01, int m02,
int m10, int m11, int m12,
int maskWidth, int maskHeight,
int lastMaskWidth,
int lastMaskHeight,
int sx, int sy, int dx, int dy,
int w, int h);
public void renderCompositeTrapezoids(byte op, int src, int maskFormat,
int dst, int srcX, int srcY,
TrapezoidList trapList) {
renderCompositeTrapezoidsNative(op, src, getFormatPtr(maskFormat),
dst, srcX, srcY,
trapList.getTrapArray());
}
private static native void
renderCompositeTrapezoidsNative(byte op, int src, long maskFormat,
int dst, int srcX, int srcY,
int[] trapezoids);
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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();
}
}
}

View file

@ -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();
}
}
}

View file

@ -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);
}
}
}

View file

@ -0,0 +1,400 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.java2d.xr;
import sun.awt.SunToolkit;
import sun.awt.image.*;
import sun.java2d.loops.*;
import sun.java2d.pipe.*;
import sun.java2d.*;
import java.awt.*;
import java.awt.geom.*;
import java.lang.ref.*;
public class XRPMBlitLoops {
static WeakReference<SunVolatileImage> argbTmpPM = new WeakReference<SunVolatileImage>(null);
static WeakReference<SunVolatileImage> rgbTmpPM = new WeakReference<SunVolatileImage>(null);
public XRPMBlitLoops() {
}
public static void register() {
GraphicsPrimitive[] primitives = { new XRPMBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntRgbX11),
new XRPMBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntArgbPreX11),
new XRPMBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntRgbX11),
new XRPMBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntArgbPreX11),
new XRPMScaledBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntRgbX11),
new XRPMScaledBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntArgbPreX11),
new XRPMScaledBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntRgbX11),
new XRPMScaledBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntArgbPreX11),
new XRPMTransformedBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntRgbX11),
new XRPMTransformedBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntArgbPreX11),
new XRPMTransformedBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntRgbX11),
new XRPMTransformedBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntArgbPreX11),
/* SW -> Surface Blits */
new XrSwToPMBlit(SurfaceType.IntArgb, XRSurfaceData.IntRgbX11),
new XrSwToPMBlit(SurfaceType.IntRgb, XRSurfaceData.IntRgbX11),
new XrSwToPMBlit(SurfaceType.IntBgr, XRSurfaceData.IntRgbX11),
new XrSwToPMBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntRgbX11),
new XrSwToPMBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntRgbX11),
new XrSwToPMBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntRgbX11),
new XrSwToPMBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntRgbX11),
new XrSwToPMBlit(SurfaceType.IntArgb, XRSurfaceData.IntArgbPreX11),
new XrSwToPMBlit(SurfaceType.IntRgb, XRSurfaceData.IntArgbPreX11),
new XrSwToPMBlit(SurfaceType.IntBgr, XRSurfaceData.IntArgbPreX11),
new XrSwToPMBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntArgbPreX11),
new XrSwToPMBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntArgbPreX11),
new XrSwToPMBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntArgbPreX11),
new XrSwToPMBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntArgbPreX11),
/* SW->Surface Scales */
new XrSwToPMScaledBlit(SurfaceType.IntArgb, XRSurfaceData.IntRgbX11),
new XrSwToPMScaledBlit(SurfaceType.IntRgb, XRSurfaceData.IntRgbX11),
new XrSwToPMScaledBlit(SurfaceType.IntBgr, XRSurfaceData.IntRgbX11),
new XrSwToPMScaledBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntRgbX11),
new XrSwToPMScaledBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntRgbX11),
new XrSwToPMScaledBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntRgbX11),
new XrSwToPMScaledBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntRgbX11),
new XrSwToPMScaledBlit(SurfaceType.IntArgb, XRSurfaceData.IntArgbPreX11),
new XrSwToPMScaledBlit(SurfaceType.IntRgb, XRSurfaceData.IntArgbPreX11),
new XrSwToPMScaledBlit(SurfaceType.IntBgr, XRSurfaceData.IntArgbPreX11),
new XrSwToPMScaledBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntArgbPreX11),
new XrSwToPMScaledBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntArgbPreX11),
new XrSwToPMScaledBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntArgbPreX11),
new XrSwToPMScaledBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntArgbPreX11),
/* SW->Surface Transforms */
new XrSwToPMTransformedBlit(SurfaceType.IntArgb, XRSurfaceData.IntRgbX11),
new XrSwToPMTransformedBlit(SurfaceType.IntRgb, XRSurfaceData.IntRgbX11),
new XrSwToPMTransformedBlit(SurfaceType.IntBgr, XRSurfaceData.IntRgbX11),
new XrSwToPMTransformedBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntRgbX11),
new XrSwToPMTransformedBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntRgbX11),
new XrSwToPMTransformedBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntRgbX11),
new XrSwToPMTransformedBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntRgbX11),
new XrSwToPMTransformedBlit(SurfaceType.IntArgb, XRSurfaceData.IntArgbPreX11),
new XrSwToPMTransformedBlit(SurfaceType.IntRgb, XRSurfaceData.IntArgbPreX11),
new XrSwToPMTransformedBlit(SurfaceType.IntBgr, XRSurfaceData.IntArgbPreX11),
new XrSwToPMTransformedBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntArgbPreX11),
new XrSwToPMTransformedBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntArgbPreX11),
new XrSwToPMTransformedBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntArgbPreX11),
new XrSwToPMTransformedBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntArgbPreX11), };
GraphicsPrimitiveMgr.register(primitives);
}
/**
* Caches a SW surface using a temporary pixmap. The pixmap is held by a WeakReference,
* allowing it to shrink again after some time.
*/
protected static XRSurfaceData cacheToTmpSurface(SurfaceData src, XRSurfaceData dst, int w, int h, int sx, int sy) {
SunVolatileImage vImg;
SurfaceType vImgSurfaceType;
if (src.getTransparency() == Transparency.OPAQUE) {
vImg = rgbTmpPM.get();
vImgSurfaceType = SurfaceType.IntRgb;
} else {
vImg = argbTmpPM.get();
vImgSurfaceType = SurfaceType.IntArgbPre;
}
if (vImg == null || vImg.getWidth() < w || vImg.getHeight() < h) {
if (vImg != null) {
vImg.flush();
}
vImg = (SunVolatileImage) dst.getGraphicsConfig().createCompatibleVolatileImage(w, h, src.getTransparency());
vImg.setAccelerationPriority(1.0f);
if (src.getTransparency() == SurfaceData.OPAQUE) {
rgbTmpPM = new WeakReference<SunVolatileImage>(vImg);
} else {
argbTmpPM = new WeakReference<SunVolatileImage>(vImg);
}
}
Blit swToSurfaceBlit = Blit.getFromCache(src.getSurfaceType(), CompositeType.SrcNoEa, vImgSurfaceType);
XRSurfaceData vImgSurface = (XRSurfaceData) vImg.getDestSurface();
swToSurfaceBlit.Blit(src, vImgSurface, null, null, sx, sy, 0, 0, w, h);
return vImgSurface;
}
}
class XRPMBlit extends Blit {
public XRPMBlit(SurfaceType srcType, SurfaceType dstType) {
super(srcType, CompositeType.AnyAlpha, dstType);
}
public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) {
try {
SunToolkit.awtLock();
XRSurfaceData x11sdDst = (XRSurfaceData) dst;
x11sdDst.validateAsDestination(null, clip);
XRSurfaceData x11sdSrc = (XRSurfaceData) src;
x11sdSrc.validateAsSource(null, XRUtils.RepeatNone, XRUtils.FAST);
x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null);
x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, sx, sy, dx, dy, w, h);
} finally {
SunToolkit.awtUnlock();
}
}
}
class XRPMScaledBlit extends ScaledBlit {
public XRPMScaledBlit(SurfaceType srcType, SurfaceType dstType) {
super(srcType, CompositeType.AnyAlpha, dstType);
}
/*
* TODO: This breaks scales with non-integer coordinates!?!?!
*/
public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1,
double dx2, double dy2) {
try {
SunToolkit.awtLock();
XRSurfaceData x11sdDst = (XRSurfaceData) dst;
x11sdDst.validateAsDestination(null, clip);
XRSurfaceData x11sdSrc = (XRSurfaceData) src;
x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null);
double xScale = (dx2 - dx1) / (sx2 - sx1);
double yScale = (dy2 - dy1) / (sy2 - sy1);
sx1 *= xScale;
sx2 *= xScale;
sy1 *= yScale;
sy2 *= yScale;
AffineTransform xForm = AffineTransform.getScaleInstance(1 / xScale, 1 / yScale);
x11sdSrc.validateAsSource(xForm, XRUtils.RepeatNone, XRUtils.FAST); /*
* TODO:
* padded
* blit
* required
* :
* -
* /
* ?
* ?
*/
x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, (int) sx1, (int) sy1, (int) dx1, (int) dy1, (int) (dx2 - dx1), (int) (dy2 - dy1));
} finally {
SunToolkit.awtUnlock();
}
}
}
/**
* Called also if scale+transform is set
*
* @author Clemens Eisserer
*/
class XRPMTransformedBlit extends TransformBlit {
public XRPMTransformedBlit(SurfaceType srcType, SurfaceType dstType) {
super(srcType, CompositeType.AnyAlpha, dstType);
}
/*
* Calculates the composite-rectangle required for transformed blits. This
* method is functionally equal to: Shape shp =
* xform.createTransformedShape(rect); Rectangle bounds = shp.getBounds();
* but performs significantly better.
*/
public Rectangle getCompositeBounds(AffineTransform tr, int dstx, int dsty, int width, int height) {
double[] compBounds = new double[8];
compBounds[0] = dstx;
compBounds[1] = dsty;
compBounds[2] = dstx + width;
compBounds[3] = dsty;
compBounds[4] = dstx + width;
compBounds[5] = dsty + height;
compBounds[6] = dstx;
compBounds[7] = dsty + height;
tr.transform(compBounds, 0, compBounds, 0, 4);
double minX = Math.min(compBounds[0], Math.min(compBounds[2], Math.min(compBounds[4], compBounds[6])));
double minY = Math.min(compBounds[1], Math.min(compBounds[3], Math.min(compBounds[5], compBounds[7])));
double maxX = Math.max(compBounds[0], Math.max(compBounds[2], Math.max(compBounds[4], compBounds[6])));
double maxY = Math.max(compBounds[1], Math.max(compBounds[3], Math.max(compBounds[5], compBounds[7])));
minX = Math.floor(minX);
minY = Math.floor(minY);
maxX = Math.ceil(maxX);
maxY = Math.ceil(maxY);
return new Rectangle((int) minX, (int) minY, (int) (maxX - minX), (int) (maxY - minY));
}
public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform xform, int hint, int srcx, int srcy,
int dstx, int dsty, int width, int height) {
try {
SunToolkit.awtLock();
int filter = XRUtils.ATransOpToXRQuality(hint);
XRSurfaceData x11sdDst = (XRSurfaceData) dst;
x11sdDst.validateAsDestination(null, clip);
XRSurfaceData x11sdSrc = (XRSurfaceData) src;
x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null);
Rectangle bounds = getCompositeBounds(xform, dstx, dsty, width, height);
AffineTransform trx = AffineTransform.getTranslateInstance((-bounds.x), (-bounds.y));
trx.concatenate(xform);
AffineTransform maskTX = (AffineTransform) trx.clone();
trx.translate(-srcx, -srcy);
try {
trx.invert();
} catch (NoninvertibleTransformException ex) {
trx.setToIdentity();
System.err.println("Reseted to identity!");
}
boolean omitMask = isMaskOmittable(trx, comp, filter);
if (!omitMask) {
XRMaskImage mask = x11sdSrc.maskBuffer.getMaskImage();
x11sdSrc.validateAsSource(trx, XRUtils.RepeatPad, filter);
int maskPicture = mask.prepareBlitMask(x11sdDst, maskTX, width, height);
x11sdDst.maskBuffer.con.renderComposite(XRCompositeManager.getInstance(x11sdSrc).getCompRule(), x11sdSrc.picture, maskPicture, x11sdDst.picture,
0, 0, 0, 0, bounds.x, bounds.y, bounds.width, bounds.height);
} else {
int repeat = filter == XRUtils.FAST ? XRUtils.RepeatNone : XRUtils.RepeatPad;
x11sdSrc.validateAsSource(trx, repeat, filter);
x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, 0, 0, bounds.x, bounds.y, bounds.width, bounds.height);
}
} finally {
SunToolkit.awtUnlock();
}
}
/* TODO: Is mask ever omitable??? ... should be for 90 degree rotation and no shear, but we always need to use RepeatPad */
protected static boolean isMaskOmittable(AffineTransform trx, Composite comp, int filter) {
return (filter == XRUtils.FAST || trx.getTranslateX() == (int) trx.getTranslateX() /*
* If
* translate
* is
* integer
* only
*/
&& trx.getTranslateY() == (int) trx.getTranslateY() && (trx.getShearX() == 0 && trx.getShearY() == 0 // Only
// 90 degree
// rotation
|| trx.getShearX() == -trx.getShearY())) && ((AlphaComposite) comp).getAlpha() == 1.0f; // No
// ExtraAlpha!=1
}
}
class XrSwToPMBlit extends Blit {
Blit pmToSurfaceBlit;
XrSwToPMBlit(SurfaceType srcType, SurfaceType dstType) {
super(srcType, CompositeType.AnyAlpha, dstType);
pmToSurfaceBlit = new XRPMBlit(dstType, dstType);
}
public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) {
/*
* If the blit is write-only (putimge), no need for a temporary VI.
*/
if (CompositeType.SrcOverNoEa.equals(comp) && (src.getTransparency() == Transparency.OPAQUE)) {
Blit opaqueSwToSurfaceBlit = Blit.getFromCache(src.getSurfaceType(), CompositeType.SrcNoEa, dst.getSurfaceType());
opaqueSwToSurfaceBlit.Blit(src, dst, comp, clip, sx, sy, dx, dy, w, h);
} else {
try {
SunToolkit.awtLock();
XRSurfaceData vImgSurface = XRPMBlitLoops.cacheToTmpSurface(src, (XRSurfaceData) dst, w, h, sx, sy);
pmToSurfaceBlit.Blit(vImgSurface, dst, comp, clip, 0, 0, dx, dy, w, h);
} finally {
SunToolkit.awtUnlock();
}
}
}
}
class XrSwToPMScaledBlit extends ScaledBlit {
ScaledBlit pmToSurfaceBlit;
XrSwToPMScaledBlit(SurfaceType srcType, SurfaceType dstType) {
super(srcType, CompositeType.AnyAlpha, dstType);
pmToSurfaceBlit = new XRPMScaledBlit(dstType, dstType);
}
public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1,
double dx2, double dy2) {
{
int w = sx2 - sx1;
int h = sy2 - sy1;
try {
SunToolkit.awtLock();
XRSurfaceData vImgSurface = XRPMBlitLoops.cacheToTmpSurface(src, (XRSurfaceData) dst, w, h, sx1, sy1);
pmToSurfaceBlit.Scale(vImgSurface, dst, comp, clip, 0, 0, w, h, dx1, dy1, dx2, dy2);
} finally {
SunToolkit.awtUnlock();
}
}
}
}
class XrSwToPMTransformedBlit extends TransformBlit {
TransformBlit pmToSurfaceBlit;
XrSwToPMTransformedBlit(SurfaceType srcType, SurfaceType dstType) {
super(srcType, CompositeType.AnyAlpha, dstType);
pmToSurfaceBlit = new XRPMTransformedBlit(dstType, dstType);
}
public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform xform, int hint, int sx, int sy, int dstx,
int dsty, int w, int h) {
try {
SunToolkit.awtLock();
XRSurfaceData vImgSurface = XRPMBlitLoops.cacheToTmpSurface(src, (XRSurfaceData) dst, w, h, sx, sy);
pmToSurfaceBlit.Transform(vImgSurface, dst, comp, clip, xform, hint, 0, 0, dstx, dsty, w, h);
} finally {
SunToolkit.awtUnlock();
}
}
}

View file

@ -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));
}
}

View file

@ -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();
}
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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?!?!
}
}
}

View file

@ -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,6 +97,54 @@ static XImage * cachedXImage;
#endif /* !HEADLESS */
jboolean XShared_initIDs(JNIEnv *env, jboolean allowShmPixmaps)
{
#ifndef HEADLESS
union {
char c[4];
int i;
} endian;
endian.i = 0xff000000;
nativeByteOrder = (endian.c[0]) ? MSBFirst : LSBFirst;
dgaAvailable = JNI_FALSE;
cachedXImage = NULL;
if (sizeof(X11RIPrivate) > SD_RASINFO_PRIVATE_SIZE) {
JNU_ThrowInternalError(env, "Private RasInfo structure too large!");
return JNI_FALSE;
}
#ifdef MITSHM
if (getenv("NO_AWT_MITSHM") == NULL &&
getenv("NO_J2D_MITSHM") == NULL) {
char * force;
TryInitMITShm(env, &useMitShmExt, &useMitShmPixmaps);
if(allowShmPixmaps) {
useMitShmPixmaps = (useMitShmPixmaps == CAN_USE_MITSHM);
force = getenv("J2D_PIXMAPS");
if (force != NULL) {
if (useMitShmPixmaps && (strcmp(force, "shared") == 0)) {
forceSharedPixmaps = JNI_TRUE;
} else if (strcmp(force, "server") == 0) {
useMitShmPixmaps = JNI_FALSE;
}
}
}else {
useMitShmPixmaps = JNI_FALSE;
}
}
return JNI_TRUE;
#endif /* MITSHM */
#endif /* !HEADLESS */
}
/*
* Class: sun_java2d_x11_X11SurfaceData
* Method: initIDs
@ -107,30 +155,17 @@ 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;
union {
char c[4];
int i;
} endian;
endian.i = 0xff000000;
nativeByteOrder = (endian.c[0]) ? MSBFirst : LSBFirst;
cachedXImage = NULL;
if (sizeof(X11RIPrivate) > SD_RASINFO_PRIVATE_SIZE) {
JNU_ThrowInternalError(env, "Private RasInfo structure too large!");
return;
}
xorCompClass = (*env)->NewGlobalRef(env, XORComp);
if (tryDGA && (getenv("NO_J2D_DGA") == NULL)) {
/* we use RTLD_NOW because of bug 4032715 */
lib = dlopen("libsunwjdga.so", RTLD_NOW);
}
dgaAvailable = JNI_FALSE;
if (lib != NULL) {
JDgaStatus ret = JDGA_FAILED;
void *sym = dlsym(lib, "JDgaLibInit");
@ -149,24 +184,7 @@ 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;
@ -193,22 +211,6 @@ Java_sun_java2d_x11_X11SurfaceData_isDrawableValid(JNIEnv *env, jobject this)
return ret;
}
/*
* Class: sun_java2d_x11_X11SurfaceData
* Method: isDgaAvailable
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL
Java_sun_java2d_x11_X11SurfaceData_isDgaAvailable(JNIEnv *env, jobject this)
{
#if defined(HEADLESS) || defined(__linux__)
return JNI_FALSE;
#else
return dgaAvailable;
#endif /* HEADLESS */
}
/*
* Class: sun_java2d_x11_X11SurfaceData
* Method: isShmPMAvailable
@ -224,6 +226,20 @@ Java_sun_java2d_x11_X11SurfaceData_isShmPMAvailable(JNIEnv *env, jobject this)
#endif /* HEADLESS, MITSHM */
}
/*
* Class: sun_java2d_x11_X11SurfaceData
* Method: isDgaAvailable
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL
Java_sun_java2d_x11_X11SurfaceData_isDgaAvailable(JNIEnv *env, jobject this)
{
#if defined(HEADLESS) || defined(__linux__)
return JNI_FALSE;
#else
return dgaAvailable;
#endif /* HEADLESS */
}
/*
* Class: sun_java2d_x11_X11SurfaceData
@ -231,7 +247,7 @@ Java_sun_java2d_x11_X11SurfaceData_isShmPMAvailable(JNIEnv *env, jobject this)
* 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

View file

@ -30,6 +30,8 @@
#include <jdga.h>
#include <X11/extensions/Xrender.h>
/**
* This include file contains support declarations for loops using the
* X11 extended SurfaceData interface to talk to an X11 drawable from
@ -110,6 +112,7 @@ struct _X11SDOps {
jboolean isBgInitialized; /* whether the bg pixel is valid */
jint pmWidth; /* width, height of the */
jint pmHeight; /* pixmap */
Picture xrPic;
#ifdef MITSHM
ShmPixmapData shmPMData; /* data for switching between shm/nonshm pixmaps*/
#endif /* MITSHM */
@ -136,6 +139,9 @@ void X11SD_DisposeXImage(XImage * image);
void X11SD_DirectRenderNotify(JNIEnv *env, X11SDOps *xsdo);
#endif /* !HEADLESS */
jboolean XShared_initIDs(JNIEnv *env, jboolean allowShmPixmaps);
jboolean XShared_initSurface(JNIEnv *env, X11SDOps *xsdo, jint depth, jint width, jint height, jlong drawable);
/*
* This function returns a pointer to a native X11SDOps structure
* for accessing the indicated X11 SurfaceData Java object. It

View file

@ -0,0 +1,784 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
#include "X11SurfaceData.h"
#include <jni.h>
#include <math.h>
#include "Region.h"
#include "fontscalerdefs.h"
#include <X11/extensions/Xrender.h>
#ifndef X_RenderCreateLinearGradient
typedef struct _XLinearGradient {
XPointFixed p1;
XPointFixed p2;
} XLinearGradient;
#endif
#ifndef X_RenderCreateRadialGradient
typedef struct _XCircle {
XFixed x;
XFixed y;
XFixed radius;
} XCircle;
typedef struct _XRadialGradient {
XCircle inner;
XCircle outer;
} XRadialGradient;
#endif
#ifdef __solaris__
/* Solaris 10 will not have these symbols at runtime */
#include <dlfcn.h>
#include <link.h>
typedef Picture (*XRenderCreateLinearGradientFuncType)
(Display *dpy,
const XLinearGradient *gradient,
const XFixed *stops,
const XRenderColor *colors,
int nstops);
typedef Picture (*XRenderCreateRadialGradientFuncType)
(Display *dpy,
const XRadialGradient *gradient,
const XFixed *stops,
const XRenderColor *colors,
int nstops);
static
XRenderCreateLinearGradientFuncType XRenderCreateLinearGradientFunc = NULL;
static
XRenderCreateRadialGradientFuncType XRenderCreateRadialGradientFunc = NULL;
#endif
#define BUILD_TRANSFORM_MATRIX(TRANSFORM, M00, M01, M02, M10, M11, M12) \
{ \
TRANSFORM.matrix[0][0] = M00; \
TRANSFORM.matrix[0][1] = M01; \
TRANSFORM.matrix[0][2] = M02; \
TRANSFORM.matrix[1][0] = M10; \
TRANSFORM.matrix[1][1] = M11; \
TRANSFORM.matrix[1][2] = M12; \
TRANSFORM.matrix[2][0] = 0; \
TRANSFORM.matrix[2][1] = 0; \
TRANSFORM.matrix[2][2] = 1<<16; \
}
static jboolean IsXRenderAvailable() {
void *xrenderlib;
int major_opcode, first_event, first_error;
if (!XQueryExtension(awt_display, "RENDER",
&major_opcode, &first_event, &first_error)) {
return JNI_FALSE;
}
#ifdef __solaris__
xrenderlib = dlopen("libXrender.so",RTLD_GLOBAL|RTLD_LAZY);
if (xrenderlib != NULL) {
XRenderCreateLinearGradientFunc =
(XRenderCreateLinearGradientFuncType)
dlsym(xrenderlib, "XRenderCreateLinearGradient");
XRenderCreateRadialGradientFunc =
(XRenderCreateRadialGradientFuncType)
dlsym(xrenderlib, "XRenderCreateRadialGradient");
if (XRenderCreateLinearGradientFunc == NULL ||
XRenderCreateRadialGradientFunc == NULL)
{
dlclose(xrenderlib);
return JNI_FALSE;
}
}
#endif
return JNI_TRUE;
}
/*
* Class: sun_awt_X11GraphicsEnvironment
* Method: initGLX
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL
Java_sun_awt_X11GraphicsEnvironment_initXRender
(JNIEnv *env, jclass x11ge)
{
#ifndef HEADLESS
static jboolean xrenderAvailable = JNI_FALSE;
static jboolean firstTime = JNI_TRUE;
if (firstTime) {
AWT_LOCK();
xrenderAvailable = IsXRenderAvailable();
AWT_UNLOCK();
firstTime = JNI_FALSE;
}
return xrenderAvailable;
#else
return JNI_FALSE;
#endif /* !HEADLESS */
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_initIDs(JNIEnv *env, jclass cls) {
char *maskData;
XImage* defaultImg;
jfieldID maskImgID;
jlong fmt8 =
ptr_to_jlong(XRenderFindStandardFormat(awt_display, PictStandardA8));
jlong fmt32 =
ptr_to_jlong(XRenderFindStandardFormat(awt_display, PictStandardARGB32));
jfieldID a8ID = (*env)->GetStaticFieldID(env, cls, "FMTPTR_A8", "J");
jfieldID argb32ID = (*env)->GetStaticFieldID(env, cls, "FMTPTR_ARGB32", "J");
(*env)->SetStaticLongField(env, cls, a8ID, fmt8);
(*env)->SetStaticLongField(env, cls, argb32ID, fmt32);
maskData = (char *) malloc(32*32);
if (maskData == NULL) {
return;
}
defaultImg = XCreateImage(awt_display, NULL, 8, ZPixmap, 0, maskData, 32, 32, 8, 0);
defaultImg->data = maskData; //required?
maskImgID = (*env)->GetStaticFieldID(env, cls, "MASK_XIMG", "J");
(*env)->SetStaticLongField(env, cls, maskImgID, ptr_to_jlong(defaultImg));
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_freeGC
(JNIEnv *env, jobject this, jlong gc) {
XFreeGC(awt_display, (GC) jlong_to_ptr(gc));
}
JNIEXPORT jlong JNICALL
Java_sun_java2d_xr_XRBackendNative_createGC
(JNIEnv *env, jobject this, jint drawable) {
GC xgc = XCreateGC(awt_display, (Drawable) drawable, 0L, NULL);
return ptr_to_jlong(xgc);
}
JNIEXPORT jint JNICALL
Java_sun_java2d_xr_XRBackendNative_createPixmap(JNIEnv *env, jobject this,
jint drawable, jint depth,
jint width, jint height) {
return (jint) XCreatePixmap(awt_display, (Drawable) drawable,
width, height, depth);
}
JNIEXPORT jint JNICALL
Java_sun_java2d_xr_XRBackendNative_createPictureNative
(JNIEnv *env, jclass cls, jint drawable, jlong formatPtr) {
XRenderPictureAttributes pict_attr;
return XRenderCreatePicture(awt_display, (Drawable) drawable,
(XRenderPictFormat *) jlong_to_ptr(formatPtr),
0, &pict_attr);
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_freePicture
(JNIEnv *env, jobject this, jint picture) {
XRenderFreePicture(awt_display, (Picture) picture);
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_freePixmap
(JNIEnv *env, jobject this, jint pixmap) {
XFreePixmap(awt_display, (Pixmap) pixmap);
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_setPictureRepeat
(JNIEnv *env, jobject this, jint picture, jint repeat) {
XRenderPictureAttributes pict_attr;
pict_attr.repeat = repeat;
XRenderChangePicture (awt_display, (Picture) picture, CPRepeat, &pict_attr);
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_setGCExposures
(JNIEnv *env, jobject this, jlong gc, jboolean exposure) {
XSetGraphicsExposures(awt_display,
(GC) jlong_to_ptr(gc), exposure ? True : False); //TODO: ????
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_setGCForeground
(JNIEnv *env, jobject this, jlong gc, jint pixel) {
XSetForeground(awt_display, (GC) jlong_to_ptr(gc), (unsigned long) pixel);
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_copyArea
(JNIEnv *env, jobject this, jint src, jint dst, jlong gc,
jint srcx, jint srcy, jint width, jint height, jint dstx, jint dsty) {
XCopyArea(awt_display, (Drawable) src, (Drawable) dst,
(GC) jlong_to_ptr(gc), srcx, srcy, width, height, dstx, dsty);
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_renderComposite
(JNIEnv *env, jobject this, jbyte op, jint src, jint mask, jint dst,
jint srcX, jint srcY, jint maskX, jint maskY,
jint dstX, jint dstY, jint width, jint height) {
XRenderComposite (awt_display, op,
(Picture)src, (Picture)mask, (Picture)dst,
srcX, srcY, maskX, maskY, dstX, dstY, width, height);
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_renderRectangle
(JNIEnv *env, jobject this, jint dst, jbyte op,
jshort red, jshort green, jshort blue, jshort alpha,
jint x, jint y, jint width, jint height) {
XRenderColor color;
color.alpha = alpha;
color.red = red;
color.green = green;
color.blue = blue;
XRenderFillRectangle(awt_display, op, (Picture) dst, &color,
x, y, width, height);
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_XRenderRectanglesNative
(JNIEnv *env, jclass xsd, jint dst, jbyte op,
jshort red, jshort green, jshort blue, jshort alpha,
jintArray rectArray, jint rectCnt) {
int i;
jint* rects;
XRectangle *xRects;
XRectangle sRects[256];
XRenderColor color;
color.alpha = alpha;
color.red = red;
color.green = green;
color.blue = blue;
if (rectCnt <= 256) {
xRects = &sRects[0];
} else {
xRects = (XRectangle *) malloc(sizeof(XRectangle) * rectCnt);
if (xRects == NULL) {
return;
}
}
if ((rects = (jint *) (*env)->GetPrimitiveArrayCritical(env, rectArray, NULL)) == NULL) {
return;
}
for (i=0; i < rectCnt; i++) {
xRects[i].x = rects[i*4 + 0];
xRects[i].y = rects[i*4 + 1];
xRects[i].width = rects[i*4 + 2];
xRects[i].height = rects[i*4 + 3];
}
XRenderFillRectangles(awt_display, op,
(Picture) dst, &color, xRects, rectCnt);
(*env)->ReleasePrimitiveArrayCritical(env, rectArray, rects, JNI_ABORT);
if (xRects != &sRects[0]) {
free(xRects);
}
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_XRSetTransformNative
(JNIEnv *env, jclass xsd, jint pic,
jint m00, jint m01, jint m02, jint m10, jint m11, jint m12) {
XTransform tr;
BUILD_TRANSFORM_MATRIX(tr, m00, m01, m02, m10, m11, m12);
XRenderSetPictureTransform (awt_display, (Picture) pic, &tr);
}
JNIEXPORT jint JNICALL
Java_sun_java2d_xr_XRBackendNative_XRCreateLinearGradientPaintNative
(JNIEnv *env, jclass xsd, jfloatArray fractionsArray,
jshortArray pixelsArray, jint x1, jint y1, jint x2, jint y2,
jint numStops, jint repeat,
jint m00, jint m01, jint m02, jint m10, jint m11, jint m12) {
jint i;
jshort* pixels;
jfloat* fractions;
XTransform tr;
XRenderPictureAttributes pict_attr;
Picture gradient = 0;
XRenderColor *colors;
XFixed *stops;
XLinearGradient grad;
if ((pixels = (jshort *)
(*env)->GetPrimitiveArrayCritical(env, pixelsArray, NULL)) == NULL) {
return -1;
}
if ((fractions = (jfloat *)
(*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL)) == NULL) {
(*env)->ReleasePrimitiveArrayCritical(env,
pixelsArray, pixels, JNI_ABORT);
return -1;
}
grad.p1.x = x1;
grad.p1.y = y1;
grad.p2.x = x2;
grad.p2.y = y2;
/*TODO optimized & malloc check*/
colors = (XRenderColor *) malloc(numStops * sizeof(XRenderColor));
stops = (XFixed *) malloc(numStops * sizeof(XFixed));
for (i=0; i < numStops; i++) {
stops[i] = XDoubleToFixed(fractions[i]);
colors[i].alpha = pixels[i*4 + 0];
colors[i].red = pixels[i*4 + 1];
colors[i].green = pixels[i*4 + 2];
colors[i].blue = pixels[i*4 + 3];
}
#ifdef __solaris__
if (XRenderCreateLinearGradientFunc!=NULL) {
gradient = (*XRenderCreateLinearGradientFunc)(awt_display, &grad, stops, colors, numStops);
}
#else
gradient = XRenderCreateLinearGradient(awt_display, &grad, stops, colors, numStops);
#endif
free(colors);
free(stops);
(*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT);
if (gradient != 0) {
BUILD_TRANSFORM_MATRIX(tr, m00, m01, m02, m10, m11, m12);
XRenderSetPictureTransform (awt_display, gradient, &tr);
pict_attr.repeat = repeat;
XRenderChangePicture (awt_display, gradient, CPRepeat, &pict_attr);
}
return (jint) gradient;
}
JNIEXPORT jint JNICALL
Java_sun_java2d_xr_XRBackendNative_XRCreateRadialGradientPaintNative
(JNIEnv *env, jclass xsd, jfloatArray fractionsArray,
jshortArray pixelsArray, jint numStops,
jint innerRadius, jint outerRadius, jint repeat,
jint m00, jint m01, jint m02, jint m10, jint m11, jint m12) {
jint i;
jshort* pixels;
jfloat* fractions;
XTransform tr;
XRenderPictureAttributes pict_attr;
Picture gradient = 0;
XRenderColor *colors;
XFixed *stops;
XRadialGradient grad;
if ((pixels =
(jshort *)(*env)->GetPrimitiveArrayCritical(env, pixelsArray, NULL)) == NULL) {
return -1;
}
if ((fractions = (jfloat *)
(*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL)) == NULL) {
(*env)->ReleasePrimitiveArrayCritical(env,
pixelsArray, pixels, JNI_ABORT);
return -1; //TODO release pixels first
}
grad.inner.x = 0;
grad.inner.y = 0;
grad.inner.radius = innerRadius;
grad.outer.x = 0;
grad.outer.y = 0;
grad.outer.radius = outerRadius;
/*TODO optimized & malloc check*/
colors = (XRenderColor *) malloc(numStops * sizeof(XRenderColor));
stops = (XFixed *) malloc(numStops * sizeof(XFixed));
for (i=0; i < numStops; i++) {
stops[i] = XDoubleToFixed(fractions[i]);
colors[i].alpha = pixels[i*4 + 0];
colors[i].red = pixels[i*4 + 1];
colors[i].green = pixels[i*4 + 2];
colors[i].blue = pixels[i*4 + 3];
}
#ifdef __solaris__
if (XRenderCreateRadialGradientFunc != NULL) {
gradient = (jint) (*XRenderCreateRadialGradientFunc)(awt_display, &grad, stops, colors, numStops);
}
#else
gradient = (jint) XRenderCreateRadialGradient(awt_display, &grad, stops, colors, numStops);
#endif
free(colors);
free(stops);
(*env)->ReleasePrimitiveArrayCritical(env, pixelsArray, pixels, JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, fractions, JNI_ABORT);
if (gradient != 0) {
BUILD_TRANSFORM_MATRIX(tr, m00, m01, m02, m10, m11, m12);
XRenderSetPictureTransform (awt_display, gradient, &tr);
pict_attr.repeat = repeat;
XRenderChangePicture (awt_display, gradient, CPRepeat, &pict_attr);
}
return (jint) gradient;
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_setFilter
(JNIEnv *env, jobject this, jint picture, jint filter) {
char * filterName = "fast";
switch(filter) {
case 0:
filterName = "fast";
break;
case 1:
filterName = "good";
break;
case 2:
filterName = "best";
break;
}
XRenderSetPictureFilter(awt_display, (Picture) picture, filterName, NULL, 0);
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_XRSetClipNative
(JNIEnv *env, jclass xsd, jlong dst,
jint x1, jint y1, jint x2, jint y2,
jobject complexclip, jboolean isGC)
{
int numrects;
XRectangle rects[256];
XRectangle *pRect = rects;
numrects = RegionToYXBandedRectangles(env,
x1, y1, x2, y2, complexclip,
&pRect, 256);
if (isGC == JNI_TRUE) {
if (dst != (jlong) 0) {
XSetClipRectangles(awt_display, (GC) jlong_to_ptr(dst), 0, 0, pRect, numrects, YXBanded);
}
} else {
XRenderSetPictureClipRectangles (awt_display, (Picture) dst, 0, 0, pRect, numrects);
}
if (pRect != rects) {
free(pRect);
}
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_putMaskNative
(JNIEnv *env, jclass cls, jint drawable, jlong gc, jbyteArray imageData,
jint sx, jint sy, jint dx, jint dy, jint width, jint height,
jint maskOff, jint maskScan, jfloat ea, jlong imgPtr) {
int line, pix;
char *mask;
char *defaultData;
XImage *defaultImg, *img;
jboolean imageFits;
if ((mask = (char *)
(*env)->GetPrimitiveArrayCritical(env, imageData, NULL)) == NULL) {
return;
}
defaultImg = (XImage *) jlong_to_ptr(imgPtr);
if (ea != 1.0f) {
for (line=0; line < height; line++) {
for (pix=0; pix < width; pix++) {
int index = maskScan*line + pix + maskOff;
mask[index] = (((unsigned char) mask[index])*ea);
}
}
}
/*
* 1. If existing XImage and supplied buffer match, only adjust the data pointer
* 2. If existing XImage is large enough to hold the data but does not match in
* scan the data is copied to fit the XImage.
* 3. If data is larger than the existing XImage a new temporary XImage is
* allocated.
* The default XImage is optimized for the AA tiles, which are currently 32x32.
*/
defaultData = defaultImg->data;
img = defaultImg;
imageFits = defaultImg->width >= width && defaultImg->height >= height;
if (imageFits &&
maskOff == defaultImg->xoffset && maskScan == defaultImg->bytes_per_line) {
defaultImg->data = mask;
} else {
if (imageFits) {
for (line=0; line < height; line++) {
for (pix=0; pix < width; pix++) {
img->data[line*img->bytes_per_line + pix] =
(unsigned char) (mask[maskScan*line + pix + maskOff]);
}
}
} else {
img = XCreateImage(awt_display, NULL, 8, ZPixmap,
maskOff, mask, maskScan, height, 8, 0);
}
}
XPutImage(awt_display, (Pixmap) drawable, (GC) jlong_to_ptr(gc),
img, 0, 0, 0, 0, width, height);
(*env)->ReleasePrimitiveArrayCritical(env, imageData, mask, JNI_ABORT);
if (img != defaultImg) {
img->data = NULL;
XDestroyImage(img);
}
defaultImg->data = defaultData;
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_XRAddGlyphsNative
(JNIEnv *env, jclass cls, jint glyphSet,
jlongArray glyphInfoPtrsArray, jint glyphCnt,
jbyteArray pixelDataArray, int pixelDataLength) {
jlong *glyphInfoPtrs;
unsigned char *pixelData;
int i;
XGlyphInfo *xginfo = (XGlyphInfo *) malloc(sizeof(XGlyphInfo) * glyphCnt);
Glyph *gid = (Glyph *) malloc(sizeof(Glyph) * glyphCnt);
if (xginfo == NULL || gid == NULL) {
return;
}
if ((glyphInfoPtrs = (jlong *) (*env)->GetPrimitiveArrayCritical(env, glyphInfoPtrsArray, NULL)) == NULL) {
return;
}
if ((pixelData = (unsigned char *)
(*env)->GetPrimitiveArrayCritical(env, pixelDataArray, NULL)) == NULL) {
(*env)->ReleasePrimitiveArrayCritical(env,
glyphInfoPtrsArray, glyphInfoPtrs, JNI_ABORT);
return;
}
for (i=0; i < glyphCnt; i++) {
GlyphInfo *jginfo = (GlyphInfo *) jlong_to_ptr(glyphInfoPtrs[i]);
gid[i] = (Glyph) (0xffffffff & ((unsigned int) jginfo->cellInfo));
xginfo[i].x = (-jginfo->topLeftX);
xginfo[i].y = (-jginfo->topLeftY);
xginfo[i].width = jginfo->width;
xginfo[i].height = jginfo->height;
xginfo[i].xOff = round(jginfo->advanceX);
xginfo[i].yOff = round(jginfo->advanceY);
}
XRenderAddGlyphs(awt_display, glyphSet, &gid[0], &xginfo[0], glyphCnt,
pixelData, pixelDataLength);
(*env)->ReleasePrimitiveArrayCritical(env, glyphInfoPtrsArray, glyphInfoPtrs, JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, pixelDataArray, pixelData, JNI_ABORT);
free(xginfo);
free(gid);
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_XRFreeGlyphsNative
(JNIEnv *env, jclass cls, jint glyphSet, jintArray gidArray, jint glyphCnt) {
jint *gids;
int i;
if ((gids = (jint *) (*env)->GetPrimitiveArrayCritical(env, gidArray, NULL)) == NULL) {
return;
}
XRenderFreeGlyphs (awt_display, (GlyphSet) glyphSet, (Glyph *) gids, glyphCnt);
(*env)->ReleasePrimitiveArrayCritical(env, gidArray, gids, JNI_ABORT);
}
JNIEXPORT jint JNICALL
Java_sun_java2d_xr_XRBackendNative_XRenderCreateGlyphSetNative
(JNIEnv *env, jclass cls, jlong format) {
return XRenderCreateGlyphSet(awt_display, (XRenderPictFormat *) jlong_to_ptr(format));
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_XRenderCompositeTextNative
(JNIEnv *env, jclass cls, jint op, jint src, jint dst, jlong maskFmt,
jintArray eltArray, jintArray glyphIDArray, jint eltCnt, jint glyphCnt) {
jint i;
jint *ids;
jint *elts;
XGlyphElt32 *xelts;
Glyph *xids;
XGlyphElt32 selts[24];
Glyph sids[256];
int charCnt = 0;
if (eltCnt <= 24) {
xelts = &selts[0];
}else {
xelts = (XGlyphElt32 *) malloc(sizeof(XGlyphElt32) * eltCnt);
}
if (glyphCnt <= 256) {
xids = &sids[0];
}else {
xids = (Glyph *) malloc(sizeof(Glyph) * glyphCnt);
}
if ((ids = (jint *) (*env)->GetPrimitiveArrayCritical(env, glyphIDArray, NULL)) == NULL) {
return;
}
if ((elts = (jint *)
(*env)->GetPrimitiveArrayCritical(env, eltArray, NULL)) == NULL) {
(*env)->ReleasePrimitiveArrayCritical(env,
glyphIDArray, ids, JNI_ABORT);
return;
}
for (i=0; i < glyphCnt; i++) {
xids[i] = (Glyph) ids[i];
}
for (i=0; i < eltCnt; i++) {
xelts[i].nchars = elts[i*4 + 0];
xelts[i].xOff = elts[i*4 + 1];
xelts[i].yOff = elts[i*4 + 2];
xelts[i].glyphset = (GlyphSet) elts[i*4 + 3];
xelts[i].chars = (unsigned int *) &xids[charCnt];
charCnt += xelts[i].nchars;
}
XRenderCompositeText32(awt_display, op, (Picture) src, (Picture) dst,
(XRenderPictFormat *) jlong_to_ptr(maskFmt),
0, 0, 0, 0, xelts, eltCnt);
(*env)->ReleasePrimitiveArrayCritical(env, glyphIDArray, ids, JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, eltArray, elts, JNI_ABORT);
if (xelts != &selts[0]) {
free(xelts);
}
if (xids != &sids[0]) {
free(xids);
}
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_setGCMode
(JNIEnv *env, jobject this, jlong gc, jboolean copy) {
GC xgc = (GC) jlong_to_ptr(gc);
if (copy == JNI_TRUE) {
XSetFunction(awt_display, xgc, GXcopy);
} else {
XSetFunction(awt_display, xgc, GXxor);
}
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_GCRectanglesNative
(JNIEnv *env, jclass xsd, jint dst, jlong gc,
jintArray rectArray, jint rectCnt) {
int i;
jint* rects;
XRectangle *xRects;
XRectangle sRects[256];
if (rectCnt <= 256) {
xRects = &sRects[0];
} else {
xRects = (XRectangle *) malloc(sizeof(XRectangle) * rectCnt);
if (xRects == NULL) {
return;
}
}
if ((rects = (jint *) (*env)->GetPrimitiveArrayCritical(env, rectArray, NULL)) == NULL) {
return;
}
for (i=0; i < rectCnt; i++) {
xRects[i].x = rects[i*4 + 0];
xRects[i].y = rects[i*4 + 1];
xRects[i].width = rects[i*4 + 2];
xRects[i].height = rects[i*4 + 3];
}
XFillRectangles(awt_display, (Drawable) dst, (GC) jlong_to_ptr(gc), xRects, rectCnt);
(*env)->ReleasePrimitiveArrayCritical(env, rectArray, rects, JNI_ABORT);
if (xRects != &sRects[0]) {
free(xRects);
}
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRBackendNative_renderCompositeTrapezoidsNative
(JNIEnv *env, jclass cls, jbyte op, jint src, jlong maskFmt,
jint dst, jint srcX, jint srcY, jintArray trapArray) {
jint *traps;
if ((traps = (jint *) (*env)->GetPrimitiveArrayCritical(env, trapArray, NULL)) == NULL) {
return;
}
XRenderCompositeTrapezoids(awt_display, op, (Picture) src, (Picture) dst,
(XRenderPictFormat *) jlong_to_ptr(maskFmt),
srcX, srcY, (XTrapezoid *) (traps+5), traps[0]);
(*env)->ReleasePrimitiveArrayCritical(env, trapArray, traps, JNI_ABORT);
}

View file

@ -0,0 +1,116 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
#include "GraphicsPrimitiveMgr.h"
#include "Region.h"
#include "Trace.h"
#include "X11SurfaceData.h"
/*#include <xcb/xcb.h>*/
#include <Xrender.h>
#ifndef RepeatNone /* added in 0.10 */
#define RepeatNone 0
#define RepeatNormal 1
#define RepeatPad 2
#define RepeatReflect 3
#endif
#include <sys/uio.h>
#include <dlfcn.h>
#include <setjmp.h>
#ifndef HEADLESS
jfieldID pictID;
jfieldID xidID;
jfieldID blitMaskPMID;
jfieldID blitMaskPictID;
#endif /* !HEADLESS */
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRSurfaceData_initXRPicture(JNIEnv *env, jobject xsd,
jlong pXSData,
jint pictFormat)
{
#ifndef HEADLESS
X11SDOps *xsdo;
XRenderPictFormat *fmt;
J2dTraceLn(J2D_TRACE_INFO, "in XRSurfaceData_initXRender");
xsdo = (X11SDOps *) jlong_to_ptr(pXSData);
if (xsdo == NULL) {
return;
}
if (xsdo->xrPic == None) {
XRenderPictureAttributes pict_attr;
pict_attr.repeat = RepeatNone;
fmt = XRenderFindStandardFormat(awt_display, pictFormat);
xsdo->xrPic =
XRenderCreatePicture(awt_display, xsdo->drawable, fmt,
CPRepeat, &pict_attr);
}
(*env)->SetIntField (env, xsd, pictID, xsdo->xrPic);
(*env)->SetIntField (env, xsd, xidID, xsdo->drawable);
#endif /* !HEADLESS */
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRSurfaceData_initIDs(JNIEnv *env, jclass xsd)
{
#ifndef HEADLESS
J2dTraceLn(J2D_TRACE_INFO, "in XRSurfaceData_initIDs");
pictID = (*env)->GetFieldID(env, xsd, "picture", "I");
xidID = (*env)->GetFieldID(env, xsd, "xid", "I");
XShared_initIDs(env, JNI_FALSE);
#endif /* !HEADLESS */
}
JNIEXPORT void JNICALL
Java_sun_java2d_xr_XRSurfaceData_XRInitSurface(JNIEnv *env, jclass xsd,
jint depth,
jint width, jint height,
jlong drawable, jint pictFormat)
{
#ifndef HEADLESS
X11SDOps *xsdo;
J2dTraceLn(J2D_TRACE_INFO, "in XRSurfaceData_initSurface");
xsdo = X11SurfaceData_GetOps(env, xsd);
if (xsdo == NULL) {
return;
}
XShared_initSurface(env, xsdo, depth, width, height, drawable);
#endif /* !HEADLESS */
}