title: Meaning of "index" parameter in glEnableVertexAttribArray and (possibly) a bug in the OS X OpenGL implementation
body: <p>1) Do I understand correctly that to draw using vertex arrays or VBOs I need for all my attributes to either call glBindAttribLocation before the shader program linkage or call glGetAttribLocation after the shader program was successfully linked and then use the bound/obtained index in the glVertexAttribPointer and glEnableVertexAttribArray calls?</p>
  
  <p>To be more specific: these three functions - glGetAttribLocation, glVertexAttribPointer and glEnableVertexAttribArray - they all have an input parameter named "index". Is it the same "index" for all the three? And is it the same thing as the one returned by glGetAttribLocation?</p>
  
  <p>If yes:
  2) I've been facing a problem on OS X, I described it here: <a href="https://stackoverflow.com/questions/28093919/using-default-attribute-location-doesnt-work-on-osx-osx-opengl-bug">https://stackoverflow.com/questions/28093919/using-default-attribute-location-doesnt-work-on-osx-osx-opengl-bug</a> , but unfortunately didn't get any replies.</p>
  
  <p>The problem is that depending on what attribute locations I bind to my attributes I do or do not see anything on the screen. I only see this behavior on my MacBook Pro with OS X 10.9.5; I've tried running the same code on Linux and Windows and it seems to work on those platforms independently from which locations are my attributes bound to.</p>
  
  <p>Here is a code example (which is supposed to draw a red triangle on the screen) that exhibits the problem:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;GLFW/glfw3.h&gt;
  
  GLuint global_program_object;
  GLint  global_position_location;
  GLint  global_aspect_ratio_location;
  GLuint global_buffer_names[1];
  
  int LoadShader(GLenum type, const char *shader_source)
    {
    GLuint shader;
    GLint compiled;
    shader = glCreateShader(type);
    if (shader == 0)
      return 0;
    glShaderSource(shader, 1, &amp;shader_source, NULL);
    glCompileShader(shader);
    glGetShaderiv(shader, GL_COMPILE_STATUS, &amp;compiled);
    if (!compiled)
      {
      GLint info_len = 0;
      glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &amp;info_len);
      if (info_len &gt; 1)
        {
        char* info_log = new char[info_len];
        glGetShaderInfoLog(shader, info_len, NULL, info_log);
        std::cout &lt;&lt; "Error compiling shader" &lt;&lt;  info_log &lt;&lt; std::endl;
        delete info_log;
        }
      glDeleteShader(shader);
      return 0; 
      }
    return shader; 
    }
  
  int InitGL()
    {
    char vertex_shader_source[] =
      "attribute vec4  att_position;                       \n"
      "attribute float dummy;\n"
      "uniform   float uni_aspect_ratio;                   \n"
      "void main()                                         \n"
      "  {                                                 \n"
      "  vec4 test = att_position * dummy;\n"
      "  mat4 mat_projection =                             \n"
      "   mat4(1.0 / uni_aspect_ratio, 0.0,  0.0, 0.0,     \n"
      "                           0.0, 1.0,  0.0, 0.0,     \n"
      "                           0.0, 0.0, -1.0, 0.0,     \n"
      "                           0.0, 0.0,  0.0, 1.0);    \n"
      "  gl_Position = att_position;                       \n"
      "  gl_Position *= mat_projection;                    \n"
      "  }                                                 \n";
  
    char fragment_shader_source[] =
      "void main()                                \n"
      "  {                                        \n"
      "  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n"
      "  }                                        \n";
  
    GLuint vertex_shader;
    GLuint fragment_shader;
    GLuint program_object;
    GLint  linked;
  
    vertex_shader   = LoadShader(GL_VERTEX_SHADER  , vertex_shader_source  );
    fragment_shader = LoadShader(GL_FRAGMENT_SHADER, fragment_shader_source);
  
    program_object = glCreateProgram();
    if(program_object == 0)
      return 1;
    glAttachShader(program_object, vertex_shader  );
    glAttachShader(program_object, fragment_shader);
  
    // Here any index except 0 results in observing the black screen
    glBindAttribLocation(program_object, 1, "att_position");
    glLinkProgram(program_object);
    glGetProgramiv(program_object, GL_LINK_STATUS, &amp;linked);
    if(!linked)
      {
      GLint info_len = 0;
      glGetProgramiv(program_object, GL_INFO_LOG_LENGTH, &amp;info_len);
      if(info_len &gt; 1)
        {
        char* info_log = new char[info_len];
        glGetProgramInfoLog(program_object, info_len, NULL, info_log);
        std::cout &lt;&lt; "Error linking program" &lt;&lt;  info_log &lt;&lt; std::endl;
        delete info_log; 
        }
      glDeleteProgram(program_object);
      return 1;
      }
    global_program_object = program_object;
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glUseProgram(global_program_object);
    global_position_location     = glGetAttribLocation (global_program_object, "att_position");
    global_aspect_ratio_location = glGetUniformLocation(global_program_object, "uni_aspect_ratio");
  
    GLfloat vertices[] = {-0.5f, -0.5f, 0.0f,
                           0.5f, -0.5f, 0.0f,
                           0.0f,  0.5f, 0.0f};
  
    glGenBuffers(1, global_buffer_names);
    glBindBuffer(GL_ARRAY_BUFFER, global_buffer_names[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 9, vertices, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    return 0;
    }
  
  void Render()
    {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    glUseProgram(global_program_object);
    glBindBuffer(GL_ARRAY_BUFFER, global_buffer_names[0]);
    glVertexAttribPointer(global_position_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(global_position_location);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glDisableVertexAttribArray(global_position_location);
    glUseProgram(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
  
  void FreeGL()
    {
    glDeleteBuffers(1, global_buffer_names);
    glDeleteProgram(global_program_object);
    }
  
  void SetViewport(int width, int height)
    {
    glViewport(0, 0, width, height);
    glUseProgram(global_program_object);
    glUniform1f(global_aspect_ratio_location, static_cast&lt;GLfloat&gt;(width) / static_cast&lt;GLfloat&gt;(height));
    }
  
  
  int main(void)
    {
    GLFWwindow* window;
    if (!glfwInit())
      return -1;
    window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
    if (!window)
      {
      glfwTerminate();
      return -1;
      }
    glfwMakeContextCurrent(window);
    InitGL();
  
    // Double the resolution to correctly draw with Retina display
    SetViewport(1280, 960);
    while (!glfwWindowShouldClose(window))
      {
      Render();
      glfwSwapBuffers(window);
      glfwPollEvents();
      }
    FreeGL();
    glfwTerminate();
    return 0;
    }
  </code></pre>
  
  <p>Does this look like a bug to you? Can anyone reproduce it? If it's a bug where should I report it?</p>
  
  <p>P.S.
  I've also tried SDL instead of GLFW, the behavior is the same...</p>