blob: 39f2e4956e41f453fb32857621c1d9745b706129 [file] [log] [blame]
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.java2d.opengl;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.ColorModel;
import sun.java2d.SunGraphics2D;
import sun.java2d.SurfaceData;
import sun.lwawt.macosx.CPlatformView;
public abstract class CGLSurfaceData extends OGLSurfaceData {
protected final int scale;
protected final int width;
protected final int height;
protected CPlatformView pView;
private CGLGraphicsConfig graphicsConfig;
native void validate(int xoff, int yoff, int width, int height, boolean isOpaque);
private native void initOps(long pConfigInfo, long pPeerData, long layerPtr,
int xoff, int yoff, boolean isOpaque);
protected native boolean initPbuffer(long pData, long pConfigInfo,
boolean isOpaque, int width, int height);
protected CGLSurfaceData(CGLGraphicsConfig gc, ColorModel cm, int type,
int width, int height) {
super(gc, cm, type);
// TEXTURE shouldn't be scaled, it is used for managed BufferedImages.
scale = type == TEXTURE ? 1 : gc.getDevice().getScaleFactor();
this.width = width * scale;
this.height = height * scale;
}
protected CGLSurfaceData(CPlatformView pView, CGLGraphicsConfig gc,
ColorModel cm, int type,int width, int height)
{
this(gc, cm, type, width, height);
this.pView = pView;
this.graphicsConfig = gc;
long pConfigInfo = gc.getNativeConfigInfo();
long pPeerData = 0L;
boolean isOpaque = true;
if (pView != null) {
pPeerData = pView.getAWTView();
isOpaque = pView.isOpaque();
}
CGLGraphicsConfig.refPConfigInfo(pConfigInfo);
initOps(pConfigInfo, pPeerData, 0, 0, 0, isOpaque);
}
protected CGLSurfaceData(CGLLayer layer, CGLGraphicsConfig gc,
ColorModel cm, int type,int width, int height)
{
this(gc, cm, type, width, height);
this.graphicsConfig = gc;
long pConfigInfo = gc.getNativeConfigInfo();
long layerPtr = 0L;
boolean isOpaque = true;
if (layer != null) {
layerPtr = layer.getPointer();
isOpaque = layer.isOpaque();
}
CGLGraphicsConfig.refPConfigInfo(pConfigInfo);
initOps(pConfigInfo, 0, layerPtr, 0, 0, isOpaque);
}
@Override //SurfaceData
public GraphicsConfiguration getDeviceConfiguration() {
return graphicsConfig;
}
/**
* Creates a SurfaceData object representing the primary (front) buffer of
* an on-screen Window.
*/
public static CGLWindowSurfaceData createData(CPlatformView pView) {
CGLGraphicsConfig gc = getGC(pView);
return new CGLWindowSurfaceData(pView, gc);
}
/**
* Creates a SurfaceData object representing the intermediate buffer
* between the Java2D flusher thread and the AppKit thread.
*/
public static CGLLayerSurfaceData createData(CGLLayer layer) {
CGLGraphicsConfig gc = getGC(layer);
Rectangle r = layer.getBounds();
return new CGLLayerSurfaceData(layer, gc, r.width, r.height);
}
/**
* Creates a SurfaceData object representing the back buffer of a
* double-buffered on-screen Window.
*/
public static CGLOffScreenSurfaceData createData(CPlatformView pView,
Image image, int type) {
CGLGraphicsConfig gc = getGC(pView);
Rectangle r = pView.getBounds();
if (type == FLIP_BACKBUFFER) {
return new CGLOffScreenSurfaceData(pView, gc, r.width, r.height,
image, gc.getColorModel(), FLIP_BACKBUFFER);
} else {
return new CGLVSyncOffScreenSurfaceData(pView, gc, r.width,
r.height, image, gc.getColorModel(), type);
}
}
/**
* Creates a SurfaceData object representing an off-screen buffer (either a
* Pbuffer or Texture).
*/
public static CGLOffScreenSurfaceData createData(CGLGraphicsConfig gc,
int width, int height, ColorModel cm, Image image, int type) {
return new CGLOffScreenSurfaceData(null, gc, width, height, image, cm,
type);
}
public static CGLGraphicsConfig getGC(CPlatformView pView) {
if (pView != null) {
return (CGLGraphicsConfig)pView.getGraphicsConfiguration();
} else {
// REMIND: this should rarely (never?) happen, but what if
// default config is not CGL?
GraphicsEnvironment env = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsDevice gd = env.getDefaultScreenDevice();
return (CGLGraphicsConfig) gd.getDefaultConfiguration();
}
}
public static CGLGraphicsConfig getGC(CGLLayer layer) {
return (CGLGraphicsConfig)layer.getGraphicsConfiguration();
}
public void validate() {
// Overridden in CGLWindowSurfaceData below
}
@Override
public double getDefaultScaleX() {
return scale;
}
@Override
public double getDefaultScaleY() {
return scale;
}
protected native void clearWindow();
public static class CGLWindowSurfaceData extends CGLSurfaceData {
public CGLWindowSurfaceData(CPlatformView pView,
CGLGraphicsConfig gc) {
super(pView, gc, gc.getColorModel(), WINDOW, 0, 0);
}
@Override
public SurfaceData getReplacement() {
return pView.getSurfaceData();
}
@Override
public Rectangle getBounds() {
Rectangle r = pView.getBounds();
return new Rectangle(0, 0, r.width, r.height);
}
/**
* Returns destination Component associated with this SurfaceData.
*/
@Override
public Object getDestination() {
return pView.getDestination();
}
public void validate() {
OGLRenderQueue rq = OGLRenderQueue.getInstance();
rq.lock();
try {
rq.flushAndInvokeNow(new Runnable() {
public void run() {
Rectangle peerBounds = pView.getBounds();
validate(0, 0, peerBounds.width, peerBounds.height, pView.isOpaque());
}
});
} finally {
rq.unlock();
}
}
@Override
public void invalidate() {
super.invalidate();
clearWindow();
}
}
/**
* A surface which implements an intermediate buffer between
* the Java2D flusher thread and the AppKit thread.
*
* This surface serves as a buffer attached to a CGLLayer and
* the layer redirects all painting to the buffer's graphics.
*/
public static class CGLLayerSurfaceData extends CGLSurfaceData {
private CGLLayer layer;
public CGLLayerSurfaceData(CGLLayer layer, CGLGraphicsConfig gc,
int width, int height) {
super(layer, gc, gc.getColorModel(), FBOBJECT, width, height);
this.layer = layer;
initSurface(this.width, this.height);
}
@Override
public SurfaceData getReplacement() {
return layer.getSurfaceData();
}
@Override
boolean isOnScreen() {
return true;
}
@Override
public Rectangle getBounds() {
return new Rectangle(width, height);
}
@Override
public Object getDestination() {
return layer.getDestination();
}
@Override
public int getTransparency() {
return layer.getTransparency();
}
@Override
public void invalidate() {
super.invalidate();
clearWindow();
}
}
/**
* A surface which implements a v-synced flip back-buffer with COPIED
* FlipContents.
*
* This surface serves as a back-buffer to the outside world, while it is
* actually an offscreen surface. When the BufferStrategy this surface
* belongs to is showed, it is first copied to the real private
* FLIP_BACKBUFFER, which is then flipped.
*/
public static class CGLVSyncOffScreenSurfaceData extends
CGLOffScreenSurfaceData {
private CGLOffScreenSurfaceData flipSurface;
public CGLVSyncOffScreenSurfaceData(CPlatformView pView,
CGLGraphicsConfig gc, int width, int height, Image image,
ColorModel cm, int type) {
super(pView, gc, width, height, image, cm, type);
flipSurface = CGLSurfaceData.createData(pView, image,
FLIP_BACKBUFFER);
}
public SurfaceData getFlipSurface() {
return flipSurface;
}
@Override
public void flush() {
flipSurface.flush();
super.flush();
}
}
public static class CGLOffScreenSurfaceData extends CGLSurfaceData {
private Image offscreenImage;
public CGLOffScreenSurfaceData(CPlatformView pView,
CGLGraphicsConfig gc, int width, int height, Image image,
ColorModel cm, int type) {
super(pView, gc, cm, type, width, height);
offscreenImage = image;
initSurface(this.width, this.height);
}
@Override
public SurfaceData getReplacement() {
return restoreContents(offscreenImage);
}
@Override
public Rectangle getBounds() {
if (type == FLIP_BACKBUFFER) {
Rectangle r = pView.getBounds();
return new Rectangle(0, 0, r.width, r.height);
} else {
return new Rectangle(width, height);
}
}
/**
* Returns destination Image associated with this SurfaceData.
*/
@Override
public Object getDestination() {
return offscreenImage;
}
}
// Mac OS X specific APIs for JOGL/Java2D bridge...
// given a surface create and attach GL context, then return it
private native static long createCGLContextOnSurface(CGLSurfaceData sd,
long sharedContext);
public static long createOGLContextOnSurface(Graphics g, long sharedContext) {
SurfaceData sd = ((SunGraphics2D) g).surfaceData;
if ((sd instanceof CGLSurfaceData) == true) {
CGLSurfaceData cglsd = (CGLSurfaceData) sd;
return createCGLContextOnSurface(cglsd, sharedContext);
} else {
return 0L;
}
}
// returns whether or not the makeCurrent operation succeeded
native static boolean makeCGLContextCurrentOnSurface(CGLSurfaceData sd,
long ctx);
public static boolean makeOGLContextCurrentOnSurface(Graphics g, long ctx) {
SurfaceData sd = ((SunGraphics2D) g).surfaceData;
if ((ctx != 0L) && ((sd instanceof CGLSurfaceData) == true)) {
CGLSurfaceData cglsd = (CGLSurfaceData) sd;
return makeCGLContextCurrentOnSurface(cglsd, ctx);
} else {
return false;
}
}
// additional cleanup
private native static void destroyCGLContext(long ctx);
public static void destroyOGLContext(long ctx) {
if (ctx != 0L) {
destroyCGLContext(ctx);
}
}
static void dispose(long pData, long pConfigInfo) {
OGLSurfaceData.dispose(pData, pConfigInfo);
CGLGraphicsConfig.deRefPConfigInfo(pConfigInfo);
}
}