blob: b2863df75c67151ab0500e9a1a064bc2720b4165 [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.opengl.internal.win32.*;
import org.eclipse.swt.internal.win32.*;
/**
* 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 hDC;
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 ();
hDC = drawable.internal_new_GC (data);
if (hDC == 0) SWT.error (SWT.ERROR_NO_HANDLES);
int bits = OS.GetDeviceCaps (hDC, OS.BITSPIXEL);
int planes = OS.GetDeviceCaps (hDC, OS.PLANES);
int depth = bits * planes;
PIXELFORMATDESCRIPTOR pfd = new PIXELFORMATDESCRIPTOR ();
pfd.nSize = (short) PIXELFORMATDESCRIPTOR.sizeof;
pfd.nVersion = 1;
pfd.dwFlags =
WGL.PFD_DRAW_TO_WINDOW
| WGL.PFD_SUPPORT_OPENGL
| WGL.PFD_DOUBLEBUFFER;
pfd.dwLayerMask = WGL.PFD_MAIN_PLANE;
pfd.iPixelType = (byte) WGL.PFD_TYPE_RGBA;
pfd.cColorBits = (byte) depth;
pfd.cDepthBits = (byte) depth;
pfd.cAccumBits = 0;
pfd.cStencilBits = 0;
int pixelFormat = WGL.ChoosePixelFormat (hDC, pfd);
if (pixelFormat == 0) {
drawable.internal_dispose_GC (hDC, data);
SWT.error (SWT.ERROR_UNSUPPORTED_DEPTH);
}
if (!WGL.SetPixelFormat (hDC, pixelFormat, pfd)) {
drawable.internal_dispose_GC (hDC, data);
SWT.error (SWT.ERROR_UNSUPPORTED_DEPTH);
}
handle = WGL.wglCreateContext (hDC);
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;
if (WGL.wglGetCurrentContext () == handle) {
WGL.wglMakeCurrent (0, 0);
}
WGL.wglDeleteContext (handle);
handle = 0;
// drawable may be disposed
try {
drawable.internal_dispose_GC (hDC, data);
} catch (SWTException e) {
}
int hHeap = OS.GetProcessHeap ();
if (selectBufferPtr != 0) {
OS.HeapFree (hHeap, 0, selectBufferPtr);
}
hDC = 0;
drawable = null;
data.device = null;
data = null;
}
public int[] getSelectBuffer (int selectBufferPtr, int[] selectBuffer) {
OS.MoveMemory (selectBuffer, selectBufferPtr, selectBuffer.length * 4);
return selectBuffer;
}
public int getSelectBufferPtr (int[] selectBuffer) {
if (selectBufferPtr == 0) {
int hHeap = OS.GetProcessHeap ();
selectBufferPtr =
OS.HeapAlloc (
hHeap,
OS.HEAP_ZERO_MEMORY,
selectBuffer.length * 4);
}
OS.MoveMemory (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 WGL.wglGetCurrentContext () == 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 first, int count) {
Font font = new Font (device, fdata);
int oldFont = OS.SelectObject (hDC, font.handle);
WGL.wglUseFontBitmaps (hDC, first, count, 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) {
int ptr = 0;
int hHeap = 0;
if (lpgmf != null && lpgmf.length == count + 1) {
hHeap = OS.GetProcessHeap ();
ptr =
OS.HeapAlloc (
hHeap,
OS.HEAP_ZERO_MEMORY,
count * GLYPHMETRICSFLOAT.sizeof);
}
if (format == GL.GL_POLYGON) {
format = WGL.WGL_FONT_POLYGONS;
}
if (format == GL.GL_LINE) {
format = WGL.WGL_FONT_LINES;
}
Font font = new Font (device, fdata);
int oldFont = OS.SelectObject (hDC, font.handle);
WGL.wglUseFontOutlines (hDC, first, count, base, deviation, extrusion, format, ptr);
OS.SelectObject (hDC, oldFont);
font.dispose ();
if (ptr != 0) {
int sizeof = GLYPHMETRICSFLOAT.sizeof;
for (int i = 0; i < lpgmf.length; i++) {
WGL.MoveMemory (lpgmf [i], ptr + (sizeof * i), sizeof);
};
OS.HeapFree (hHeap, 0, ptr);
}
}
/**
* 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 (0, 0, width, height);
float nRange = 200.0f;
GL.glMatrixMode (GL.GL_PROJECTION);
GL.glLoadIdentity ();
// load projection
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 (WGL.wglGetCurrentContext () == handle) return;
WGL.wglMakeCurrent (hDC, 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);
WGL.SwapBuffers (hDC);
}
}