| /* |
| * Copyright 2007-2008 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.d3d; |
| |
| import java.awt.AWTException; |
| import java.awt.BufferCapabilities; |
| import java.awt.BufferCapabilities.FlipContents; |
| import java.awt.Component; |
| import java.awt.Graphics; |
| import java.awt.ImageCapabilities; |
| import java.awt.Transparency; |
| import java.awt.color.ColorSpace; |
| import java.awt.image.ColorModel; |
| import java.awt.image.DataBuffer; |
| import java.awt.image.DirectColorModel; |
| import java.awt.image.VolatileImage; |
| import sun.awt.Win32GraphicsConfig; |
| import sun.awt.image.SunVolatileImage; |
| import sun.awt.image.SurfaceManager; |
| import sun.awt.windows.WComponentPeer; |
| import sun.java2d.Surface; |
| import sun.java2d.SurfaceData; |
| import sun.java2d.pipe.hw.AccelDeviceEventNotifier; |
| import sun.java2d.pipe.hw.AccelTypedVolatileImage; |
| import sun.java2d.pipe.hw.AccelGraphicsConfig; |
| import sun.java2d.pipe.hw.AccelSurface; |
| import sun.java2d.pipe.hw.ContextCapabilities; |
| import static sun.java2d.pipe.hw.AccelSurface.*; |
| import static sun.java2d.d3d.D3DContext.D3DContextCaps.*; |
| import sun.java2d.pipe.hw.AccelDeviceEventListener; |
| |
| public class D3DGraphicsConfig |
| extends Win32GraphicsConfig |
| implements AccelGraphicsConfig |
| { |
| private static ImageCapabilities imageCaps = new D3DImageCaps(); |
| |
| private BufferCapabilities bufferCaps; |
| private D3DGraphicsDevice device; |
| |
| protected D3DGraphicsConfig(D3DGraphicsDevice device) { |
| super(device, 0); |
| this.device = device; |
| } |
| |
| public SurfaceData createManagedSurface(int w, int h, int transparency) { |
| return D3DSurfaceData.createData(this, w, h, |
| getColorModel(transparency), |
| null, |
| D3DSurfaceData.TEXTURE); |
| } |
| |
| @Override |
| public synchronized void displayChanged() { |
| super.displayChanged(); |
| // the context could hold a reference to a D3DSurfaceData, which in |
| // turn has a reference back to this D3DGraphicsConfig, so in order |
| // for this instance to be disposed we need to break the connection |
| D3DRenderQueue rq = D3DRenderQueue.getInstance(); |
| rq.lock(); |
| try { |
| D3DContext.invalidateCurrentContext(); |
| } finally { |
| rq.unlock(); |
| } |
| } |
| |
| @Override |
| public ColorModel getColorModel(int transparency) { |
| switch (transparency) { |
| case Transparency.OPAQUE: |
| // REMIND: once the ColorModel spec is changed, this should be |
| // an opaque premultiplied DCM... |
| return new DirectColorModel(24, 0xff0000, 0xff00, 0xff); |
| case Transparency.BITMASK: |
| return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000); |
| case Transparency.TRANSLUCENT: |
| ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB); |
| return new DirectColorModel(cs, 32, |
| 0xff0000, 0xff00, 0xff, 0xff000000, |
| true, DataBuffer.TYPE_INT); |
| default: |
| return null; |
| } |
| } |
| |
| @Override |
| public String toString() { |
| return ("D3DGraphicsConfig[dev="+screen+",pixfmt="+visual+"]"); |
| } |
| |
| /** |
| * The following methods are invoked from WComponentPeer.java rather |
| * than having the Win32-dependent implementations hardcoded in that |
| * class. This way the appropriate actions are taken based on the peer's |
| * GraphicsConfig, whether it is a Win32GraphicsConfig or a |
| * D3DGraphicsConfig. |
| */ |
| |
| /** |
| * Creates a new SurfaceData that will be associated with the given |
| * WComponentPeer. D3D9 doesn't allow rendering to the screen, |
| * so a GDI surface will be returned. |
| */ |
| @Override |
| public SurfaceData createSurfaceData(WComponentPeer peer, |
| int numBackBuffers) |
| { |
| return super.createSurfaceData(peer, numBackBuffers); |
| } |
| |
| /** |
| * The following methods correspond to the multibuffering methods in |
| * WComponentPeer.java... |
| */ |
| |
| /** |
| * Checks that the requested configuration is natively supported; if not, |
| * an AWTException is thrown. |
| */ |
| @Override |
| public void assertOperationSupported(Component target, |
| int numBuffers, |
| BufferCapabilities caps) |
| throws AWTException |
| { |
| if (numBuffers < 2 || numBuffers > 4) { |
| throw new AWTException("Only 2-4 buffers supported"); |
| } |
| if (caps.getFlipContents() == BufferCapabilities.FlipContents.COPIED && |
| numBuffers != 2) |
| { |
| throw new AWTException("FlipContents.COPIED is only" + |
| "supported for 2 buffers"); |
| } |
| } |
| |
| /** |
| * Creates a D3D-based backbuffer for the given peer and returns the |
| * image wrapper. |
| */ |
| @Override |
| public VolatileImage createBackBuffer(WComponentPeer peer) { |
| Component target = (Component)peer.getTarget(); |
| // it is possible for the component to have size 0x0, adjust it to |
| // be at least 1x1 to avoid IAE |
| int w = Math.max(1, target.getWidth()); |
| int h = Math.max(1, target.getHeight()); |
| return new SunVolatileImage(target, w, h, Boolean.TRUE); |
| } |
| |
| /** |
| * Performs the native D3D flip operation for the given target Component. |
| */ |
| @Override |
| public void flip(WComponentPeer peer, |
| Component target, VolatileImage backBuffer, |
| int x1, int y1, int x2, int y2, |
| BufferCapabilities.FlipContents flipAction) |
| { |
| // REMIND: we should actually get a surface data for the |
| // backBuffer's VI |
| SurfaceManager d3dvsm = |
| SurfaceManager.getManager(backBuffer); |
| SurfaceData sd = d3dvsm.getPrimarySurfaceData(); |
| if (sd instanceof D3DSurfaceData) { |
| D3DSurfaceData d3dsd = (D3DSurfaceData)sd; |
| D3DSurfaceData.swapBuffers(d3dsd, x1, y1, x2, y2); |
| } else { |
| // the surface was likely lost could not have been restored |
| Graphics g = peer.getGraphics(); |
| try { |
| g.drawImage(backBuffer, |
| x1, y1, x2, y2, |
| x1, y1, x2, y2, |
| null); |
| } finally { |
| g.dispose(); |
| } |
| } |
| |
| if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) { |
| Graphics g = backBuffer.getGraphics(); |
| try { |
| g.setColor(target.getBackground()); |
| g.fillRect(0, 0, |
| backBuffer.getWidth(), |
| backBuffer.getHeight()); |
| } finally { |
| g.dispose(); |
| } |
| } |
| } |
| |
| private static class D3DBufferCaps extends BufferCapabilities { |
| public D3DBufferCaps() { |
| // REMIND: should we indicate that the front-buffer |
| // (the on-screen rendering) is not accelerated? |
| super(imageCaps, imageCaps, FlipContents.UNDEFINED); |
| } |
| @Override |
| public boolean isMultiBufferAvailable() { |
| return true; |
| } |
| |
| } |
| |
| @Override |
| public BufferCapabilities getBufferCapabilities() { |
| if (bufferCaps == null) { |
| bufferCaps = new D3DBufferCaps(); |
| } |
| return bufferCaps; |
| } |
| |
| private static class D3DImageCaps extends ImageCapabilities { |
| private D3DImageCaps() { |
| super(true); |
| } |
| @Override |
| public boolean isTrueVolatile() { |
| return true; |
| } |
| } |
| |
| @Override |
| public ImageCapabilities getImageCapabilities() { |
| return imageCaps; |
| } |
| |
| D3DGraphicsDevice getD3DDevice() { |
| return device; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see sun.java2d.pipe.hw.BufferedContextProvider#getContext |
| */ |
| @Override |
| public D3DContext getContext() { |
| return device.getContext(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see sun.java2d.pipe.hw.AccelGraphicsConfig#createCompatibleVolatileImage |
| */ |
| @Override |
| public VolatileImage |
| createCompatibleVolatileImage(int width, int height, |
| int transparency, int type) |
| { |
| if (type == FLIP_BACKBUFFER || type == WINDOW || type == UNDEFINED || |
| transparency == Transparency.BITMASK) |
| { |
| return null; |
| } |
| boolean isOpaque = transparency == Transparency.OPAQUE; |
| if (type == RT_TEXTURE) { |
| int cap = isOpaque ? CAPS_RT_TEXTURE_OPAQUE : CAPS_RT_TEXTURE_ALPHA; |
| if (!device.isCapPresent(cap)) { |
| return null; |
| } |
| } else if (type == RT_PLAIN) { |
| if (!isOpaque && !device.isCapPresent(CAPS_RT_PLAIN_ALPHA)) { |
| return null; |
| } |
| } |
| |
| SunVolatileImage vi = new AccelTypedVolatileImage(this, width, height, |
| transparency, type); |
| Surface sd = vi.getDestSurface(); |
| if (!(sd instanceof AccelSurface) || |
| ((AccelSurface)sd).getType() != type) |
| { |
| vi.flush(); |
| vi = null; |
| } |
| |
| return vi; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see sun.java2d.pipe.hw.AccelGraphicsConfig#getContextCapabilities |
| */ |
| @Override |
| public ContextCapabilities getContextCapabilities() { |
| return device.getContextCapabilities(); |
| } |
| |
| @Override |
| public void addDeviceEventListener(AccelDeviceEventListener l) { |
| AccelDeviceEventNotifier.addListener(l, device.getScreen()); |
| } |
| |
| @Override |
| public void removeDeviceEventListener(AccelDeviceEventListener l) { |
| AccelDeviceEventNotifier.removeListener(l); |
| } |
| } |