| /******************************************************************************* |
| * Copyright (c) 2000, 2004 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-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.motif.*; |
| import org.eclipse.swt.opengl.internal.motif.*; |
| |
| /** |
| * 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; |
| this.data = new GCData (); |
| gc = drawable.internal_new_GC (data); |
| if (gc == 0) SWT.error (SWT.ERROR_NO_HANDLES); |
| int xDisplay = data.display; |
| int screen = OS.XDefaultScreen (xDisplay); |
| int depth = OS.XDefaultDepthOfScreen (OS.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); |
| OS.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 = data.display; |
| if (XGL.glXGetCurrentContext () == handle) { |
| XGL.glXMakeCurrent (xDisplay, 0, 0); |
| } |
| if (selectBufferPtr != 0) OS.XtFree (selectBufferPtr); |
| XGL.glXDestroyContext (xDisplay, handle); |
| handle = 0; |
| // drawable may be disposed |
| try { |
| drawable.internal_dispose_GC (gc, data); |
| } catch (SWTException e) { |
| } |
| gc = 0; |
| data.display = data.drawable = data.colormap = 0; |
| /*data.fontList =*/ data.clipRgn = data.renderTable = 0; |
| drawable = null; |
| data.device = null; |
| data.image = null; |
| //data.codePage = 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 = OS.XtMalloc (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; |
| XGL.glXMakeCurrent (data.display, data.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); |
| XGL.glXSwapBuffers (data.display, data.drawable); |
| } |
| } |