/*
 * (C) Copyright IBM Corporation 2005
 * All Rights Reserved.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sub license,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
 * IBM,
 * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "glheader.h"
#include <inttypes.h>
#include <GL/gl.h>
#include "indirect.h"
#include "glxclient.h"
#include "indirect_vertex_array.h"
#include <GL/glxproto.h>

static void
do_vertex_attrib_enable( GLuint index, GLboolean val )
{
    __GLXcontext *gc = __glXGetCurrentContext();
    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);

    if ( ! __glXSetArrayEnable( state, GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB,
				index, val ) ) {
	__glXSetError(gc, GL_INVALID_ENUM);
    }
}


void __indirect_glEnableVertexAttribArrayARB( GLuint index )
{
    do_vertex_attrib_enable( index, GL_TRUE );
}


void __indirect_glDisableVertexAttribArrayARB( GLuint index )
{
    do_vertex_attrib_enable( index, GL_FALSE );
}


static void
get_parameter( unsigned opcode, unsigned size, GLenum target, GLuint index,
	       void * params )
{
    __GLXcontext * const gc = __glXGetCurrentContext();
    Display * const dpy = gc->currentDpy;
    const GLuint cmdlen = 12;

    if (__builtin_expect(dpy != NULL, 1)) {
        GLubyte const * pc = __glXSetupVendorRequest(gc,
						     X_GLXVendorPrivateWithReply,
						     opcode, cmdlen);

	*((GLenum *)(pc +  0)) = target;
	*((GLuint *)(pc +  4)) = index;
	*((GLuint *)(pc +  8)) = 0;

        (void) __glXReadReply(dpy, size, params, GL_FALSE);
        UnlockDisplay(dpy); SyncHandle();
    }
    return;
}


void __indirect_glGetProgramEnvParameterfvARB( GLenum target, GLuint index,
					       GLfloat * params )
{
    get_parameter( 1296, 4, target, index, params );
}


void __indirect_glGetProgramEnvParameterdvARB( GLenum target, GLuint index,
					       GLdouble * params )
{
    get_parameter( 1297, 8, target, index, params );
}


void __indirect_glGetProgramLocalParameterfvARB( GLenum target, GLuint index,
						 GLfloat * params )
{
    get_parameter( 1305, 4, target, index, params );
}


void __indirect_glGetProgramLocalParameterdvARB( GLenum target, GLuint index,
						 GLdouble * params )
{
    get_parameter( 1306, 8, target, index, params );
}


void __indirect_glGetVertexAttribPointervNV( GLuint index, GLenum pname,
					     GLvoid ** pointer )
{
    __GLXcontext * const gc = __glXGetCurrentContext();
    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
 
    if ( pname != GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB ) {
	__glXSetError( gc, GL_INVALID_ENUM );
    }
    
    if ( ! __glXGetArrayPointer( state, GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB,
				 index, pointer ) ) {
	__glXSetError( gc, GL_INVALID_VALUE );
    }
}


/**
 * Get the selected attribute from the vertex array state vector.
 * 
 * \returns
 * On success \c GL_TRUE is returned.  Otherwise, \c GL_FALSE is returned.
 */
static GLboolean
get_attrib_array_data( __GLXattribute * state, GLuint index, GLenum cap,
		       GLintptr * data )
{
    GLboolean retval = GL_FALSE;
    const GLenum attrib = GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB;

    switch( cap ) {
    case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB:
	retval = __glXGetArrayEnable( state, attrib, index, data );
	break;

    case GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB:
	retval = __glXGetArraySize( state, attrib, index, data );
	break;

    case GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB:
	retval = __glXGetArrayStride( state, attrib, index, data );
	break;

    case GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB:
	retval = __glXGetArrayType( state, attrib, index, data );
	break;

    case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB:
	retval = __glXGetArrayNormalized( state, attrib, index, data );
	break;
    }

    
    return retval;
}


static void get_vertex_attrib( __GLXcontext * gc, unsigned vop,
			       GLuint index, GLenum pname,
			       xReply * reply )
{
    Display * const dpy = gc->currentDpy;
    GLubyte * const pc = __glXSetupVendorRequest(gc,
						 X_GLXVendorPrivateWithReply,
						 vop, 8);
						     
    *((uint32_t *)(pc +  0)) = index;
    *((uint32_t *)(pc +  4)) = pname;

    (void) _XReply( dpy, reply, 0, False );
}


void __indirect_glGetVertexAttribivARB( GLuint index, GLenum pname,
					GLint * params )
{
    __GLXcontext * const gc = __glXGetCurrentContext();
    Display * const dpy = gc->currentDpy;
    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
    xGLXSingleReply reply;


    get_vertex_attrib( gc, 1303, index, pname, (xReply *) & reply );

    if ( reply.size != 0 ) {
	GLintptr data;


	if ( get_attrib_array_data( state, index, pname, & data ) ) {
	    *params = (GLint) data;
	}
	else {
	    if (reply.size == 1) {
		*params = (GLint) reply.pad3;
	    } 
	    else {
		_XRead(dpy, (void *) params, 4 * reply.size);
	    }
	}
    }

    UnlockDisplay(dpy);
    SyncHandle();
}


void __indirect_glGetVertexAttribfvARB( GLuint index, GLenum pname,
					GLfloat * params )
{
    __GLXcontext * const gc = __glXGetCurrentContext();
    Display * const dpy = gc->currentDpy;
    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
    xGLXSingleReply reply;


    get_vertex_attrib( gc, 1302, index, pname, (xReply *) & reply );

    if ( reply.size != 0 ) {
	GLintptr data;


	if ( get_attrib_array_data( state, index, pname, & data ) ) {
	    *params = (GLfloat) data;
	}
	else {
	    if (reply.size == 1) {
		(void) memcpy( params, & reply.pad3, sizeof( GLfloat ) );
	    } 
	    else {
		_XRead(dpy, (void *) params, 4 * reply.size);
	    }
	}
    }

    UnlockDisplay(dpy);
    SyncHandle();
}


void __indirect_glGetVertexAttribdvARB( GLuint index, GLenum pname,
					GLdouble * params )
{
    __GLXcontext * const gc = __glXGetCurrentContext();
    Display * const dpy = gc->currentDpy;
    __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
    xGLXSingleReply reply;


    get_vertex_attrib( gc, 1301, index, pname, (xReply *) & reply );

    if ( reply.size != 0 ) {
	GLintptr data;


	if ( get_attrib_array_data( state, index, pname, & data ) ) {
	    *params = (GLdouble) data;
	}
	else {
	    if (reply.size == 1) {
		(void) memcpy( params, & reply.pad3, sizeof( GLdouble ) );
	    } 
	    else {
		_XRead(dpy, (void *) params, 8 * reply.size);
	    }
	}
    }

    UnlockDisplay(dpy);
    SyncHandle();
}
