blob: 0acee0d4ec60619abf337029414219e895f2400a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.opengl;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.gtk.*;
import org.eclipse.swt.opengl.internal.gtk.*;
/**
* Instances of <code>GLContext</code> are used to draw on swt <code>Drawable</code>s
* through invocations of provided OpenGL functions.
* <p>
* Application code must explicitly invoke the <code>GLContext.dispose ()</code>
* method to release the operating system resources managed by each instance
* when those instances are no longer required. This is <em>particularly</em>
* important on Windows95 and Windows98 where the operating system has a limited
* number of device contexts available.
* </p>
*/
public class GLContext {
int handle;
int gc;
GCData data;
Drawable drawable;
int selectBufferPtr = 0;
static final int MSB_FIRST = 1;
static final int LSB_FIRST = 2;
/**
* Constructs a new instance of this class which has been
* configured to draw on the specified drawable.
* <p>
* You must dispose the <code>GLContext</code> when it is no longer required.
* </p>
*
* @param drawable the drawable to draw on
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the drawable is null</li>
* </ul>
* @exception SWTError <ul>
* <li>ERROR_NO_HANDLES if a handle could not be obtained for gc creation</li>
* <li>ERROR_UNSUPPORTED_DEPTH - if the current display depth is not supported</li>
* </ul>
*/
public GLContext (Drawable drawable) {
if (drawable == null) SWT.error (SWT.ERROR_NULL_ARGUMENT);
this.drawable = drawable;
data = new GCData ();
gc = drawable.internal_new_GC (data);
if (gc == 0) SWT.error (SWT.ERROR_NO_HANDLES);
int xDisplay = XGTK.gdk_x11_gc_get_xdisplay (gc);
int screen = XGTK.XDefaultScreen (xDisplay);
int depth = XGTK.XDefaultDepthOfScreen (XGTK.XDefaultScreenOfDisplay (xDisplay));
int attrib [] = {
XGL.GLX_LEVEL,
0,
XGL.GLX_RGBA,
XGL.GLX_DOUBLEBUFFER,
XGL.GLX_DEPTH_SIZE,
depth,
0
};
int infoPtr = XGL.glXChooseVisual (xDisplay, screen, attrib);
if (infoPtr == 0) SWT.error (SWT.ERROR_UNSUPPORTED_DEPTH);
XVisualInfo info = new XVisualInfo ();
XGL.memmove (info, infoPtr, XVisualInfo.sizeof);
XGTK.XFree (infoPtr);
handle = XGL.glXCreateContext (xDisplay, info, 0, false);
if (handle == 0) SWT.error (SWT.ERROR_NO_HANDLES);
}
public ImageData convertImageData (ImageData source) {
PaletteData palette = new PaletteData (0xff0000, 0xff00, 0xff);
ImageData newSource = new ImageData (source.width, source.height, 24, palette);
ImageDataUtil.blit (
1,
source.data,
source.depth,
source.bytesPerLine,
(source.depth != 16) ? MSB_FIRST : LSB_FIRST,
0,
0,
source.width,
source.height,
source.palette.redMask,
source.palette.greenMask,
source.palette.blueMask,
255,
null,
0,
0,
0,
newSource.data,
newSource.depth,
newSource.bytesPerLine,
(newSource.depth != 16) ? MSB_FIRST : LSB_FIRST,
0,
0,
newSource.width,
newSource.height,
newSource.palette.redMask,
newSource.palette.greenMask,
newSource.palette.blueMask,
false,
true);
return newSource;
}
/**
* Disposes of the operating system resources associated with
* the receiver. Applications must dispose of all <code>GLContext</code>s
* that they allocate.
*/
public void dispose () {
if (handle == 0) return;
int xDisplay = XGTK.gdk_x11_gc_get_xdisplay (gc);
if (XGL.glXGetCurrentContext () == handle) {
int display = XGTK.gdk_x11_gc_get_xdisplay (gc);
XGL.glXMakeCurrent (display, 0, 0);
}
if (selectBufferPtr != 0) XGTK.free (selectBufferPtr);
XGL.glXDestroyContext (xDisplay, handle);
handle = 0;
// drawable may be disposed
try {
drawable.internal_dispose_GC (gc, data);
} catch (SWTException e) {
}
gc = 0;
data.clipRgn = data.context = data.drawable = 0;
data.font = data.layout = data.style = 0;
drawable = null;
data.device = null;
data.image = null;
data = null;
}
public int[] getSelectBuffer (int selectBufferPtr, int[] selectBuffer) {
OS.memmove (selectBuffer, selectBufferPtr, selectBuffer.length * 4);
return selectBuffer;
}
public int getSelectBufferPtr (int[] selectBuffer) {
if (selectBufferPtr == 0) {
selectBufferPtr = XGTK.malloc (selectBuffer.length * 4);
}
OS.memmove (selectBufferPtr, selectBuffer, selectBuffer.length * 4);
return selectBufferPtr;
}
/**
* Returns a boolean indicating whether the receiver is the current
* <code>GLContext</code>.
*
* @return true if the receiver is the current <code>GLContext</code>,
* false otherwise
* @exception SWTError <ul>
* <li>ERROR_GRAPHIC_DISPOSED if the receiver is disposed</li>
* </ul>
*/
public boolean isCurrent () {
if (isDisposed ()) SWT.error (SWT.ERROR_GRAPHIC_DISPOSED);
return XGL.glXGetCurrentContext () == handle;
}
/**
* Returns a boolean indicating whether the <code>GLContext</code> has been
* disposed.
* <p>
* This method gets the dispose state for the <code>GLContext</code>.
* When a <code>GLContext</code> has been disposed, it is an error to
* invoke any other method using the <code>GLContext</code>.
*
* @return true if the <code>GLContext</code> is disposed, false otherwise
*/
public boolean isDisposed () {
return handle == 0;
}
/**
* Loads the specified bitmap font.
*
* @param fdata
* @param device
* @param base
* @param first
* @param count
*/
public void loadBitmapFont (FontData fdata, Device device, int base, int startIndex, int length) {
/* Temporary code, due some problems when running on UTF-8 loadBitmapFont ()
* is restrict to works only for ascii.
* Note: en_US.ISO8859-1 also code be used.
*/
// fdata.setLocale ("C");
// Font font = new Font (device, fdata);
// int fontList = font.handle;
// int[] buffer = new int [1];
// if (!OS.XmFontListInitFontContext (buffer, fontList)) return;
// int context = buffer [0];
// XFontStruct fontStruct = new XFontStruct ();
// int fontListEntry;
// int[] fontStructPtr = new int [1];
// int[] fontNamePtr = new int [1];
// int xfont = 0;
// // go through each entry in the font list
// while ((fontListEntry = OS.XmFontListNextEntry (context)) != 0) {
// int fontPtr = OS.XmFontListEntryGetFont (fontListEntry, buffer);
// if (buffer [0] == OS.XmFONT_IS_FONT) {
// // FontList contains a single font
// OS.memmove (fontStruct, fontPtr, 20 * 4);
// xfont = fontStruct.fid;
// } else {
// // FontList contains a fontSet
// int nFonts = OS.XFontsOfFontSet (fontPtr, fontStructPtr, fontNamePtr);
// int[] fontStructs = new int [nFonts];
// OS.memmove (fontStructs, fontStructPtr [0], nFonts * 4);
// // Go through each fontStruct in the font set.
// for (int i = 0; i < nFonts; i++) {
// OS.memmove (fontStruct, fontStructs [i], XFontStruct.sizeof);
// xfont = fontStruct.fid;
// }
// }
// }
// if (xfont != 0) {
// XGL.glXUseXFont (xfont, startIndex, length, base);
// }
// font.dispose ();
// OS.XmFontListFreeFontContext (context);
}
/**
* Loads the specified outline font.
*
* @param fdata
* @param device
* @param base
* @param first
* @param count
* @param deviation
* @param extrusion
* @param format
* @param lpgmf
*/
public void loadOutlineFont (FontData fdata, Device device, int base, int first,
int count, float deviation, float extrusion, int format, GLYPHMETRICSFLOAT[] lpgmf) {
// stub
}
/**
* Resizes the receiver.
*
* @param x
* @param y
* @param width
* @param height
*/
public void resize (int x, int y, int width, int height) {
if (height == 0) height = 1;
GL.glViewport (x, y, width, height);
GL.glMatrixMode (GL.GL_PROJECTION);
GL.glLoadIdentity ();
GLU.gluPerspective (45.0f, (float) width / (float) height, 0.1f, 100.0f);
GL.glMatrixMode (GL.GL_MODELVIEW);
GL.glLoadIdentity ();
}
/**
* Sets the receiver to be the current <code>GLContext</code>.
*
* @exception SWTError <ul>
* <li>ERROR_GRAPHIC_DISPOSED if the receiver is disposed</li>
* </ul>
*/
public void setCurrent () {
if (isDisposed ()) SWT.error (SWT.ERROR_GRAPHIC_DISPOSED);
if (XGL.glXGetCurrentContext () == handle) return;
int display = XGTK.gdk_x11_gc_get_xdisplay (gc);
int drawable = XGTK.gdk_x11_drawable_get_xid (data.drawable);
XGL.glXMakeCurrent (display, drawable, handle);
}
/**
* Swaps the receiver's buffers.
*
* @exception SWTError <ul>
* <li>ERROR_GRAPHIC_DISPOSED if the receiver is disposed</li>
* </ul>
*/
public void swapBuffers () {
if (isDisposed ()) SWT.error (SWT.ERROR_GRAPHIC_DISPOSED);
int display = XGTK.gdk_x11_gc_get_xdisplay (gc);
int drawable = XGTK.gdk_x11_drawable_get_xid(data.drawable);
XGL.glXSwapBuffers (display, drawable);
}
}