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 GraphicsDevice 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         return new AffineTransform();
 186     }
 187 
 188     /**
 189      *
 190      * Returns a Transform that can be composed with the default Transform
 191      * of a Graphics2D so that 72 units in user space will equal 1 inch
 192      * in device space.
 193      * Given a Graphics2D, g, one can reset the transformation to create
 194      * such a mapping by using the following pseudocode:
 195      * <pre>
 196      *      GraphicsConfiguration gc = g.getGraphicsConfiguration();
 197      *
 198      *      g.setTransform(gc.getDefaultTransform());
 199      *      g.transform(gc.getNormalizingTransform());
 200      * </pre>
 201      * Note that sometimes this Transform will be identity (e.g. for
 202      * printers or metafile output) and that this Transform is only
 203      * as accurate as the information supplied by the underlying system.
 204      * For image buffers, this Transform will be the Identity transform,
 205      * since there is no valid distance measurement.
 206      */
 207     public AffineTransform getNormalizingTransform() {
 208         Win32GraphicsEnvironment ge = (Win32GraphicsEnvironment)
 209             GraphicsEnvironment.getLocalGraphicsEnvironment();
 210         double xscale = ge.getXResolution() / 72.0;
 211         double yscale = ge.getYResolution() / 72.0;
 212         return new AffineTransform(xscale, 0.0, 0.0, yscale, 0.0, 0.0);
 213     }
 214 
 215     public String toString() {
 216         return (super.toString()+"[dev="+screen+",pixfmt="+visual+"]");
 217     }
 218 
 219     private native Rectangle getBounds(int screen);
 220 
 221     public Rectangle getBounds() {
 222         return getBounds(screen.getScreen());
 223     }
 224 
 225     public synchronized void displayChanged() {
 226         solidloops = null;
 227     }
 228 
 229     public void paletteChanged() {}
 230 
 231     /**
 232      * The following methods are invoked from WComponentPeer.java rather
 233      * than having the Win32-dependent implementations hardcoded in that
 234      * class.  This way the appropriate actions are taken based on the peer's
 235      * GraphicsConfig, whether it is a Win32GraphicsConfig or a
 236      * WGLGraphicsConfig.
 237      */
 238 
 239     /**
 240      * Creates a new SurfaceData that will be associated with the given
 241      * WComponentPeer.
 242      */
 243     public SurfaceData createSurfaceData(WComponentPeer peer,
 244                                          int numBackBuffers)
 245     {
 246         return GDIWindowSurfaceData.createData(peer);
 247     }
 248 
 249     /**
 250      * Creates a new managed image of the given width and height
 251      * that is associated with the target Component.
 252      */
 253     public Image createAcceleratedImage(Component target,
 254                                         int width, int height)
 255     {
 256         ColorModel model = getColorModel(Transparency.OPAQUE);
 257         WritableRaster wr =
 258             model.createCompatibleWritableRaster(width, height);
 259         return new OffScreenImage(target, model, wr,
 260                                   model.isAlphaPremultiplied());
 261     }
 262 
 263     /**
 264      * The following methods correspond to the multibuffering methods in
 265      * WComponentPeer.java...
 266      */
 267 
 268     /**
 269      * Checks that the requested configuration is natively supported; if not,
 270      * an AWTException is thrown.
 271      */
 272     public void assertOperationSupported(Component target,
 273                                          int numBuffers,
 274                                          BufferCapabilities caps)
 275         throws AWTException
 276     {
 277         // the default pipeline doesn't support flip buffer strategy
 278         throw new AWTException(
 279             "The operation requested is not supported");
 280     }
 281 
 282     /**
 283      * This method is called from WComponentPeer when a surface data is replaced
 284      * REMIND: while the default pipeline doesn't support flipping, it may
 285      * happen that the accelerated device may have this graphics config
 286      * (like if the device restoration failed when one device exits fs mode
 287      * while others remain).
 288      */
 289     public VolatileImage createBackBuffer(WComponentPeer peer) {
 290         Component target = (Component)peer.getTarget();
 291         return new SunVolatileImage(target,
 292                                     target.getWidth(), target.getHeight(),
 293                                     Boolean.TRUE);
 294     }
 295 
 296     /**
 297      * Performs the native flip operation for the given target Component.
 298      *
 299      * REMIND: we should really not get here because that would mean that
 300      * a FLIP BufferStrategy has been created, and one could only be created
 301      * if accelerated pipeline is present but in some rare (and transitional)
 302      * cases it may happen that the accelerated graphics device may have a
 303      * default graphics configuraiton, so this is just a precaution.
 304      */
 305     public void flip(WComponentPeer peer,
 306                      Component target, VolatileImage backBuffer,
 307                      int x1, int y1, int x2, int y2,
 308                      BufferCapabilities.FlipContents flipAction)
 309     {
 310         if (flipAction == BufferCapabilities.FlipContents.COPIED ||
 311             flipAction == BufferCapabilities.FlipContents.UNDEFINED) {
 312             Graphics g = peer.getGraphics();
 313             try {
 314                 g.drawImage(backBuffer,
 315                             x1, y1, x2, y2,
 316                             x1, y1, x2, y2,
 317                             null);
 318             } finally {
 319                 g.dispose();
 320             }
 321         } else if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) {
 322             Graphics g = backBuffer.getGraphics();
 323             try {
 324                 g.setColor(target.getBackground());
 325                 g.fillRect(0, 0,
 326                            backBuffer.getWidth(),
 327                            backBuffer.getHeight());
 328             } finally {
 329                 g.dispose();
 330             }
 331         }
 332         // the rest of the flip actions are not supported
 333     }
 334 
 335     @Override
 336     public boolean isTranslucencyCapable() {
 337         //XXX: worth checking if 8-bit? Anyway, it doesn't hurt.
 338         return true;
 339     }
 340 }