blob: 73fba4e0b75e14d1317ba38f564e02d87c153ad8 [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.*;
import org.eclipse.swt.widgets.*;
/**
* 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;
Widget widget;
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.data = new GCData ();
gc = drawable.internal_new_GC (data);
if (gc == 0) SWT.error (SWT.ERROR_NO_HANDLES);
// int attrib [] = {
//// GTKGLEXT.GLX_LEVEL,
//// 0,
//// GTKGLEXT.GDK_GL_MODE_RGBA,
// GTKGLEXT.GDK_GL_MODE_DOUBLE,
// GTKGLEXT.GDK_GL_MODE_DEPTH,
// 24,// depth,
// 0
// };
// adding to next line causes badness: XGL.GDK_GL_MODE_INDEX |
int mode = GTKGLEXT.GDK_GL_MODE_RGB | GTKGLEXT.GDK_GL_MODE_DOUBLE | GTKGLEXT.GDK_GL_MODE_DEPTH;
int glconfig = GTKGLEXT.gdk_gl_config_new_by_mode (mode);
// int glconfig = GTKGLEXT.gdk_gl_config_new (attrib);
// for now assume that the Drawable is a Widget
this.widget = (Widget) drawable;
OS.gtk_widget_unrealize (widget.handle);
boolean success = GTKGLEXT.gtk_widget_set_gl_capability (
widget.handle,
glconfig,
0,
true,
GTKGLEXT.GDK_GL_RGBA_TYPE);
OS.gtk_widget_realize(widget.handle);
handle = GTKGLEXT.gtk_widget_create_gl_context (widget.handle, 0, true, GTKGLEXT.GDK_GL_RGBA_TYPE);
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;
// the following causes problems
// int current = GTKGLEXT.gdk_gl_context_get_current ();
// if (current == handle) {
// GTKGLEXT.gdk_gl_drawable_make_current (0, 0);
// }
// int xDisplay = data.display;
// if (XGL.glXGetCurrentContext () == handle) {
// XGL.glXMakeCurrent (xDisplay, 0, 0);
// }
if (selectBufferPtr != 0) OS.g_free(selectBufferPtr);
GTKGLEXT.gdk_gl_context_destroy (handle);
// XGL.glXDestroyContext (xDisplay, handle);
handle = 0;
// gdkDrawable = 0;
// drawable may be disposed
try {
((Drawable)widget).internal_dispose_GC (gc, data);
} catch (SWTException e) {
}
gc = 0;
data.context = data.drawable = data.layout = 0;
data.font = data.clipRgn = data.lineStyle = 0;
widget = 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 = OS.g_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 GTKGLEXT.gdk_gl_context_get_current () == 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) {
Font font = new Font (device, fdata);
// int oldFont = OS.SelectObject (hDC, font.handle);
GTKGLEXT.gdk_gl_font_use_pango_font (font.handle, startIndex, length, base);
// OS.SelectObject (hDC, oldFont);
font.dispose ();
}
/**
* 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);
int currentContext = GTKGLEXT.gdk_gl_context_get_current ();
if (currentContext == handle) return;
if (currentContext != 0) {
int drawable = GTKGLEXT.gdk_gl_context_get_gl_drawable(currentContext);
GTKGLEXT.gdk_gl_drawable_gl_end (drawable);
}
int gdkDrawable = GTKGLEXT.gtk_widget_get_gl_drawable (widget.handle);
GTKGLEXT.gdk_gl_drawable_gl_begin (gdkDrawable, handle);
GTKGLEXT.gdk_gl_drawable_make_current (gdkDrawable, 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 gdkDrawable = GTKGLEXT.gtk_widget_get_gl_drawable (widget.handle);
GTKGLEXT.gdk_gl_drawable_swap_buffers (gdkDrawable);
}
}