Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/windows/classes/sun/java2d/opengl/WGLGraphicsConfig.java
32288 views
/*1* Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.java2d.opengl;2627import java.awt.AWTException;28import java.awt.BufferCapabilities;29import java.awt.BufferCapabilities.FlipContents;30import java.awt.Color;31import java.awt.Component;32import java.awt.Graphics;33import java.awt.Graphics2D;34import java.awt.ImageCapabilities;35import java.awt.Transparency;36import java.awt.color.ColorSpace;37import java.awt.image.ColorModel;38import java.awt.image.DataBuffer;39import java.awt.image.DirectColorModel;40import java.awt.image.VolatileImage;41import sun.awt.Win32GraphicsConfig;42import sun.awt.Win32GraphicsDevice;43import sun.awt.image.SunVolatileImage;44import sun.awt.image.SurfaceManager;45import sun.awt.windows.WComponentPeer;46import sun.java2d.Disposer;47import sun.java2d.DisposerRecord;48import sun.java2d.SunGraphics2D;49import sun.java2d.Surface;50import sun.java2d.SurfaceData;51import sun.java2d.pipe.hw.AccelSurface;52import sun.java2d.pipe.hw.AccelTypedVolatileImage;53import sun.java2d.pipe.hw.ContextCapabilities;54import static sun.java2d.opengl.OGLContext.OGLContextCaps.*;55import static sun.java2d.opengl.WGLSurfaceData.*;56import sun.java2d.opengl.OGLContext.OGLContextCaps;57import sun.java2d.pipe.hw.AccelDeviceEventListener;58import sun.java2d.pipe.hw.AccelDeviceEventNotifier;59import sun.java2d.windows.GDIWindowSurfaceData;6061public class WGLGraphicsConfig62extends Win32GraphicsConfig63implements OGLGraphicsConfig64{65protected static boolean wglAvailable;66private static ImageCapabilities imageCaps = new WGLImageCaps();6768private BufferCapabilities bufferCaps;69private long pConfigInfo;70private ContextCapabilities oglCaps;71private OGLContext context;72private Object disposerReferent = new Object();7374public static native int getDefaultPixFmt(int screennum);75private static native boolean initWGL();76private static native long getWGLConfigInfo(int screennum, int visualnum);77private static native int getOGLCapabilities(long configInfo);7879static {80wglAvailable = initWGL();81}8283protected WGLGraphicsConfig(Win32GraphicsDevice device, int visualnum,84long configInfo, ContextCapabilities oglCaps)85{86super(device, visualnum);87this.pConfigInfo = configInfo;88this.oglCaps = oglCaps;89context = new OGLContext(OGLRenderQueue.getInstance(), this);9091// add a record to the Disposer so that we destroy the native92// WGLGraphicsConfigInfo data when this object goes away93Disposer.addRecord(disposerReferent,94new WGLGCDisposerRecord(pConfigInfo,95device.getScreen()));96}9798public Object getProxyKey() {99return this;100}101102public SurfaceData createManagedSurface(int w, int h, int transparency) {103return WGLSurfaceData.createData(this, w, h,104getColorModel(transparency),105null,106OGLSurfaceData.TEXTURE);107}108109public static WGLGraphicsConfig getConfig(Win32GraphicsDevice device,110int pixfmt)111{112if (!wglAvailable) {113return null;114}115116long cfginfo = 0;117final String ids[] = new String[1];118OGLRenderQueue rq = OGLRenderQueue.getInstance();119rq.lock();120try {121// getWGLConfigInfo() creates and destroys temporary122// surfaces/contexts, so we should first invalidate the current123// Java-level context and flush the queue...124OGLContext.invalidateCurrentContext();125WGLGetConfigInfo action =126new WGLGetConfigInfo(device.getScreen(), pixfmt);127rq.flushAndInvokeNow(action);128cfginfo = action.getConfigInfo();129if (cfginfo != 0L) {130OGLContext.setScratchSurface(cfginfo);131rq.flushAndInvokeNow(new Runnable() {132public void run() {133ids[0] = OGLContext.getOGLIdString();134}135});136}137} finally {138rq.unlock();139}140if (cfginfo == 0) {141return null;142}143144int oglCaps = getOGLCapabilities(cfginfo);145ContextCapabilities caps = new OGLContextCaps(oglCaps, ids[0]);146147return new WGLGraphicsConfig(device, pixfmt, cfginfo, caps);148}149150/**151* This is a small helper class that allows us to execute152* getWGLConfigInfo() on the queue flushing thread.153*/154private static class WGLGetConfigInfo implements Runnable {155private int screen;156private int pixfmt;157private long cfginfo;158private WGLGetConfigInfo(int screen, int pixfmt) {159this.screen = screen;160this.pixfmt = pixfmt;161}162public void run() {163cfginfo = getWGLConfigInfo(screen, pixfmt);164}165public long getConfigInfo() {166return cfginfo;167}168}169170public static boolean isWGLAvailable() {171return wglAvailable;172}173174/**175* Returns true if the provided capability bit is present for this config.176* See OGLContext.java for a list of supported capabilities.177*/178@Override179public final boolean isCapPresent(int cap) {180return ((oglCaps.getCaps() & cap) != 0);181}182183@Override184public final long getNativeConfigInfo() {185return pConfigInfo;186}187188/**189* {@inheritDoc}190*191* @see sun.java2d.pipe.hw.BufferedContextProvider#getContext192*/193@Override194public final OGLContext getContext() {195return context;196}197198private static class WGLGCDisposerRecord implements DisposerRecord {199private long pCfgInfo;200private int screen;201public WGLGCDisposerRecord(long pCfgInfo, int screen) {202this.pCfgInfo = pCfgInfo;203}204public void dispose() {205OGLRenderQueue rq = OGLRenderQueue.getInstance();206rq.lock();207try {208rq.flushAndInvokeNow(new Runnable() {209public void run() {210AccelDeviceEventNotifier.211eventOccured(screen,212AccelDeviceEventNotifier.DEVICE_RESET);213AccelDeviceEventNotifier.214eventOccured(screen,215AccelDeviceEventNotifier.DEVICE_DISPOSED);216}217});218} finally {219rq.unlock();220}221if (pCfgInfo != 0) {222OGLRenderQueue.disposeGraphicsConfig(pCfgInfo);223pCfgInfo = 0;224}225}226}227228@Override229public synchronized void displayChanged() {230super.displayChanged();231// the context could hold a reference to a WGLSurfaceData, which in232// turn has a reference back to this WGLGraphicsConfig, so in order233// for this instance to be disposed we need to break the connection234OGLRenderQueue rq = OGLRenderQueue.getInstance();235rq.lock();236try {237OGLContext.invalidateCurrentContext();238} finally {239rq.unlock();240}241}242243@Override244public ColorModel getColorModel(int transparency) {245switch (transparency) {246case Transparency.OPAQUE:247// REMIND: once the ColorModel spec is changed, this should be248// an opaque premultiplied DCM...249return new DirectColorModel(24, 0xff0000, 0xff00, 0xff);250case Transparency.BITMASK:251return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000);252case Transparency.TRANSLUCENT:253ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);254return new DirectColorModel(cs, 32,2550xff0000, 0xff00, 0xff, 0xff000000,256true, DataBuffer.TYPE_INT);257default:258return null;259}260}261262@Override263public String toString() {264return ("WGLGraphicsConfig[dev="+screen+",pixfmt="+visual+"]");265}266267/**268* The following methods are invoked from WComponentPeer.java rather269* than having the Win32-dependent implementations hardcoded in that270* class. This way the appropriate actions are taken based on the peer's271* GraphicsConfig, whether it is a Win32GraphicsConfig or a272* WGLGraphicsConfig.273*/274275/**276* Creates a new SurfaceData that will be associated with the given277* WComponentPeer.278*/279@Override280public SurfaceData createSurfaceData(WComponentPeer peer,281int numBackBuffers)282{283SurfaceData sd = WGLSurfaceData.createData(peer);284if (sd == null) {285sd = GDIWindowSurfaceData.createData(peer);286}287return sd;288}289290/**291* The following methods correspond to the multibuffering methods in292* WComponentPeer.java...293*/294295/**296* Checks that the requested configuration is natively supported; if not,297* an AWTException is thrown.298*/299@Override300public void assertOperationSupported(Component target,301int numBuffers,302BufferCapabilities caps)303throws AWTException304{305if (numBuffers > 2) {306throw new AWTException(307"Only double or single buffering is supported");308}309BufferCapabilities configCaps = getBufferCapabilities();310if (!configCaps.isPageFlipping()) {311throw new AWTException("Page flipping is not supported");312}313if (caps.getFlipContents() == BufferCapabilities.FlipContents.PRIOR) {314throw new AWTException("FlipContents.PRIOR is not supported");315}316}317318/**319* Creates a WGL-based backbuffer for the given peer and returns the320* image wrapper.321*/322@Override323public VolatileImage createBackBuffer(WComponentPeer peer) {324Component target = (Component)peer.getTarget();325// it is possible for the component to have size 0x0, adjust it to326// be at least 1x1 to avoid IAE327int w = Math.max(1, target.getWidth());328int h = Math.max(1, target.getHeight());329return new SunVolatileImage(target,330w, h,331Boolean.TRUE);332}333334/**335* Performs the native WGL flip operation for the given target Component.336*/337@Override338public void flip(WComponentPeer peer,339Component target, VolatileImage backBuffer,340int x1, int y1, int x2, int y2,341BufferCapabilities.FlipContents flipAction)342{343if (flipAction == BufferCapabilities.FlipContents.COPIED) {344SurfaceManager vsm = SurfaceManager.getManager(backBuffer);345SurfaceData sd = vsm.getPrimarySurfaceData();346347if (sd instanceof WGLVSyncOffScreenSurfaceData) {348WGLVSyncOffScreenSurfaceData vsd =349(WGLVSyncOffScreenSurfaceData)sd;350SurfaceData bbsd = vsd.getFlipSurface();351Graphics2D bbg =352new SunGraphics2D(bbsd, Color.black, Color.white, null);353try {354bbg.drawImage(backBuffer, 0, 0, null);355} finally {356bbg.dispose();357}358} else {359Graphics g = peer.getGraphics();360try {361g.drawImage(backBuffer,362x1, y1, x2, y2,363x1, y1, x2, y2,364null);365} finally {366g.dispose();367}368return;369}370} else if (flipAction == BufferCapabilities.FlipContents.PRIOR) {371// not supported by WGL...372return;373}374375OGLSurfaceData.swapBuffers(peer.getData());376377if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) {378Graphics g = backBuffer.getGraphics();379try {380g.setColor(target.getBackground());381g.fillRect(0, 0,382backBuffer.getWidth(),383backBuffer.getHeight());384} finally {385g.dispose();386}387}388}389390private static class WGLBufferCaps extends BufferCapabilities {391public WGLBufferCaps(boolean dblBuf) {392super(imageCaps, imageCaps,393dblBuf ? FlipContents.UNDEFINED : null);394}395}396397@Override398public BufferCapabilities getBufferCapabilities() {399if (bufferCaps == null) {400boolean dblBuf = isCapPresent(CAPS_DOUBLEBUFFERED);401bufferCaps = new WGLBufferCaps(dblBuf);402}403return bufferCaps;404}405406private static class WGLImageCaps extends ImageCapabilities {407private WGLImageCaps() {408super(true);409}410public boolean isTrueVolatile() {411return true;412}413}414415@Override416public ImageCapabilities getImageCapabilities() {417return imageCaps;418}419420/**421* {@inheritDoc}422*423* @see sun.java2d.pipe.hw.AccelGraphicsConfig#createCompatibleVolatileImage424*/425@Override426public VolatileImage427createCompatibleVolatileImage(int width, int height,428int transparency, int type)429{430if (type == FLIP_BACKBUFFER || type == WINDOW || type == UNDEFINED ||431transparency == Transparency.BITMASK)432{433return null;434}435436if (type == FBOBJECT) {437if (!isCapPresent(CAPS_EXT_FBOBJECT)) {438return null;439}440} else if (type == PBUFFER) {441boolean isOpaque = transparency == Transparency.OPAQUE;442if (!isOpaque && !isCapPresent(CAPS_STORED_ALPHA)) {443return null;444}445}446447SunVolatileImage vi = new AccelTypedVolatileImage(this, width, height,448transparency, type);449Surface sd = vi.getDestSurface();450if (!(sd instanceof AccelSurface) ||451((AccelSurface)sd).getType() != type)452{453vi.flush();454vi = null;455}456457return vi;458}459460/**461* {@inheritDoc}462*463* @see sun.java2d.pipe.hw.AccelGraphicsConfig#getContextCapabilities464*/465@Override466public ContextCapabilities getContextCapabilities() {467return oglCaps;468}469470@Override471public void addDeviceEventListener(AccelDeviceEventListener l) {472AccelDeviceEventNotifier.addListener(l, screen.getScreen());473}474475@Override476public void removeDeviceEventListener(AccelDeviceEventListener l) {477AccelDeviceEventNotifier.removeListener(l);478}479}480481482