/*****************************************************************************
 *                    Yumetech, Inc Copyright (c) 2006
 *                            Java Source
 *
 * This source is licensed under the BSD-style License
 * Please read http://www.opensource.org/licenses/bsd-license.php for more
 * information or docs/BSD.txt in the downloaded code.
 *
 * This software comes with the standard NO WARRANTY disclaimer for any
 * purpose. Use it at your own risk. If there's a problem you get to fix it.
 *
 ****************************************************************************/

package org.j3d.opengl.swt.internal.ri.osx;

// External imports
import java.util.*;
import javax.media.opengl.*;
import com.sun.opengl.impl.*;

import java.security.AccessController;
import java.security.PrivilegedAction;

import com.sun.opengl.impl.macosx.agl.AGL;

// Local imports
// None

public class MacPbufferGLContext extends MacGLContext
{
    /**  State for render-to-texture and render-to-texture-rectangle support */
    private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV
    private int texture;             // actual texture object

    private static boolean isTigerOrLater;

    /** Reference to the pBuffer ID from the drawable */
    private long pBufferID;

    static
    {
        String osVersion =
            (String)AccessController.doPrivileged(new PrivilegedAction()
            {
                public Object run()
                {
                    return System.getProperty("os.version");
                }
            }
        );
        StringTokenizer tok = new StringTokenizer(osVersion, ". ");
        int major = Integer.parseInt(tok.nextToken());
        int minor = Integer.parseInt(tok.nextToken());
        isTigerOrLater = ((major > 10) || (minor > 3));
    }

    /**
     * Create a new context instance that wraps the given drawable and references
     * the internal pBuffer ID.
     */
    public MacPbufferGLContext(MacGLDrawable drawable,
                               GLContext shareWith,
                               long bufferId)
    {
        super(drawable, shareWith);
        this.drawable = drawable;
        pBufferID = bufferId;
    }

    public void bindPbufferToTexture()
    {
        GL gl = getGL();
        gl.glBindTexture(textureTarget, texture);
        // FIXME: not clear whether this is really necessary, but since
        // the API docs seem to imply it is and since it doesn't seem to
        // impact performance, leaving it in
        AGL.aglTexImagePBuffer(aglContextID, pBufferID, GL.GL_FRONT);
    }

    public void releasePbufferFromTexture()
    {
    }

    protected int makeCurrentImpl() throws GLException
    {
        if(pBufferID == 0)
        {
            // pbuffer not instantiated yet
            return CONTEXT_NOT_CURRENT;
        }

        int res = super.makeCurrentImpl();

        if(res == CONTEXT_CURRENT_NEW)
        {
            // Initialize render-to-texture support if requested
            boolean rect = drawable.getCapabilities().getPbufferRenderToTextureRectangle();
            GL gl = getGL();
            if(rect)
            {
                if(!gl.isExtensionAvailable("GL_EXT_texture_rectangle"))
                {
                    System.err.println("MacPbufferGLContext: WARNING: GL_EXT_texture_rectangle extension not " +
                                                         "supported; skipping requested render_to_texture_rectangle support for pbuffer");
                    rect = false;
                }
            }

            textureTarget = (rect ? GL.GL_TEXTURE_RECTANGLE_EXT : GL.GL_TEXTURE_2D);
            int[] tmp = new int[1];
            gl.glGenTextures(1, tmp, 0);
            texture = tmp[0];
            gl.glBindTexture(textureTarget, texture);
            gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
            gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
            gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
            gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
            gl.glCopyTexImage2D(textureTarget, 0, GL.GL_RGB, 0, 0, drawable.getWidth(), drawable.getHeight(), 0);
        }
        return res;
    }

    public int getFloatingPointMode()
    {
        return GLPbuffer.APPLE_FLOAT;
    }

    protected boolean create()
    {
        GLCapabilities capabilities = drawable.getCapabilities();
        if(capabilities.getPbufferFloatingPointBuffers() &&
            !isTigerOrLater)
        {
            throw new GLException("Floating-point pbuffers supported only on OS X 10.4 or later");
        }

        if(!super.create(true, capabilities.getPbufferFloatingPointBuffers()))
        {
            return false;
        }

        // Must now associate the pbuffer with our newly-created context
        AGL.aglSetPBuffer(aglContextID, pBufferID, 0, 0, 0);
        return true;
    }
}
