src/macosx/classes/sun/java2d/opengl/CGLGraphicsConfig.java

Print this page




  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.java2d.opengl;
  27 
  28 import java.awt.AWTException;
  29 import java.awt.BufferCapabilities;
  30 import java.awt.Color;
  31 import java.awt.Component;
  32 import java.awt.Graphics;
  33 import java.awt.Graphics2D;
  34 import java.awt.GraphicsConfiguration;
  35 import java.awt.GraphicsDevice;
  36 import java.awt.GraphicsEnvironment;
  37 import java.awt.Image;
  38 import java.awt.ImageCapabilities;
  39 import java.awt.Rectangle;
  40 import java.awt.Transparency;
  41 import java.awt.color.ColorSpace;
  42 import java.awt.image.BufferedImage;
  43 import java.awt.image.ColorModel;
  44 import java.awt.image.DataBuffer;
  45 import java.awt.image.DirectColorModel;
  46 import java.awt.image.VolatileImage;
  47 import java.awt.image.WritableRaster;
  48 
  49 import sun.awt.CGraphicsConfig;
  50 import sun.awt.CGraphicsDevice;
  51 import sun.awt.TextureSizeConstraining;
  52 import sun.awt.image.OffScreenImage;
  53 import sun.awt.image.SunVolatileImage;
  54 import sun.awt.image.SurfaceManager;
  55 import sun.java2d.Disposer;
  56 import sun.java2d.DisposerRecord;
  57 import sun.java2d.SunGraphics2D;
  58 import sun.java2d.Surface;
  59 import sun.java2d.SurfaceData;
  60 import sun.java2d.opengl.OGLContext.OGLContextCaps;
  61 import sun.java2d.pipe.hw.AccelSurface;
  62 import sun.java2d.pipe.hw.AccelTypedVolatileImage;
  63 import sun.java2d.pipe.hw.ContextCapabilities;
  64 import static sun.java2d.opengl.OGLSurfaceData.*;
  65 import static sun.java2d.opengl.OGLContext.OGLContextCaps.*;
  66 import sun.java2d.opengl.CGLSurfaceData.CGLVSyncOffScreenSurfaceData;
  67 import sun.java2d.pipe.hw.AccelDeviceEventListener;
  68 import sun.java2d.pipe.hw.AccelDeviceEventNotifier;
  69 

  70 import sun.lwawt.macosx.CPlatformView;
  71 
  72 public class CGLGraphicsConfig extends CGraphicsConfig
  73     implements OGLGraphicsConfig, TextureSizeConstraining
  74 {
  75     //private static final int kOpenGLSwapInterval = RuntimeOptions.getCurrentOptions().OpenGLSwapInterval;

  76     private static final int kOpenGLSwapInterval = 0; // TODO
  77     protected static boolean cglAvailable;
  78     private static ImageCapabilities imageCaps = new CGLImageCaps();
  79 
  80     private int pixfmt;
  81     private BufferCapabilities bufferCaps;
  82     private long pConfigInfo;
  83     private ContextCapabilities oglCaps;
  84     private OGLContext context;
  85     private Object disposerReferent = new Object();
  86 
  87     public static native int getDefaultPixFmt(int screennum);
  88     private static native boolean initCGL();
  89     private static native long getCGLConfigInfo(int screennum, int visualnum,
  90                                                 int swapInterval);
  91     private static native int getOGLCapabilities(long configInfo);
  92 
  93     static {
  94         cglAvailable = initCGL();
  95     }
  96 
  97     protected CGLGraphicsConfig(CGraphicsDevice device, int pixfmt,
  98                                 long configInfo, ContextCapabilities oglCaps)
  99     {
 100         super(device);
 101 
 102         this.pixfmt = pixfmt;
 103         this.pConfigInfo = configInfo;
 104         this.oglCaps = oglCaps;
 105         context = new OGLContext(OGLRenderQueue.getInstance(), this);
 106 
 107         // add a record to the Disposer so that we destroy the native
 108         // CGLGraphicsConfigInfo data when this object goes away
 109         Disposer.addRecord(disposerReferent,
 110                            new CGLGCDisposerRecord(pConfigInfo));
 111     }
 112 
 113     @Override
 114     public Object getProxyKey() {
 115         return this;
 116     }
 117 


 153             rq.unlock();
 154         }
 155         if (cfginfo == 0) {
 156             return null;
 157         }
 158 
 159         int oglCaps = getOGLCapabilities(cfginfo);
 160         ContextCapabilities caps = new OGLContextCaps(oglCaps, ids[0]);
 161 
 162         return new CGLGraphicsConfig(device, pixfmt, cfginfo, caps);
 163     }
 164 
 165     public static boolean isCGLAvailable() {
 166         return cglAvailable;
 167     }
 168 
 169     /**
 170      * Returns true if the provided capability bit is present for this config.
 171      * See OGLContext.java for a list of supported capabilities.
 172      */
 173     public final boolean isCapPresent(int cap) {

 174         return ((oglCaps.getCaps() & cap) != 0);
 175     }
 176 
 177     public final long getNativeConfigInfo() {

 178         return pConfigInfo;
 179     }
 180 
 181     /**
 182      * {@inheritDoc}
 183      *
 184      * @see sun.java2d.pipe.hw.BufferedContextProvider#getContext
 185      */
 186     public final OGLContext getContext() {

 187         return context;
 188     }
 189 
 190     @Override
 191     public BufferedImage createCompatibleImage(int width, int height) {
 192         ColorModel model = new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
 193         WritableRaster
 194             raster = model.createCompatibleWritableRaster(width, height);
 195         return new BufferedImage(model, raster, model.isAlphaPremultiplied(),
 196                                  null);
 197     }
 198 
 199     @Override
 200     public ColorModel getColorModel(int transparency) {
 201         switch (transparency) {
 202         case Transparency.OPAQUE:
 203             // REMIND: once the ColorModel spec is changed, this should be
 204             //         an opaque premultiplied DCM...
 205             return new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
 206         case Transparency.BITMASK:


 240         // the context could hold a reference to a CGLSurfaceData, which in
 241         // turn has a reference back to this CGLGraphicsConfig, so in order
 242         // for this instance to be disposed we need to break the connection
 243         OGLRenderQueue rq = OGLRenderQueue.getInstance();
 244         rq.lock();
 245         try {
 246             OGLContext.invalidateCurrentContext();
 247         } finally {
 248             rq.unlock();
 249         }
 250 
 251         updateTotalDisplayBounds();
 252     }
 253 
 254     @Override
 255     public String toString() {
 256         int screen = getDevice().getCoreGraphicsScreen();
 257         return ("CGLGraphicsConfig[dev="+screen+",pixfmt="+pixfmt+"]");
 258     }
 259 
 260 
 261     /**
 262      * The following methods are invoked from ComponentModel.java rather
 263      * than having the Mac OS X-dependent implementations hardcoded in that
 264      * class.  This way the appropriate actions are taken based on the peer's
 265      * GraphicsConfig, whether it is a CGraphicsConfig or a
 266      * CGLGraphicsConfig.
 267      */
 268 
 269     /**
 270      * Creates a new SurfaceData that will be associated with the given
 271      * LWWindowPeer.
 272      */
 273     @Override
 274     public SurfaceData createSurfaceData(CPlatformView pView) {
 275         return CGLSurfaceData.createData(pView);
 276     }
 277 
 278     /**
 279      * Creates a new SurfaceData that will be associated with the given
 280      * CGLLayer.
 281      */
 282     @Override
 283     public SurfaceData createSurfaceData(CGLLayer layer) {
 284         return CGLSurfaceData.createData(layer);
 285     }
 286 
 287     /**
 288      * Creates a new hidden-acceleration image of the given width and height
 289      * that is associated with the target Component.
 290      */
 291     @Override
 292     public Image createAcceleratedImage(Component target,
 293                                         int width, int height)
 294     {
 295         ColorModel model = getColorModel(Transparency.OPAQUE);
 296         WritableRaster wr =
 297             model.createCompatibleWritableRaster(width, height);
 298         return new OffScreenImage(target, model, wr,
 299                                   model.isAlphaPremultiplied());
 300     }
 301 
 302     /**
 303      * The following methods correspond to the multibuffering methods in
 304      * CWindowPeer.java...
 305      */
 306 
 307     /**
 308      * Attempts to create a OGL-based backbuffer for the given peer.  If
 309      * the requested configuration is not natively supported, an AWTException
 310      * is thrown.  Otherwise, if the backbuffer creation is successful, a
 311      * value of 1 is returned.
 312      */
 313     @Override
 314     public long createBackBuffer(CPlatformView pView,
 315                                  int numBuffers, BufferCapabilities caps)
 316         throws AWTException
 317     {
 318         if (numBuffers > 2) {
 319             throw new AWTException(
 320                 "Only double or single buffering is supported");


 321         }
 322         BufferCapabilities configCaps = getBufferCapabilities();
 323         if (!configCaps.isPageFlipping()) {
 324             throw new AWTException("Page flipping is not supported");
 325         }
 326         if (caps.getFlipContents() == BufferCapabilities.FlipContents.PRIOR) {
 327             throw new AWTException("FlipContents.PRIOR is not supported");
 328         }
 329 
 330         // non-zero return value means backbuffer creation was successful
 331         // (checked in CPlatformWindow.flip(), etc.)
 332         return 1;
 333     }
 334 
 335     /**
 336      * Destroys the backbuffer object represented by the given handle value.
 337      */
 338     @Override
 339     public void destroyBackBuffer(long backBuffer) {








 340     }
 341 
 342     /**
 343      * Creates a VolatileImage that essentially wraps the target Component's
 344      * backbuffer (the provided backbuffer handle is essentially ignored).
 345      */
 346     @Override
 347     public VolatileImage createBackBufferImage(Component target,
 348                                                long backBuffer)
 349     {
 350         return new SunVolatileImage(target,
 351                                     target.getWidth(), target.getHeight(),
 352                                     Boolean.TRUE);
 353     }
 354 
 355     /**
 356      * Performs the native OGL flip operation for the given target Component.
 357      */
 358     @Override
 359     public void flip(CPlatformView pView,
 360                      Component target, VolatileImage xBackBuffer,
 361                      int x1, int y1, int x2, int y2,
 362                      BufferCapabilities.FlipContents flipAction)
 363     {
 364         if (flipAction == BufferCapabilities.FlipContents.COPIED) {
 365             SurfaceManager vsm = SurfaceManager.getManager(xBackBuffer);
 366             SurfaceData sd = vsm.getPrimarySurfaceData();
 367 
 368             if (sd instanceof CGLVSyncOffScreenSurfaceData) {
 369                 CGLVSyncOffScreenSurfaceData vsd =
 370                     (CGLVSyncOffScreenSurfaceData)sd;
 371                 SurfaceData bbsd = vsd.getFlipSurface();
 372                 Graphics2D bbg =
 373                     new SunGraphics2D(bbsd, Color.black, Color.white, null);
 374                 try {
 375                     bbg.drawImage(xBackBuffer, 0, 0, null);
 376                 } finally {
 377                     bbg.dispose();
 378                 }
 379             } else {
 380                 pView.drawImageOnPeer(xBackBuffer, x1, y1, x2, y2);
 381                 return;
 382             }
 383         } else if (flipAction == BufferCapabilities.FlipContents.PRIOR) {
 384             // not supported by CGL...
 385             return;
 386         }
 387 
 388         OGLSurfaceData.swapBuffers(pView.getAWTView());
 389 
 390         if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) {
 391             Graphics g = xBackBuffer.getGraphics();
 392             try {
 393                 g.setColor(target.getBackground());
 394                 g.fillRect(0, 0,
 395                            xBackBuffer.getWidth(),
 396                            xBackBuffer.getHeight());
 397             } finally {
 398                 g.dispose();
 399             }
 400         }
 401     }
 402 
 403     private static class CGLBufferCaps extends BufferCapabilities {
 404         public CGLBufferCaps(boolean dblBuf) {
 405             super(imageCaps, imageCaps,
 406                   dblBuf ? FlipContents.UNDEFINED : null);
 407         }
 408     }
 409 
 410     @Override
 411     public BufferCapabilities getBufferCapabilities() {
 412         if (bufferCaps == null) {
 413             bufferCaps = new CGLBufferCaps(isDoubleBuffered());
 414         }
 415         return bufferCaps;
 416     }
 417 
 418     private static class CGLImageCaps extends ImageCapabilities {
 419         private CGLImageCaps() {
 420             super(true);
 421         }
 422         public boolean isTrueVolatile() {
 423             return true;
 424         }
 425     }
 426 
 427     @Override
 428     public ImageCapabilities getImageCapabilities() {
 429         return imageCaps;
 430     }
 431 
 432     /**
 433      * {@inheritDoc}
 434      *
 435      * @see sun.java2d.pipe.hw.AccelGraphicsConfig#createCompatibleVolatileImage
 436      */
 437     public VolatileImage
 438         createCompatibleVolatileImage(int width, int height,
 439                                       int transparency, int type)
 440     {
 441         if (type == FLIP_BACKBUFFER || type == WINDOW || type == UNDEFINED ||
 442             transparency == Transparency.BITMASK)
 443         {
 444             return null;
 445         }
 446 
 447         if (type == FBOBJECT) {
 448             if (!isCapPresent(CAPS_EXT_FBOBJECT)) {
 449                 return null;
 450             }
 451         } else if (type == PBUFFER) {
 452             boolean isOpaque = transparency == Transparency.OPAQUE;
 453             if (!isOpaque && !isCapPresent(CAPS_STORED_ALPHA)) {
 454                 return null;
 455             }
 456         }
 457 
 458         SunVolatileImage vi = new AccelTypedVolatileImage(this, width, height,
 459                                                           transparency, type);
 460         Surface sd = vi.getDestSurface();
 461         if (!(sd instanceof AccelSurface) ||
 462             ((AccelSurface)sd).getType() != type)
 463         {
 464             vi.flush();
 465             vi = null;
 466         }
 467 
 468         return vi;
 469     }
 470 
 471     /**
 472      * {@inheritDoc}
 473      *
 474      * @see sun.java2d.pipe.hw.AccelGraphicsConfig#getContextCapabilities
 475      */

 476     public ContextCapabilities getContextCapabilities() {
 477         return oglCaps;
 478     }
 479 

 480     public void addDeviceEventListener(AccelDeviceEventListener l) {
 481         int screen = getDevice().getCoreGraphicsScreen();
 482         AccelDeviceEventNotifier.addListener(l, screen);
 483     }
 484 

 485     public void removeDeviceEventListener(AccelDeviceEventListener l) {
 486         AccelDeviceEventNotifier.removeListener(l);
 487     }
 488 
 489     private static final Rectangle totalDisplayBounds = new Rectangle();
 490 
 491     private static void updateTotalDisplayBounds() {
 492         synchronized (totalDisplayBounds) {
 493             Rectangle virtualBounds = new Rectangle();
 494             for (GraphicsDevice gd : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) {
 495                 for (GraphicsConfiguration gc : gd.getConfigurations()) {
 496                     virtualBounds = virtualBounds.union(gc.getBounds());
 497                 }
 498             }
 499             totalDisplayBounds.setBounds(virtualBounds);
 500         }
 501     }
 502 
 503     // 7160609: GL still fails to create a square texture of this size,
 504     //          so we use this value to cap the total display bounds.




  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.java2d.opengl;
  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.Graphics2D;
  33 import java.awt.GraphicsConfiguration;
  34 import java.awt.GraphicsDevice;
  35 import java.awt.GraphicsEnvironment;
  36 import java.awt.Image;
  37 import java.awt.ImageCapabilities;
  38 import java.awt.Rectangle;
  39 import java.awt.Transparency;
  40 import java.awt.color.ColorSpace;
  41 import java.awt.image.BufferedImage;
  42 import java.awt.image.ColorModel;
  43 import java.awt.image.DataBuffer;
  44 import java.awt.image.DirectColorModel;
  45 import java.awt.image.VolatileImage;
  46 import java.awt.image.WritableRaster;
  47 
  48 import sun.awt.CGraphicsConfig;
  49 import sun.awt.CGraphicsDevice;

  50 import sun.awt.image.OffScreenImage;
  51 import sun.awt.image.SunVolatileImage;

  52 import sun.java2d.Disposer;
  53 import sun.java2d.DisposerRecord;

  54 import sun.java2d.Surface;
  55 import sun.java2d.SurfaceData;
  56 import sun.java2d.opengl.OGLContext.OGLContextCaps;
  57 import sun.java2d.pipe.hw.AccelSurface;
  58 import sun.java2d.pipe.hw.AccelTypedVolatileImage;
  59 import sun.java2d.pipe.hw.ContextCapabilities;
  60 import static sun.java2d.opengl.OGLSurfaceData.*;
  61 import static sun.java2d.opengl.OGLContext.OGLContextCaps.*;

  62 import sun.java2d.pipe.hw.AccelDeviceEventListener;
  63 import sun.java2d.pipe.hw.AccelDeviceEventNotifier;
  64 
  65 import sun.lwawt.LWComponentPeer;
  66 import sun.lwawt.macosx.CPlatformView;
  67 
  68 public final class CGLGraphicsConfig extends CGraphicsConfig
  69     implements OGLGraphicsConfig
  70 {
  71     //private static final int kOpenGLSwapInterval =
  72     // RuntimeOptions.getCurrentOptions().OpenGLSwapInterval;
  73     private static final int kOpenGLSwapInterval = 0; // TODO
  74     private static boolean cglAvailable;
  75     private static ImageCapabilities imageCaps = new CGLImageCaps();
  76 
  77     private int pixfmt;
  78     private BufferCapabilities bufferCaps;
  79     private long pConfigInfo;
  80     private ContextCapabilities oglCaps;
  81     private OGLContext context;
  82     private final Object disposerReferent = new Object();
  83 
  84     public static native int getDefaultPixFmt(int screennum);
  85     private static native boolean initCGL();
  86     private static native long getCGLConfigInfo(int screennum, int visualnum,
  87                                                 int swapInterval);
  88     private static native int getOGLCapabilities(long configInfo);
  89 
  90     static {
  91         cglAvailable = initCGL();
  92     }
  93 
  94     private CGLGraphicsConfig(CGraphicsDevice device, int pixfmt,
  95                                 long configInfo, ContextCapabilities oglCaps)
  96     {
  97         super(device);
  98 
  99         this.pixfmt = pixfmt;
 100         this.pConfigInfo = configInfo;
 101         this.oglCaps = oglCaps;
 102         context = new OGLContext(OGLRenderQueue.getInstance(), this);
 103 
 104         // add a record to the Disposer so that we destroy the native
 105         // CGLGraphicsConfigInfo data when this object goes away
 106         Disposer.addRecord(disposerReferent,
 107                            new CGLGCDisposerRecord(pConfigInfo));
 108     }
 109 
 110     @Override
 111     public Object getProxyKey() {
 112         return this;
 113     }
 114 


 150             rq.unlock();
 151         }
 152         if (cfginfo == 0) {
 153             return null;
 154         }
 155 
 156         int oglCaps = getOGLCapabilities(cfginfo);
 157         ContextCapabilities caps = new OGLContextCaps(oglCaps, ids[0]);
 158 
 159         return new CGLGraphicsConfig(device, pixfmt, cfginfo, caps);
 160     }
 161 
 162     public static boolean isCGLAvailable() {
 163         return cglAvailable;
 164     }
 165 
 166     /**
 167      * Returns true if the provided capability bit is present for this config.
 168      * See OGLContext.java for a list of supported capabilities.
 169      */
 170     @Override
 171     public boolean isCapPresent(int cap) {
 172         return ((oglCaps.getCaps() & cap) != 0);
 173     }
 174 
 175     @Override
 176     public long getNativeConfigInfo() {
 177         return pConfigInfo;
 178     }
 179 
 180     /**
 181      * {@inheritDoc}
 182      *
 183      * @see sun.java2d.pipe.hw.BufferedContextProvider#getContext
 184      */
 185     @Override
 186     public OGLContext getContext() {
 187         return context;
 188     }
 189 
 190     @Override
 191     public BufferedImage createCompatibleImage(int width, int height) {
 192         ColorModel model = new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
 193         WritableRaster
 194             raster = model.createCompatibleWritableRaster(width, height);
 195         return new BufferedImage(model, raster, model.isAlphaPremultiplied(),
 196                                  null);
 197     }
 198 
 199     @Override
 200     public ColorModel getColorModel(int transparency) {
 201         switch (transparency) {
 202         case Transparency.OPAQUE:
 203             // REMIND: once the ColorModel spec is changed, this should be
 204             //         an opaque premultiplied DCM...
 205             return new DirectColorModel(24, 0xff0000, 0xff00, 0xff);
 206         case Transparency.BITMASK:


 240         // the context could hold a reference to a CGLSurfaceData, which in
 241         // turn has a reference back to this CGLGraphicsConfig, so in order
 242         // for this instance to be disposed we need to break the connection
 243         OGLRenderQueue rq = OGLRenderQueue.getInstance();
 244         rq.lock();
 245         try {
 246             OGLContext.invalidateCurrentContext();
 247         } finally {
 248             rq.unlock();
 249         }
 250 
 251         updateTotalDisplayBounds();
 252     }
 253 
 254     @Override
 255     public String toString() {
 256         int screen = getDevice().getCoreGraphicsScreen();
 257         return ("CGLGraphicsConfig[dev="+screen+",pixfmt="+pixfmt+"]");
 258     }
 259 













 260     @Override
 261     public SurfaceData createSurfaceData(CPlatformView pView) {
 262         return CGLSurfaceData.createData(pView);
 263     }
 264 




 265     @Override
 266     public SurfaceData createSurfaceData(CGLLayer layer) {
 267         return CGLSurfaceData.createData(layer);
 268     }
 269 




 270     @Override
 271     public Image createAcceleratedImage(Component target,
 272                                         int width, int height)
 273     {
 274         ColorModel model = getColorModel(Transparency.OPAQUE);
 275         WritableRaster wr = model.createCompatibleWritableRaster(width, height);

 276         return new OffScreenImage(target, model, wr,
 277                                   model.isAlphaPremultiplied());
 278     }
 279 











 280     @Override
 281     public void assertOperationSupported(final int numBuffers,
 282                                          final BufferCapabilities caps)
 283             throws AWTException {
 284         // Assume this method is never called with numBuffers != 2, as 0 is
 285         // unsupported, and 1 corresponds to a SingleBufferStrategy which
 286         // doesn't depend on the peer. Screen is considered as a separate
 287         // "buffer".
 288         if (numBuffers != 2) {
 289             throw new AWTException("Only double buffering is supported");
 290         }
 291         final BufferCapabilities configCaps = getBufferCapabilities();
 292         if (!configCaps.isPageFlipping()) {
 293             throw new AWTException("Page flipping is not supported");
 294         }
 295         if (caps.getFlipContents() == BufferCapabilities.FlipContents.PRIOR) {
 296             throw new AWTException("FlipContents.PRIOR is not supported");
 297         }




 298     }
 299 



 300     @Override
 301     public Image createBackBuffer(final LWComponentPeer<?, ?> peer) {
 302         final Rectangle r = peer.getBounds();
 303         // It is possible for the component to have size 0x0, adjust it to
 304         // be at least 1x1 to avoid IAE
 305         final int w = Math.max(1, r.width);
 306         final int h = Math.max(1, r.height);
 307         final int transparency = peer.isTranslucent() ? Transparency.TRANSLUCENT
 308                                                       : Transparency.OPAQUE;
 309         return new SunVolatileImage(this, w, h, transparency, null);
 310     }
 311 




 312     @Override
 313     public void destroyBackBuffer(final Image backBuffer) {
 314         if (backBuffer != null) {
 315             backBuffer.flush();
 316         }


 317     }
 318 



 319     @Override
 320     public void flip(final LWComponentPeer<?, ?> peer, final Image backBuffer,
 321                      final int x1, final int y1, final int x2, final int y2,
 322                      final BufferCapabilities.FlipContents flipAction) {
 323         final Graphics g = peer.getGraphics();











 324         try {
 325             g.drawImage(backBuffer, x1, y1, x2, y2, x1, y1, x2, y2, null);
 326         } finally {
 327             g.dispose();








 328         }



 329         if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) {
 330             final Graphics2D bg = (Graphics2D) backBuffer.getGraphics();
 331             try {
 332                 bg.setBackground(peer.getBackground());
 333                 bg.clearRect(0, 0, backBuffer.getWidth(null),
 334                              backBuffer.getHeight(null));

 335             } finally {
 336                 bg.dispose();
 337             }
 338         }
 339     }
 340 
 341     private static class CGLBufferCaps extends BufferCapabilities {
 342         public CGLBufferCaps(boolean dblBuf) {
 343             super(imageCaps, imageCaps,
 344                   dblBuf ? FlipContents.UNDEFINED : null);
 345         }
 346     }
 347 
 348     @Override
 349     public BufferCapabilities getBufferCapabilities() {
 350         if (bufferCaps == null) {
 351             bufferCaps = new CGLBufferCaps(isDoubleBuffered());
 352         }
 353         return bufferCaps;
 354     }
 355 
 356     private static class CGLImageCaps extends ImageCapabilities {
 357         private CGLImageCaps() {
 358             super(true);
 359         }
 360         public boolean isTrueVolatile() {
 361             return true;
 362         }
 363     }
 364 
 365     @Override
 366     public ImageCapabilities getImageCapabilities() {
 367         return imageCaps;
 368     }
 369 
 370     @Override
 371     public VolatileImage createCompatibleVolatileImage(int width, int height,
 372                                                        int transparency,
 373                                                        int type) {





 374         if (type == FLIP_BACKBUFFER || type == WINDOW || type == UNDEFINED ||
 375             transparency == Transparency.BITMASK)
 376         {
 377             return null;
 378         }
 379 
 380         if (type == FBOBJECT) {
 381             if (!isCapPresent(CAPS_EXT_FBOBJECT)) {
 382                 return null;
 383             }
 384         } else if (type == PBUFFER) {
 385             boolean isOpaque = transparency == Transparency.OPAQUE;
 386             if (!isOpaque && !isCapPresent(CAPS_STORED_ALPHA)) {
 387                 return null;
 388             }
 389         }
 390 
 391         SunVolatileImage vi = new AccelTypedVolatileImage(this, width, height,
 392                                                           transparency, type);
 393         Surface sd = vi.getDestSurface();
 394         if (!(sd instanceof AccelSurface) ||
 395             ((AccelSurface)sd).getType() != type)
 396         {
 397             vi.flush();
 398             vi = null;
 399         }
 400 
 401         return vi;
 402     }
 403 
 404     /**
 405      * {@inheritDoc}
 406      *
 407      * @see sun.java2d.pipe.hw.AccelGraphicsConfig#getContextCapabilities
 408      */
 409     @Override
 410     public ContextCapabilities getContextCapabilities() {
 411         return oglCaps;
 412     }
 413 
 414     @Override
 415     public void addDeviceEventListener(AccelDeviceEventListener l) {
 416         int screen = getDevice().getCoreGraphicsScreen();
 417         AccelDeviceEventNotifier.addListener(l, screen);
 418     }
 419 
 420     @Override
 421     public void removeDeviceEventListener(AccelDeviceEventListener l) {
 422         AccelDeviceEventNotifier.removeListener(l);
 423     }
 424 
 425     private static final Rectangle totalDisplayBounds = new Rectangle();
 426 
 427     private static void updateTotalDisplayBounds() {
 428         synchronized (totalDisplayBounds) {
 429             Rectangle virtualBounds = new Rectangle();
 430             for (GraphicsDevice gd : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) {
 431                 for (GraphicsConfiguration gc : gd.getConfigurations()) {
 432                     virtualBounds = virtualBounds.union(gc.getBounds());
 433                 }
 434             }
 435             totalDisplayBounds.setBounds(virtualBounds);
 436         }
 437     }
 438 
 439     // 7160609: GL still fails to create a square texture of this size,
 440     //          so we use this value to cap the total display bounds.