/* * This file is modified by Ivan Maidanski <ivmai@ivmaisoft.com> * Project name: JCGO-SUNAWT (http://www.ivmaisoft.com/jcgo/) */ /* * @(#)X11RemoteOffScreenImage.java 1.15 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package sun.awt.motif; import java.awt.Component; import java.awt.Color; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.DirectColorModel; import java.awt.image.PixelInterleavedSampleModel; import java.awt.image.SampleModel; import java.awt.image.SinglePixelPackedSampleModel; import java.awt.image.WritableRaster; import sun.awt.X11SurfaceData; import sun.awt.X11SurfaceData.X11PixmapSurfaceData; import sun.awt.image.AcceleratedOffScreenImage; import sun.awt.image.BufImgSurfaceData; import sun.awt.image.DataBufferNative; import sun.awt.image.WritableRasterNative; import sun.java2d.SunGraphics2D; import sun.java2d.SurfaceData; import sun.java2d.loops.CompositeType; import sun.java2d.pipe.DrawImage; /** * This class extends the functionality of X11OffScreenImage by * forcing the use of a pixmap-based surfaceData object. In * X11OffScreenImage, the default surfaceData object is the default * one used by BufferedImage, setup by a call to the superclass * constructor. Acceleration is achieved by caching a version of * the data in a pixmap and copying from that pixmap when appropriate. * <P> * This is sufficient for accelerating sprite-type images, which are * rendered to infrequently but copied from often. Back buffers * do not benefit from this acceleration since the cached copy * would never be used. This is deemed sufficient for local X * usage; users performing complex Java2D operations (e.g., * anti-aliasing, compositing, text, or anything that requires * read-modify-write operations) would see a degradation in performance * were we to force all operations to go through the pixmap-based * image. * <P> * In the RemoteX case, however, performance is so abysmal in the * case of double-buffering (with the back buffer living in the * Java heap), that the advantage of speeding up the basic * applications (i.e., those using 1.1 API or simple Swing operations, * and thus avoiding complex Java2D read-modify-write operations) * is judged to outweigh the possible performance loss in some * applications from having the back buffer located in a pixmap. * <P> * The decision to instantiate this class (versus X11OffScreenImage) * is based on whether we are running remotely and whether the * user has enabled/disabled a property related to this issue: * -Dsun.java2d.remote */ public class X11RemoteOffScreenImage extends X11OffScreenImage { int bufImageTypeSw; // Cache for later BI creation // in getSnapshot() SurfaceData bisd; // intermediate BufImgSD for use in // copyBackupToAccelerated private static native void initIDs(); static { initIDs(); } public X11RemoteOffScreenImage(Component c, ColorModel cm, WritableRaster raster, boolean isRasterPremultiplied) { super(c, cm, raster, isRasterPremultiplied, false); bufImageTypeSw = getType(); if (!accelerationEnabled) { return; } GraphicsConfiguration gc = X11SurfaceData.getGC(c == null ? null : (MComponentPeer)c.getPeer()); initAcceleratedBackground(gc, getWidth(), getHeight()); if (surfaceDataHw != null) { setCurrentSurfaceData(surfaceDataHw); // this is the trick: we treat surfaceDataHw as the default // software sd in X11OffScreenImage, this way we can use // all of the functionality of X11OSI. // REMIND: rename surfaceDataHw and surfaceDataSw to // something more appropriate, i.e. sdDefault and sdCached surfaceDataSw = surfaceDataHw; initContents(); createNativeRaster(); } } private native void setSurfaceDataNative(SurfaceData sData); private native void setRasterNative(WritableRaster raster); private void setCurrentSurfaceData(SurfaceData sd) { if (sd != surfaceData) { surfaceData = sd; // OffScreenImage copy setSurfaceDataNative(sd); // BufferedImage copy } } public void initContents() { Graphics2D g2 = createGraphics(); g2.clearRect(0, 0, getWidth(), getHeight()); g2.dispose(); } /** * Need to override this method as we don't need to check for * the number of copies done from this image */ public SurfaceData getSourceSurfaceData(SurfaceData destSD, CompositeType comp, Color bgColor) { if (accelerationEnabled && (destSD != surfaceDataHw) && destSurfaceAccelerated(destSD)) { // First, we validate the pixmap sd if necessary and then return // the appropriate surfaceData object. validate(destSD.getDeviceConfiguration()); if (surfaceDataHw != null) { return surfaceDataHw; } } return surfaceDataSw; } private void createNativeRaster() { ColorModel cm = getColorModel(); SampleModel smHw = null; int dataType = 0; int scanStride = getWidth(); switch (cm.getPixelSize()) { case 8: case 12: // 8-bits uses PixelInterleavedSampleModel if (cm.getPixelSize() == 8) { dataType = DataBuffer.TYPE_BYTE; } else { dataType = DataBuffer.TYPE_USHORT; } int[] bandOffsets = new int[1]; bandOffsets[0] = 0; smHw = new PixelInterleavedSampleModel(dataType, getWidth(), getHeight(), 1, scanStride, bandOffsets); break; // all others use SinglePixelPackedSampleModel case 15: case 16: dataType = DataBuffer.TYPE_USHORT; int[] bitMasks = new int[3]; DirectColorModel dcm = (DirectColorModel)cm; bitMasks[0] = dcm.getRedMask(); bitMasks[1] = dcm.getGreenMask(); bitMasks[2] = dcm.getBlueMask(); smHw = new SinglePixelPackedSampleModel(dataType, getWidth(), getHeight(), scanStride, bitMasks); break; case 24: case 32: dataType = DataBuffer.TYPE_INT; bitMasks = new int[3]; dcm = (DirectColorModel)cm; bitMasks[0] = dcm.getRedMask(); bitMasks[1] = dcm.getGreenMask(); bitMasks[2] = dcm.getBlueMask(); smHw = new SinglePixelPackedSampleModel(dataType, getWidth(), getHeight(), scanStride, bitMasks); break; default: throw new InternalError("Unsupported depth " + cm.getPixelSize()); } DataBuffer dbn = new DataBufferNative(surfaceDataHw, dataType, getWidth(), getHeight()); // set the native raster as a default raster of BI setRasterNative(WritableRasterNative.createNativeRaster(smHw, dbn)); } /** * Returns a BufferedImage representation of this image. * In this default method, it just returns this object. * Platform-dependent implementations may choose to return * something different. For example, X11RemoteOffScreenImage * might want to return a BufferedImage that points to data current * with its pixmap version of the image. */ public BufferedImage getSnapshot() { BufferedImage bImg; if (bufImageTypeSw > 0) { bImg = new BufferedImage(getWidth(), getHeight(), bufImageTypeSw); } else { ColorModel colormodel = getColorModel(); WritableRaster writableraster = colormodel.createCompatibleWritableRaster(getWidth(), getHeight()); bImg = new BufferedImage(colormodel, writableraster, colormodel.isAlphaPremultiplied(), null); } Graphics2D g = bImg.createGraphics(); g.drawImage(this, 0, 0, null); g.dispose(); return bImg; } protected void copyBackupToAccelerated() { if (surfaceDataSw != null && surfaceDataHw != null && surfaceDataSw != surfaceDataHw) { java.awt.Font defaultFont = new java.awt.Font("Dialog", java.awt.Font.PLAIN, 12); // we can't render directly from hw sd to hw sd // as we might end up in XCopyArea with pixmaps from different // screens. So we use a temp BI SD as a bypass: // OSI.surfaceDataSw -> bisd -> AccOSI.surfaceDataHw if (bisd == null) { BufferedImage bi; if (bufImageTypeSw > 0) { bi = new BufferedImage(getWidth(), getHeight(), bufImageTypeSw); } else { ColorModel colormodel = getColorModel(); WritableRaster writableraster = colormodel.createCompatibleWritableRaster(getWidth(), getHeight()); bi = new BufferedImage(colormodel, writableraster, colormodel.isAlphaPremultiplied(), null); } bisd = BufImgSurfaceData.createData(bi); } SunGraphics2D swG2d = new SunGraphics2D(bisd, java.awt.Color.black, java.awt.Color.white, defaultFont); DrawImage.renderSurfaceData(swG2d, surfaceDataSw, (java.awt.Color)null, 0, 0, 0, 0, getWidth(), getHeight()); swG2d.dispose(); SunGraphics2D hwG2D = new SunGraphics2D(surfaceDataHw, java.awt.Color.black, java.awt.Color.white, defaultFont); DrawImage.renderSurfaceData(hwG2D, bisd, (java.awt.Color)null, 0, 0, 0, 0, getWidth(), getHeight()); hwG2D.dispose(); } } }