use tksdl;
use tkopengl;


function query_active_uniforms(int program) {
   // Query uniforms in "program"

   int numUniforms = zglGetProgrami(program, GL_ACTIVE_UNIFORMS);
   trace "[...] query_active_uniforms: #uniforms = "+numUniforms;
   int idx = 0;
   loop(numUniforms)
   {
      String name;
      Integer size;

      Integer type = zglGetActiveUniform(program, idx, size, name);

      String typeName = TKS.constantToString(type, "GL_");

      trace "[...] uniform["+idx+"]:\n\t\tname = \""+name+"\"\n\t\ttype = "+typeName+" ("+type.printf("0x%04x")+")\n\t\tsize = "+size;

      idx++;
   }
}

// (note) strange source layout (multiple "" is due to emacs syntax highlighting..)
String vert_src = "
void main()
{
   gl_Position = ftransform();
}
";

String frag_src = "
#version 130
// (note) v1.30 is required for the texture() function

uniform bool  my_bool;
uniform bvec2 my_bool_vec2;
uniform bvec3 my_bool_vec3;
uniform bvec4 my_bool_vec4;
uniform int   my_int;
uniform ivec2 my_int_vec2;
uniform ivec3 my_int_vec3;
uniform ivec4 my_int_vec4;
uniform float my_float;
uniform vec2  my_float_vec2;
uniform vec3  my_float_vec3;
uniform vec4  my_float_vec4;
uniform mat2  my_float_mat2;
uniform mat3  my_float_mat3;
uniform mat4  my_float_mat4;
uniform float my_float_array[5];
uniform sampler1D       my_sampler1D;
uniform sampler2D       my_sampler2D;
uniform sampler3D       my_sampler3D;
uniform samplerCube     my_samplerCube;
uniform sampler1DShadow my_sampler1DShadow;
uniform sampler2DShadow my_sampler2DShadow;

out vec4 fragColor;

void main()
{
   // Some dummy code to prevent the shader compiler from removing the uniforms due to optimization
   vec2 v2 = my_float_mat2 * vec2(1,1);
   vec3 v3 = my_float_mat3 * vec3(1,1,1);
   vec4 v4 = my_float_mat4 * vec4(1,1,1,1);
   int i = my_int + my_int_vec2.x + my_int_vec3.y + my_int_vec4.z + int(my_bool) + int(my_bool_vec2.x) + int(my_bool_vec3.y) + int(my_bool_vec4.z);
   float f = my_float + my_float_vec2.x + my_float_vec3.y + my_float_vec4.z + v2.x + v3.y + v4.z;
   int k;
   // (note) my_float_array is reported as \"my_float_array[0]\" with size 5
   for(k=0; k<5; k++) f+= my_float_array[k];
   v4 = texture(my_sampler1D, f) + texture(my_sampler2D, v2) + texture(my_sampler3D, v3) + texture(my_samplerCube, v3) + texture(my_sampler1DShadow, v3) + texture(my_sampler2DShadow, v3) ;
   fragColor = v4 + vec4(1, float(i), 1, my_float);
}
";

int program;
int vert;
int frag;


function onReopen() {
   String log;

   program = glCreateProgram();

   vert = glCreateShader(GL_VERTEX_SHADER);
   zglShaderSource(vert, vert_src);
   glCompileShader(vert);
   glGetShaderInfoLog(vert, log);
   trace "[...] vertex shader log=\""+log+"\".";
   glAttachShader(program, vert);

   frag = glCreateShader(GL_FRAGMENT_SHADER);
   zglShaderSource(frag, frag_src);
   glCompileShader(frag);
   glGetShaderInfoLog(frag, log);
   trace "[...] fragment shader log=\""+log+"\".";
   glAttachShader(program, frag);

   glBindFragDataLocation(program, 0, "fragColor");

   glLinkProgram(program);

   glGetProgramInfoLog(program, log);
   trace "[...] program log=\""+log+"\".";

   glUseProgram(program);
   query_active_uniforms(program);
}

function main() {
   Viewport.openWindow(64, 48);
   Viewport.enableGLError = true;

   trace "[...]                   GL_VENDOR = \"" + glGetString(GL_VENDOR) + "\"";
   trace "[...]                  GL_VERSION = \"" + glGetString(GL_VERSION) + "\"";
   trace "[...] GL_SHADING_LANGUAGE_VERSION = \"" + glGetString(GL_SHADING_LANGUAGE_VERSION) + "\"";

   use callbacks;

   Configuration.debugLevel = 1;

   zglLoadExtensions();

   onReopen();

   // no event loop, immediately close window again and exit
}