Path: blob/master/src/java.desktop/windows/classes/sun/java2d/opengl/WGLGraphicsConfig.java
41159 views
/*1* Copyright (c) 2004, 2019, 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.Color;30import java.awt.Component;31import java.awt.Graphics;32import java.awt.Graphics2D;33import java.awt.ImageCapabilities;34import java.awt.Transparency;35import java.awt.color.ColorSpace;36import java.awt.image.ColorModel;37import java.awt.image.DataBuffer;38import java.awt.image.DirectColorModel;39import java.awt.image.VolatileImage;4041import 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.opengl.OGLContext.OGLContextCaps;52import sun.java2d.pipe.hw.AccelSurface;53import sun.java2d.pipe.hw.AccelTypedVolatileImage;54import sun.java2d.pipe.hw.ContextCapabilities;55import sun.java2d.windows.GDIWindowSurfaceData;5657import static sun.java2d.opengl.OGLContext.OGLContextCaps.CAPS_DOUBLEBUFFERED;58import static sun.java2d.opengl.OGLContext.OGLContextCaps.CAPS_EXT_FBOBJECT;59import static sun.java2d.opengl.WGLSurfaceData.FBOBJECT;60import static sun.java2d.opengl.WGLSurfaceData.TEXTURE;61import static sun.java2d.opengl.WGLSurfaceData.WGLVSyncOffScreenSurfaceData;6263public final class WGLGraphicsConfig64extends Win32GraphicsConfig65implements OGLGraphicsConfig66{67protected static boolean wglAvailable;68private static ImageCapabilities imageCaps = new WGLImageCaps();6970private BufferCapabilities bufferCaps;71private long pConfigInfo;72private ContextCapabilities oglCaps;73private final OGLContext context;74private Object disposerReferent = new Object();7576public static native int getDefaultPixFmt(int screennum);77private static native boolean initWGL();78private static native long getWGLConfigInfo(int screennum, int visualnum);79private static native int getOGLCapabilities(long configInfo);8081static {82wglAvailable = initWGL();83}8485@SuppressWarnings("deprecation")86protected WGLGraphicsConfig(Win32GraphicsDevice device, int visualnum,87long configInfo, ContextCapabilities oglCaps)88{89super(device, visualnum);90this.pConfigInfo = configInfo;91this.oglCaps = oglCaps;92context = new OGLContext(OGLRenderQueue.getInstance());9394// add a record to the Disposer so that we destroy the native95// WGLGraphicsConfigInfo data when this object goes away96Disposer.addRecord(disposerReferent,97new WGLGCDisposerRecord(pConfigInfo));98}99100@Override101public Object getProxyKey() {102return this;103}104105@Override106public SurfaceData createManagedSurface(int w, int h, int transparency) {107return WGLSurfaceData.createData(this, w, h,108getColorModel(transparency),109null,110OGLSurfaceData.TEXTURE);111}112113public static WGLGraphicsConfig getConfig(Win32GraphicsDevice device,114int pixfmt)115{116if (!wglAvailable) {117return null;118}119120long cfginfo = 0;121final String[] ids = new String[1];122OGLRenderQueue rq = OGLRenderQueue.getInstance();123rq.lock();124try {125// getWGLConfigInfo() creates and destroys temporary126// surfaces/contexts, so we should first invalidate the current127// Java-level context and flush the queue...128OGLContext.invalidateCurrentContext();129WGLGetConfigInfo action =130new WGLGetConfigInfo(device.getScreen(), pixfmt);131rq.flushAndInvokeNow(action);132cfginfo = action.getConfigInfo();133if (cfginfo != 0L) {134OGLContext.setScratchSurface(cfginfo);135rq.flushAndInvokeNow(new Runnable() {136@Override137public void run() {138ids[0] = OGLContext.getOGLIdString();139}140});141}142} finally {143rq.unlock();144}145if (cfginfo == 0) {146return null;147}148149int oglCaps = getOGLCapabilities(cfginfo);150ContextCapabilities caps = new OGLContextCaps(oglCaps, ids[0]);151152return new WGLGraphicsConfig(device, pixfmt, cfginfo, caps);153}154155/**156* This is a small helper class that allows us to execute157* getWGLConfigInfo() on the queue flushing thread.158*/159private static class WGLGetConfigInfo implements Runnable {160private int screen;161private int pixfmt;162private long cfginfo;163private WGLGetConfigInfo(int screen, int pixfmt) {164this.screen = screen;165this.pixfmt = pixfmt;166}167@Override168public void run() {169cfginfo = getWGLConfigInfo(screen, pixfmt);170}171public long getConfigInfo() {172return cfginfo;173}174}175176public static boolean isWGLAvailable() {177return wglAvailable;178}179180/**181* Returns true if the provided capability bit is present for this config.182* See OGLContext.java for a list of supported capabilities.183*/184@Override185public final boolean isCapPresent(int cap) {186return ((oglCaps.getCaps() & cap) != 0);187}188189@Override190public final long getNativeConfigInfo() {191return pConfigInfo;192}193194@Override195public final OGLContext getContext() {196return context;197}198199private static class WGLGCDisposerRecord implements DisposerRecord {200private long pCfgInfo;201public WGLGCDisposerRecord(long pCfgInfo) {202this.pCfgInfo = pCfgInfo;203}204@Override205public void dispose() {206if (pCfgInfo != 0) {207OGLRenderQueue.disposeGraphicsConfig(pCfgInfo);208pCfgInfo = 0;209}210}211}212213@Override214public synchronized void displayChanged() {215super.displayChanged();216// the context could hold a reference to a WGLSurfaceData, which in217// turn has a reference back to this WGLGraphicsConfig, so in order218// for this instance to be disposed we need to break the connection219OGLRenderQueue rq = OGLRenderQueue.getInstance();220rq.lock();221try {222OGLContext.invalidateCurrentContext();223} finally {224rq.unlock();225}226}227228@Override229public ColorModel getColorModel(int transparency) {230switch (transparency) {231case Transparency.OPAQUE:232// REMIND: once the ColorModel spec is changed, this should be233// an opaque premultiplied DCM...234return new DirectColorModel(24, 0xff0000, 0xff00, 0xff);235case Transparency.BITMASK:236return new DirectColorModel(25, 0xff0000, 0xff00, 0xff, 0x1000000);237case Transparency.TRANSLUCENT:238ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);239return new DirectColorModel(cs, 32,2400xff0000, 0xff00, 0xff, 0xff000000,241true, DataBuffer.TYPE_INT);242default:243return null;244}245}246247@Override248public String toString() {249return ("WGLGraphicsConfig[dev="+getDevice()+",pixfmt="+visual+"]");250}251252/**253* The following methods are invoked from WComponentPeer.java rather254* than having the Win32-dependent implementations hardcoded in that255* class. This way the appropriate actions are taken based on the peer's256* GraphicsConfig, whether it is a Win32GraphicsConfig or a257* WGLGraphicsConfig.258*/259260/**261* Creates a new SurfaceData that will be associated with the given262* WComponentPeer.263*/264@Override265public SurfaceData createSurfaceData(WComponentPeer peer,266int numBackBuffers)267{268SurfaceData sd = WGLSurfaceData.createData(peer);269if (sd == null) {270sd = GDIWindowSurfaceData.createData(peer);271}272return sd;273}274275/**276* The following methods correspond to the multibuffering methods in277* WComponentPeer.java...278*/279280/**281* Checks that the requested configuration is natively supported; if not,282* an AWTException is thrown.283*/284@Override285public void assertOperationSupported(Component target,286int numBuffers,287BufferCapabilities caps)288throws AWTException289{290if (numBuffers > 2) {291throw new AWTException(292"Only double or single buffering is supported");293}294BufferCapabilities configCaps = getBufferCapabilities();295if (!configCaps.isPageFlipping()) {296throw new AWTException("Page flipping is not supported");297}298if (caps.getFlipContents() == BufferCapabilities.FlipContents.PRIOR) {299throw new AWTException("FlipContents.PRIOR is not supported");300}301}302303/**304* Creates a WGL-based backbuffer for the given peer and returns the305* image wrapper.306*/307@Override308public VolatileImage createBackBuffer(WComponentPeer peer) {309Component target = (Component)peer.getTarget();310// it is possible for the component to have size 0x0, adjust it to311// be at least 1x1 to avoid IAE312int w = Math.max(1, target.getWidth());313int h = Math.max(1, target.getHeight());314return new SunVolatileImage(target,315w, h,316Boolean.TRUE);317}318319/**320* Performs the native WGL flip operation for the given target Component.321*/322@Override323public void flip(WComponentPeer peer,324Component target, VolatileImage backBuffer,325int x1, int y1, int x2, int y2,326BufferCapabilities.FlipContents flipAction)327{328if (flipAction == BufferCapabilities.FlipContents.COPIED) {329SurfaceManager vsm = SurfaceManager.getManager(backBuffer);330SurfaceData sd = vsm.getPrimarySurfaceData();331332if (sd instanceof WGLVSyncOffScreenSurfaceData) {333WGLVSyncOffScreenSurfaceData vsd =334(WGLVSyncOffScreenSurfaceData)sd;335SurfaceData bbsd = vsd.getFlipSurface();336Graphics2D bbg =337new SunGraphics2D(bbsd, Color.black, Color.white, null);338try {339bbg.drawImage(backBuffer, 0, 0, null);340} finally {341bbg.dispose();342}343} else {344Graphics g = peer.getGraphics();345try {346g.drawImage(backBuffer,347x1, y1, x2, y2,348x1, y1, x2, y2,349null);350} finally {351g.dispose();352}353return;354}355} else if (flipAction == BufferCapabilities.FlipContents.PRIOR) {356// not supported by WGL...357return;358}359360OGLSurfaceData.swapBuffers(peer.getData());361362if (flipAction == BufferCapabilities.FlipContents.BACKGROUND) {363Graphics g = backBuffer.getGraphics();364try {365g.setColor(target.getBackground());366g.fillRect(0, 0,367backBuffer.getWidth(),368backBuffer.getHeight());369} finally {370g.dispose();371}372}373}374375private static class WGLBufferCaps extends BufferCapabilities {376public WGLBufferCaps(boolean dblBuf) {377super(imageCaps, imageCaps,378dblBuf ? FlipContents.UNDEFINED : null);379}380}381382@Override383public BufferCapabilities getBufferCapabilities() {384if (bufferCaps == null) {385boolean dblBuf = isCapPresent(CAPS_DOUBLEBUFFERED);386bufferCaps = new WGLBufferCaps(dblBuf);387}388return bufferCaps;389}390391private static class WGLImageCaps extends ImageCapabilities {392private WGLImageCaps() {393super(true);394}395@Override396public boolean isTrueVolatile() {397return true;398}399}400401@Override402public ImageCapabilities getImageCapabilities() {403return imageCaps;404}405406@Override407public VolatileImage408createCompatibleVolatileImage(int width, int height,409int transparency, int type)410{411if ((type != FBOBJECT && type != TEXTURE)412|| transparency == Transparency.BITMASK413|| type == FBOBJECT && !isCapPresent(CAPS_EXT_FBOBJECT)) {414return null;415}416SunVolatileImage vi = new AccelTypedVolatileImage(this, width, height,417transparency, type);418Surface sd = vi.getDestSurface();419if (!(sd instanceof AccelSurface) ||420((AccelSurface)sd).getType() != type)421{422vi.flush();423vi = null;424}425426return vi;427}428429@Override430public ContextCapabilities getContextCapabilities() {431return oglCaps;432}433}434435436