
#include "TinyGL/gl_zgl.h"
#include <assert.h>
#include <string.h>

/*  WINGDIAPI GLint APIENTRY glRenderMode (GLenum mode);  */

GLint glRenderMode( GLenum mode ){
	GLContext *c      = gl_get_context();
	int        result = 0;
  
	switch( c->render_mode ){
	case GL_RENDER:
		break;
	case GL_SELECT:
		if( c->select_overflow ){
			result = -c->select_hits;
		}else{
			result = c->select_hits;
		}
		c->select_overflow  =0;
		c->select_ptr      = c->select_buffer;
		c->name_stack_size = 0;
		break;
	default:
		assert( 0 );
	}

	switch( mode ){
	case GL_RENDER:
		c->render_mode = GL_RENDER;
		break;
	case GL_SELECT:
		c->render_mode = GL_SELECT;
		assert( c->select_buffer != NULL );
		c->select_ptr      = c->select_buffer;
		c->select_hits     = 0;
		c->select_overflow = 0;
		c->select_hit      = NULL;
		break;
	default:
		assert( 0 );
	}
	return result;
}

void glSelectBuffer(int size,unsigned int *buf){
  GLContext *c=gl_get_context();

  assert(c->render_mode != GL_SELECT);
  
  c->select_buffer=buf;
  c->select_size=size;
}


void glopInitNames( GLContext *c,GLParam *p ){
  if (c->render_mode == GL_SELECT) {
    c->name_stack_size=0;
    c->select_hit=NULL;
  }
}

void glopPushName( GLContext *c,GLParam *p ){
  if (c->render_mode == GL_SELECT) {
    assert(c->name_stack_size<MAX_NAME_STACK_DEPTH);
    c->name_stack[c->name_stack_size++]=p[1].i;
    c->select_hit=NULL;
  }
}

void glopPopName( GLContext *c,GLParam *p ){
  if (c->render_mode == GL_SELECT) {
    assert(c->name_stack_size>0);
    c->name_stack_size--;
    c->select_hit=NULL;
  }
}

void glopLoadName( GLContext *c,GLParam *p ){
  if (c->render_mode == GL_SELECT) {
   assert(c->name_stack_size>0);
   c->name_stack[c->name_stack_size-1]=p[1].i;
   c->select_hit=NULL;
  }
}

void gl_add_select( GLContext *c, unsigned int zmin, unsigned int zmax ){
  unsigned int *ptr;
  int n,i;

  if (!c->select_overflow) {
    if (c->select_hit==NULL) {
      n=c->name_stack_size;
      if ((c->select_ptr-c->select_buffer+3+n) > 
	  c->select_size) {
	c->select_overflow=1;
      } else {
	ptr=c->select_ptr;
	c->select_hit=ptr;
	*ptr++=c->name_stack_size;
	*ptr++=zmin;
	*ptr++=zmax;
	for(i=0;i<n;i++) *ptr++=c->name_stack[i];
	c->select_ptr=ptr;
	c->select_hits++;
      }
    } else {
      if (zmin<c->select_hit[1]) c->select_hit[1]=zmin;
      if (zmax>c->select_hit[2]) c->select_hit[2]=zmax;
    }
  }
}

