1 /*
   2  * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.awt;
  27 
  28 import java.awt.AWTException;
  29 import java.awt.BufferCapabilities;
  30 import java.awt.Component;
  31 import java.awt.Graphics;
  32 import java.awt.GraphicsConfiguration;
  33 import java.awt.GraphicsDevice;
  34 import java.awt.GraphicsEnvironment;
  35 import java.awt.Image;
  36 import java.awt.ImageCapabilities;
  37 import java.awt.Rectangle;
  38 import java.awt.Toolkit;
  39 import java.awt.Transparency;
  40 import java.awt.Window;
  41 import java.awt.geom.AffineTransform;
  42 import java.awt.image.BufferedImage;
  43 import java.awt.image.ColorModel;
  44 import java.awt.image.DirectColorModel;
  45 import java.awt.image.Raster;
  46 import java.awt.image.VolatileImage;
  47 import java.awt.image.WritableRaster;
  48 
  49 import sun.awt.windows.WComponentPeer;
  50 import sun.awt.image.OffScreenImage;
  51 import sun.awt.image.SunVolatileImage;
  52 import sun.awt.image.SurfaceManager;
  53 import sun.java2d.SurfaceData;
  54 import sun.java2d.InvalidPipeException;
  55 import sun.java2d.loops.RenderLoops;
  56 import sun.java2d.loops.SurfaceType;
  57 import sun.java2d.loops.CompositeType;
  58 import sun.java2d.windows.GDIWindowSurfaceData;
  59 
  60 /**
  61  * This is an implementation of a GraphicsConfiguration object for a
  62  * single Win32 visual.
  63  *
  64  * @see GraphicsEnvironment
  65  * @see GraphicsDevice
  66  */
  67 public class Win32GraphicsConfig extends GraphicsConfiguration
  68     implements DisplayChangedListener, SurfaceManager.ProxiedGraphicsConfig
  69 {
  70     protected Win32GraphicsDevice screen;
  71     protected int visual;  //PixelFormatID
  72     protected RenderLoops solidloops;
  73 
  74     private static native void initIDs();
  75 
  76     static {
  77         initIDs();
  78     }
  79 
  80     /**
  81      * Returns a Win32GraphicsConfiguration object with the given device
  82      * and PixelFormat.  Note that this method does NOT check to ensure that
  83      * the returned Win32GraphicsConfig will correctly support rendering into a
  84      * Java window.  This method is provided so that client code can do its
  85      * own checking as to the appropriateness of a particular PixelFormat.
  86      * Safer access to Win32GraphicsConfigurations is provided by
  87      * Win32GraphicsDevice.getConfigurations().
  88      */
  89     public static Win32GraphicsConfig getConfig(Win32GraphicsDevice device,
  90                                                 int pixFormatID)
  91     {
  92         return new Win32GraphicsConfig(device, pixFormatID);
  93     }
  94 
  95     /**
  96      * @deprecated as of JDK version 1.3
  97      * replaced by <code>getConfig()</code>
  98      */
  99     @Deprecated
 100     public Win32GraphicsConfig(GraphicsDevice device, int visualnum) {
 101         this.screen = (Win32GraphicsDevice)device;
 102         this.visual = visualnum;
 103         ((Win32GraphicsDevice)device).addDisplayChangedListener(this);
 104     }
 105 
 106     /**
 107      * Return the graphics device associated with this configuration.
 108      */
 109     public Win32GraphicsDevice getDevice() {
 110         return screen;
 111     }
 112 
 113     /**
 114      * Return the PixelFormatIndex this GraphicsConfig uses
 115      */
 116     public int getVisual() {
 117         return visual;
 118     }
 119 
 120     public Object getProxyKey() {
 121         return screen;
 122     }
 123 
 124     /**
 125      * Return the RenderLoops this type of destination uses for
 126      * solid fills and strokes.
 127      */
 128     private SurfaceType sTypeOrig = null;
 129     public synchronized RenderLoops getSolidLoops(SurfaceType stype) {
 130         if (solidloops == null || sTypeOrig != stype) {
 131             solidloops = SurfaceData.makeRenderLoops(SurfaceType.OpaqueColor,
 132                                                      CompositeType.SrcNoEa,
 133                                                      stype);
 134             sTypeOrig = stype;
 135         }
 136         return solidloops;
 137     }
 138 
 139     /**
 140      * Returns the color model associated with this configuration.
 141      */
 142     public synchronized ColorModel getColorModel() {
 143         return screen.getColorModel();
 144     }
 145 
 146     /**
 147      * Returns a new color model for this configuration.  This call
 148      * is only used internally, by images and components that are
 149      * associated with the graphics device.  When attributes of that
 150      * device change (for example, when the device palette is updated),
 151      * then this device-based color model will be updated internally
 152      * to reflect the new situation.
 153      */
 154     public ColorModel getDeviceColorModel() {
 155         return screen.getDynamicColorModel();
 156     }
 157 
 158     /**
 159      * Returns the color model associated with this configuration that
 160      * supports the specified transparency.
 161      */
 162     public ColorModel getColorModel(int transparency) {
 163         switch (transparency) {
 164         case Transparency.OPAQUE:
 165             return getColorModel();
 166         case Transparency.BITMASK:
 167             return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000);
 168         case Transparency.TRANSLUCENT:
 169             return ColorModel.getRGBdefault();
 170         default:
 171             return null;
 172         }
 173     }
 174 
 175     /**
 176      * Returns the default Transform for this configuration.  This
 177      * Transform is typically the Identity transform for most normal
 178      * screens.  Device coordinates for screen and printer devices will
 179      * have the origin in the upper left-hand corner of the target region of
 180      * the device, with X coordinates
 181      * increasing to the right and Y coordinates increasing downwards.
 182      * For image buffers, this Transform will be the Identity transform.
 183      */
 184     public AffineTransform getDefaultTransform() {
 185         double scaleX = screen.getDefaultScaleX();
 186         double scaleY = screen.getDefaultScaleY();
 187         return AffineTransform.getScaleInstance(scaleX, scaleY);
 188     }
 189 
 190     /**
 191      *
 192      * Returns a Transform that can be composed with the default Transform
 193      * of a Graphics2D so that 72 units in user space will equal 1 inch
 194      * in device space.
 195      * Given a Graphics2D, g, one can reset the transformation to create
 196      * such a mapping by using the following pseudocode:
 197      * <pre>
 198      *      GraphicsConfiguration gc = g.getGraphicsConfiguration();
 199      *
 200      *      g.setTransform(gc.getDefaultTransform());
 201      *      g.transform(gc.getNormalizingTransform());
 202      * </pre>
 203      * Note that sometimes this Transform will be identity (e.g. for
 204      * printers or metafile output) and that this Transform is only
 205      * as accurate as the information supplied by the underlying system.
 206      * For image buffers, this Transform will be the Identity transform,
 207      * since there is no valid distance measurement.
 208      */
 209     public AffineTransform getNormalizingTransform() {
 210         Win32GraphicsEnvironment ge = (Win32GraphicsEnvironment)
 211             GraphicsEnvironment.getLocalGraphicsEnvironment();
 212         double xscale = ge.getXResolution() / 72.0;
 213         double yscale = ge.getYResolution() / 72.0;
 214         return new AffineTransform(xscale, 0.0, 0.0, yscale, 0.0, 0.0);
 215     }
 216 
 217     public String toString() {
 218         return (super.toString()+"[dev="+screen+",pixfmt="+visual+"]");
 219     }
 220 
 221     private native Rectangle getBounds(int screen);
 222 
 223     public Rectangle getBounds() {
 224         return getBounds(screen.getScreen());
 225     }
 226 
 227     public synchronized void displayChanged() {
 228         solidloops = null;
 229     }
 230 
 231     public void paletteChanged() {}
 232 
 233     /**
 234      * The following methods are invoked from WComponentPeer.java rather
 235      * than having the Win32-dependent implementations hardcoded in that
 236      * class.  This way the appropriate actions are taken based on the peer's
 237      * GraphicsConfig, whether it is a Win32GraphicsConfig or a
 238      * WGLGraphicsConfig.
 239      */
 240 
 241     /**
 242      * Creates a new SurfaceData that will be associated with the given
 243      * WComponentPeer.
 244      */
 245     public SurfaceData createSurfaceData(WComponentPeer peer,
 246                                          int numBackBuffers)
 247     {
 248         return GDIWindowSurfaceData.createData(peer);
 249     }
 250 
 251     /**
 252      * Creates a new managed image of the given width and height
 253      * that is associated with the target Component.
 254      */
 255     public Image createAcceleratedImage(Component target,
 256                                         int width, int height)
 257     {
 258         ColorModel model = getColorModel(Transparency.OPAQUE);
 259         WritableRaster wr =
 260             model.createCompatibleWritableRaster(width, height);
 261         return new OffScreenImage(target, model, wr,
 262                                   model.isAlphaPremultiplied());
 263     }
 264 
 265     /**
 266      * The following methods correspond to the multibuffering methods in
 267      * WComponentPeer.java...
 268      */
 269 
 270     /**
 271      * Checks that the requested configuration is natively supported; if not,
 272      * an AWTException is thrown.
 273      */
 274     public void assertOperationSupported(Component target,
 275                                          int numBuffers,
 276                                          BufferCapabilities caps)
 277         throws AWTException
 278     {
 279         // the default pipeline doesn't support flip buffer strategy
 280         throw new AWTException(
 281             "The operation requested is not supported");
 282     }
 283 
 284     /**
 285      * This method is called from WComponentPeer when a surface data is replaced
 286      * REMIND: while the default pipeline doesn't support flipping, it may
 287      * happen that the accelerated device may have this graphics config
 288      * (like if the device restoration failed when one device exits fs mode
 289      * while others remain).
 290      */
 291     public VolatileImage createBackBuffer(WComponentPeer peer) {
 292         Component target = (Component)peer.getTarget();
 293         return new SunVolatileImage(target,
 294                                     target.getWidth(), target.getHeight(),
 295                                     Boolean.TRUE);
 296     }
 297 
 298     /**
 299      * Performs the native flip operation for the given target Component.
 300      *
 301      * REMIND: we should really not get here because that would mean that
 302      * a FLIP BufferStrategy has been created, and one could only be created
 303      * if accelerated pipeline is present but in some rare (and transitional)
 304      * cases it may happen that the accelerated graphics device may have a
 305      * default graphics configuraiton, so this is just a precaution.
 306      */
 307     public void flip(WComponentPeer peer,
 308                      Component target, VolatileImage backBuffer,
 309                      int x1, int y1, int x2, int y2,
 310                      BufferCapabilities.FlipContents flipAction)
 311     {
 312         if (flipAction == BufferCapabilities.FlipContents.COPIED ||
 313             flipAction == BufferCapabilities.FlipContents.UNDEFINED) {
 314             Graphics g = peer.getGraphics();
 315             try {
 316                 g.drawImage(backBuffer,
 317                             x1, y1, x2, y2,
 318                             x1, y1, x2, y2,
 319                             null);
 320             } finally {
 321                 g.dispose();
 322             }
 323         } else if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) {
 324             Graphics g = backBuffer.getGraphics();
 325             try {
 326                 g.setColor(target.getBackground());
 327                 g.fillRect(0, 0,
 328                            backBuffer.getWidth(),
 329                            backBuffer.getHeight());
 330             } finally {
 331                 g.dispose();
 332             }
 333         }
 334         // the rest of the flip actions are not supported
 335     }
 336 
 337     @Override
 338     public boolean isTranslucencyCapable() {
 339         //XXX: worth checking if 8-bit? Anyway, it doesn't hurt.
 340         return true;
 341     }
 342 }