/*******************************************************************************
 * 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);
	}
}
