001: /*******************************************************************************
002: * Copyright (c) 2000, 2004 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.swt.opengl;
011:
012: import org.eclipse.swt.*;
013: import org.eclipse.swt.graphics.*;
014: import org.eclipse.swt.internal.motif.*;
015: import org.eclipse.swt.opengl.internal.motif.*;
016:
017: /**
018: * Instances of <code>GLContext</code> are used to draw on swt <code>Drawable</code>s
019: * through invocations of provided OpenGL functions.
020: * <p>
021: * Application code must explicitly invoke the <code>GLContext.dispose ()</code>
022: * method to release the operating system resources managed by each instance
023: * when those instances are no longer required. This is <em>particularly</em>
024: * important on Windows95 and Windows98 where the operating system has a limited
025: * number of device contexts available.
026: * </p>
027: */
028: public class GLContext {
029: int handle;
030: int gc;
031: GCData data;
032: Drawable drawable;
033: int selectBufferPtr = 0;
034:
035: static final int MSB_FIRST = 1;
036: static final int LSB_FIRST = 2;
037:
038: /**
039: * Constructs a new instance of this class which has been
040: * configured to draw on the specified drawable.
041: * <p>
042: * You must dispose the <code>GLContext</code> when it is no longer required.
043: * </p>
044: *
045: * @param drawable the drawable to draw on
046: * @exception IllegalArgumentException <ul>
047: * <li>ERROR_NULL_ARGUMENT - if the drawable is null</li>
048: * </ul>
049: * @exception SWTError <ul>
050: * <li>ERROR_NO_HANDLES if a handle could not be obtained for gc creation</li>
051: * <li>ERROR_UNSUPPORTED_DEPTH - if the current display depth is not supported</li>
052: * </ul>
053: */
054: public GLContext(Drawable drawable) {
055: if (drawable == null)
056: SWT.error(SWT.ERROR_NULL_ARGUMENT);
057: this .drawable = drawable;
058: this .data = new GCData();
059: gc = drawable.internal_new_GC(data);
060: if (gc == 0)
061: SWT.error(SWT.ERROR_NO_HANDLES);
062: int xDisplay = data.display;
063: int screen = OS.XDefaultScreen(xDisplay);
064: int depth = OS.XDefaultDepthOfScreen(OS
065: .XDefaultScreenOfDisplay(xDisplay));
066: int attrib[] = { XGL.GLX_LEVEL, 0, XGL.GLX_RGBA,
067: XGL.GLX_DOUBLEBUFFER,
068: // XGL.GLX_DEPTH_SIZE,
069: // depth,
070: 0 };
071: int infoPtr = XGL.glXChooseVisual(xDisplay, screen, attrib);
072: if (infoPtr == 0)
073: SWT.error(SWT.ERROR_UNSUPPORTED_DEPTH);
074: XVisualInfo info = new XVisualInfo();
075: XGL.memmove(info, infoPtr, XVisualInfo.sizeof);
076: OS.XFree(infoPtr);
077: handle = XGL.glXCreateContext(xDisplay, info, 0, false);
078: if (handle == 0)
079: SWT.error(SWT.ERROR_NO_HANDLES);
080: }
081:
082: public ImageData convertImageData(ImageData source) {
083: PaletteData palette = new PaletteData(0xff0000, 0xff00, 0xff);
084: ImageData newSource = new ImageData(source.width,
085: source.height, 24, palette);
086: ImageDataUtil.blit(1, source.data, source.depth,
087: source.bytesPerLine, (source.depth != 16) ? MSB_FIRST
088: : LSB_FIRST, 0, 0, source.width, source.height,
089: source.palette.redMask, source.palette.greenMask,
090: source.palette.blueMask, 255, null, 0, 0, 0,
091: newSource.data, newSource.depth,
092: newSource.bytesPerLine,
093: (newSource.depth != 16) ? MSB_FIRST : LSB_FIRST, 0, 0,
094: newSource.width, newSource.height,
095: newSource.palette.redMask, newSource.palette.greenMask,
096: newSource.palette.blueMask, false, true);
097:
098: return newSource;
099: }
100:
101: /**
102: * Disposes of the operating system resources associated with
103: * the receiver. Applications must dispose of all <code>GLContext</code>s
104: * that they allocate.
105: */
106: public void dispose() {
107: if (handle == 0)
108: return;
109: int xDisplay = data.display;
110: if (XGL.glXGetCurrentContext() == handle) {
111: XGL.glXMakeCurrent(xDisplay, 0, 0);
112: }
113: if (selectBufferPtr != 0)
114: OS.XtFree(selectBufferPtr);
115: XGL.glXDestroyContext(xDisplay, handle);
116: handle = 0;
117: // drawable may be disposed
118: try {
119: drawable.internal_dispose_GC(gc, data);
120: } catch (SWTException e) {
121: }
122: gc = 0;
123: data.display = data.drawable = data.colormap = 0;
124: /*data.fontList =*/data.clipRgn = data.renderTable = 0;
125: drawable = null;
126: data.device = null;
127: data.image = null;
128: //data.codePage = null;
129: data = null;
130: }
131:
132: public int[] getSelectBuffer(int selectBufferPtr, int[] selectBuffer) {
133: OS.memmove(selectBuffer, selectBufferPtr,
134: selectBuffer.length * 4);
135: return selectBuffer;
136: }
137:
138: public int getSelectBufferPtr(int[] selectBuffer) {
139: if (selectBufferPtr == 0) {
140: selectBufferPtr = OS.XtMalloc(selectBuffer.length * 4);
141: }
142: OS.memmove(selectBufferPtr, selectBuffer,
143: selectBuffer.length * 4);
144: return selectBufferPtr;
145: }
146:
147: /**
148: * Returns a boolean indicating whether the receiver is the current
149: * <code>GLContext</code>.
150: *
151: * @return true if the receiver is the current <code>GLContext</code>,
152: * false otherwise
153: * @exception SWTError <ul>
154: * <li>ERROR_GRAPHIC_DISPOSED if the receiver is disposed</li>
155: * </ul>
156: */
157: public boolean isCurrent() {
158: if (isDisposed())
159: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
160: return XGL.glXGetCurrentContext() == handle;
161: }
162:
163: /**
164: * Returns a boolean indicating whether the <code>GLContext</code> has been
165: * disposed.
166: * <p>
167: * This method gets the dispose state for the <code>GLContext</code>.
168: * When a <code>GLContext</code> has been disposed, it is an error to
169: * invoke any other method using the <code>GLContext</code>.
170: *
171: * @return true if the <code>GLContext</code> is disposed, false otherwise
172: */
173: public boolean isDisposed() {
174: return handle == 0;
175: }
176:
177: /**
178: * Loads the specified bitmap font.
179: *
180: * @param fdata
181: * @param device
182: * @param base
183: * @param first
184: * @param count
185: */
186: public void loadBitmapFont(FontData fdata, Device device, int base,
187: int startIndex, int length) {
188: /* Temporary code, due some problems when running on UTF-8 loadBitmapFont ()
189: * is restrict to works only for ascii.
190: * Note: en_US.ISO8859-1 also code be used.
191: */
192: fdata.setLocale("C");
193: Font font = new Font(device, fdata);
194: int fontList = font.handle;
195: int[] buffer = new int[1];
196: if (!OS.XmFontListInitFontContext(buffer, fontList))
197: return;
198: int context = buffer[0];
199: XFontStruct fontStruct = new XFontStruct();
200: int fontListEntry;
201: int[] fontStructPtr = new int[1];
202: int[] fontNamePtr = new int[1];
203: int xfont = 0;
204: // go through each entry in the font list
205: while ((fontListEntry = OS.XmFontListNextEntry(context)) != 0) {
206: int fontPtr = OS.XmFontListEntryGetFont(fontListEntry,
207: buffer);
208: if (buffer[0] == OS.XmFONT_IS_FONT) {
209: // FontList contains a single font
210: OS.memmove(fontStruct, fontPtr, 20 * 4);
211: xfont = fontStruct.fid;
212: } else {
213: // FontList contains a fontSet
214: int nFonts = OS.XFontsOfFontSet(fontPtr, fontStructPtr,
215: fontNamePtr);
216: int[] fontStructs = new int[nFonts];
217: OS.memmove(fontStructs, fontStructPtr[0], nFonts * 4);
218: // Go through each fontStruct in the font set.
219: for (int i = 0; i < nFonts; i++) {
220: OS.memmove(fontStruct, fontStructs[i],
221: XFontStruct.sizeof);
222: xfont = fontStruct.fid;
223: }
224: }
225: }
226: if (xfont != 0) {
227: XGL.glXUseXFont(xfont, startIndex, length, base);
228: }
229: font.dispose();
230: OS.XmFontListFreeFontContext(context);
231: }
232:
233: /**
234: * Loads the specified outline font.
235: *
236: * @param fdata
237: * @param device
238: * @param base
239: * @param first
240: * @param count
241: * @param deviation
242: * @param extrusion
243: * @param format
244: * @param lpgmf
245: */
246: public void loadOutlineFont(FontData fdata, Device device,
247: int base, int first, int count, float deviation,
248: float extrusion, int format, GLYPHMETRICSFLOAT[] lpgmf) {
249: // stub
250: }
251:
252: /**
253: * Resizes the receiver.
254: *
255: * @param x
256: * @param y
257: * @param width
258: * @param height
259: */
260: public void resize(int x, int y, int width, int height) {
261: if (height == 0)
262: height = 1;
263: GL.glViewport(x, y, width, height);
264: GL.glMatrixMode(GL.GL_PROJECTION);
265: GL.glLoadIdentity();
266: GLU.gluPerspective(45.0f, (float) width / (float) height, 0.1f,
267: 100.0f);
268: GL.glMatrixMode(GL.GL_MODELVIEW);
269: GL.glLoadIdentity();
270: }
271:
272: /**
273: * Sets the receiver to be the current <code>GLContext</code>.
274: *
275: * @exception SWTError <ul>
276: * <li>ERROR_GRAPHIC_DISPOSED if the receiver is disposed</li>
277: * </ul>
278: */
279: public void setCurrent() {
280: if (isDisposed())
281: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
282: if (XGL.glXGetCurrentContext() == handle)
283: return;
284: XGL.glXMakeCurrent(data.display, data.drawable, handle);
285: }
286:
287: /**
288: * Swaps the receiver's buffers.
289: *
290: * @exception SWTError <ul>
291: * <li>ERROR_GRAPHIC_DISPOSED if the receiver is disposed</li>
292: * </ul>
293: */
294: public void swapBuffers() {
295: if (isDisposed())
296: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
297: XGL.glXSwapBuffers(data.display, data.drawable);
298: }
299: }
|