summaryrefslogtreecommitdiffstats
path: root/native_client_sdk/src/examples/tumbler/shader_util.cc
blob: 2bbfc84aedc4f4a41df60d36bca3aeac5d76a9b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// Copyright (c) 2011 The Native Client Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "examples/tumbler/shader_util.h"

#include <stdlib.h>
#include <stdio.h>

namespace shader_util {

GLuint CreateShaderOfType(GLenum type, const char *shader_src) {
  GLuint shader;
  GLint compiled;

  // Create the shader object
  shader = glCreateShader(type);

  if (shader == 0)
    return 0;

  // Load and compile the shader source
  glShaderSource(shader, 1, &shader_src, NULL);
  glCompileShader(shader);

  // Check the compile status
  glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
  if (compiled == 0) {
    GLint info_len = 0;
    glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len);
    if (info_len > 1) {
      char* info_log = reinterpret_cast<char*>(malloc(sizeof(char) * info_len));
      glGetShaderInfoLog(shader, info_len, NULL, info_log);
      // TODO(dspringer): We could really use a logging API.
      printf("Error compiling shader:\n%s\n", info_log);
      free(info_log);
    }
    glDeleteShader(shader);
    return 0;
  }

  return shader;
}

GLuint CreateProgramFromVertexAndFragmentShaders(
    const char *vertex_shader_src, const char *fragment_shader_src) {
  GLuint vertex_shader;
  GLuint fragment_shader;
  GLuint program_object;
  GLint linked;

  // Load the vertex/fragment shaders
  vertex_shader = CreateShaderOfType(GL_VERTEX_SHADER, vertex_shader_src);
  if (vertex_shader == 0)
    return 0;
  fragment_shader = CreateShaderOfType(GL_FRAGMENT_SHADER, fragment_shader_src);
  if (fragment_shader == 0) {
    glDeleteShader(vertex_shader);
    return 0;
  }

  // Create the program object and attach the shaders.
  program_object = glCreateProgram();
  if (program_object == 0)
    return 0;
  glAttachShader(program_object, vertex_shader);
  glAttachShader(program_object, fragment_shader);

  // Link the program
  glLinkProgram(program_object);

  // Check the link status
  glGetProgramiv(program_object, GL_LINK_STATUS, &linked);
  if (linked == 0) {
    GLint info_len = 0;
    glGetProgramiv(program_object, GL_INFO_LOG_LENGTH, &info_len);
    if (info_len > 1) {
      char* info_log = reinterpret_cast<char*>(malloc(info_len));
      glGetProgramInfoLog(program_object, info_len, NULL, info_log);
      // TODO(dspringer): We could really use a logging API.
      printf("Error linking program:\n%s\n", info_log);
      free(info_log);
    }
    glDeleteProgram(program_object);
    return 0;
  }

  // Delete these here because they are attached to the program object.
  glDeleteShader(vertex_shader);
  glDeleteShader(fragment_shader);

  return program_object;
}

}  // namespace shader_util