/*****************************************************************************
 *                     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.x1164;

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

import org.eclipse.swt.internal.Platform;

import com.sun.opengl.impl.x11.GLX;
import com.sun.opengl.impl.x11.GLXExt;
import com.sun.opengl.impl.x11.GLXFBConfig;

// Local imports
// None

/**
 *
 *
 * @author Justin Couch
 * @version $Revision: 1.1 $
 */
class X11PbufferGLContext extends X11GLContext
{
    /** The drawable that owns this context instance */
    private X11GLDrawable x11Drawable;

    /** The frame buffer config from the parent drawable */
    private GLXFBConfig fbConfig;

    /**
     * Create a new context instance for the given pbuffer.
     */
    X11PbufferGLContext(X11GLDrawable owner,
                        GLXFBConfig fbConfig,
                        GLContext shareWith)
    {
        super(owner, shareWith);

        x11Drawable = owner;
        this.fbConfig = fbConfig;
    }

    public void bindPbufferToTexture()
    {
        // FIXME: figure out how to implement this
        throw new GLException("Not yet implemented");
    }

    public void releasePbufferFromTexture()
    {
        // FIXME: figure out how to implement this
        throw new GLException("Not yet implemented");
    }

    //---------------------------------------------------------------------------
    // Methods defined by GLContextImpl
    //---------------------------------------------------------------------------

    protected int makeCurrentImpl() throws GLException
    {
        if(x11Drawable.getDrawable() == 0)
            return CONTEXT_NOT_CURRENT;

        // Note that we have to completely override makeCurrentImpl
        // because the underlying makeCurrent call differs for pbuffers
        Platform.lock.lock();

        try
        {
            boolean created = false;
            if(context == 0)
            {
                create();
                created = true;
            }

            if(!GLX.glXMakeContextCurrent(x11Drawable.getDisplay(),
                                          x11Drawable.getDrawable(),
                                          x11Drawable.getDrawable(),
                                          context))
            {
                throw new GLException("Error making context current");
            }
            else
            {
                mostRecentDisplay = x11Drawable.getDisplay();
            }

            if(created)
            {
                resetGLFunctionAvailability();
                return CONTEXT_CURRENT_NEW;
            }

            return CONTEXT_CURRENT;
        }
        finally
        {
            Platform.lock.unlock();
        }
    }

    /**
     * Release the pbuffer context now.
     */
    protected void releaseImpl() throws GLException
    {
        Platform.lock.lock();

        try
        {
            if (drawable.getDisplay() == 0)
                throw new GLException("Pbuffer destroyed out from under application-created context");

            if (!GLX.glXMakeContextCurrent(drawable.getDisplay(), 0, 0, 0))
                throw new GLException("Error freeing OpenGL context");
        }
        finally
        {
            Platform.lock.unlock();
        }
    }

    public int getFloatingPointMode()
    {
        // Floating-point pbuffers currently require NVidia hardware on X11
        return GLPbuffer.NV_FLOAT;
    }

    protected void create()
    {
        // Create a gl context for the p-buffer.
        X11GLContext other =
            (X11GLContext)GLContextShareSet.getShareContext(this);
        long share = 0;

        if (other != null)
        {
            share = other.getContext();
            if(share == 0)
                throw new GLException("GLContextShareSet returned an invalid OpenGL context");
        }

        context = GLX.glXCreateNewContext(x11Drawable.getDisplay(),
                                          fbConfig,
                                          GLXExt.GLX_RGBA_TYPE,
                                          share,
                                          true);
        if(context == 0)
            throw new GLException("pbuffer creation error: glXCreateNewContext() failed");

        GLContextShareSet.contextCreated(this);
    }
}
