~thomas-voss/glmark2/build-for-mir

« back to all changes in this revision

Viewing changes to src/libmatrix/program.cc

  • Committer: Bazaar Package Importer
  • Author(s): Jani Monoses
  • Date: 2011-08-05 00:05:19 UTC
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20110805000519-zit4dpe1wwzhnbg0
Tags: upstream-2011.07
ImportĀ upstreamĀ versionĀ 2011.07

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// Copyright (c) 2011 Linaro Limited
 
3
//
 
4
// All rights reserved. This program and the accompanying materials
 
5
// are made available under the terms of the MIT License which accompanies
 
6
// this distribution, and is available at
 
7
// http://www.opensource.org/licenses/mit-license.php
 
8
//
 
9
// Contributors:
 
10
//     Jesse Barker - original implementation.
 
11
//
 
12
#include <string>
 
13
#include <vector>
 
14
#include <sstream>
 
15
#include <fstream>
 
16
#include <iostream>
 
17
 
 
18
#include "gl-headers.h"
 
19
#include "program.h"
 
20
 
 
21
using std::string;
 
22
using LibMatrix::mat4;
 
23
using LibMatrix::vec2;
 
24
using LibMatrix::vec3;
 
25
using LibMatrix::vec4;
 
26
 
 
27
bool
 
28
gotSource(const string& filename, string& source)
 
29
{
 
30
    using std::ifstream;
 
31
    ifstream inputFile(filename.c_str());
 
32
    if (!inputFile)
 
33
    {
 
34
        std::cerr << "Failed to open \"" << filename << "\"" << std::endl;
 
35
        return false;
 
36
    }
 
37
 
 
38
    string curLine;
 
39
    while (getline(inputFile, curLine))
 
40
    {
 
41
        source += curLine;
 
42
        source += '\n';
 
43
    }
 
44
 
 
45
    return true;
 
46
}
 
47
 
 
48
Shader::Shader(unsigned int type, const string& source) :
 
49
    handle_(0),
 
50
    type_(type),
 
51
    source_(source),
 
52
    ready_(false),
 
53
    valid_(false)
 
54
{
 
55
    // Create our shader and setup the source code.
 
56
    handle_ = glCreateShader(type);
 
57
    if (!handle_)
 
58
    {
 
59
        message_ = string("Failed to create the new shader.");
 
60
        return;
 
61
    }
 
62
    const GLchar* shaderSource = source_.c_str();
 
63
    glShaderSource(handle_, 1, &shaderSource, NULL);
 
64
    GLint param = 0;
 
65
    glGetShaderiv(handle_, GL_SHADER_SOURCE_LENGTH, &param);
 
66
    if (static_cast<unsigned int>(param) != source_.length() + 1)
 
67
    {
 
68
        std::ostringstream o(string("Expected shader source length "));
 
69
        o << source_.length() << ", but got " << param << std::endl;
 
70
        message_ = o.str();
 
71
        return;
 
72
    }
 
73
    valid_ = true;
 
74
}
 
75
 
 
76
Shader::~Shader()
 
77
{
 
78
    handle_ = 0;
 
79
    type_ = 0;
 
80
    ready_ = false;
 
81
    valid_ = false;
 
82
}
 
83
 
 
84
void
 
85
Shader::compile()
 
86
{
 
87
    // Make sure we have a good shader and haven't already compiled it.
 
88
    if (!valid_ || ready_)
 
89
    {
 
90
        return;
 
91
    }
 
92
    glCompileShader(handle_);
 
93
    GLint param = 0;
 
94
    glGetShaderiv(handle_, GL_COMPILE_STATUS, &param);
 
95
    if (param == GL_FALSE)
 
96
    {
 
97
        glGetShaderiv(handle_, GL_INFO_LOG_LENGTH, &param);
 
98
        GLchar* infoLog = new GLchar[param + 1];
 
99
        glGetShaderInfoLog(handle_, param + 1, NULL, infoLog);
 
100
        message_ = infoLog;
 
101
        delete [] infoLog;
 
102
        return;
 
103
    }
 
104
    ready_ = true;
 
105
}
 
106
 
 
107
void
 
108
Shader::attach(unsigned int program)
 
109
{
 
110
    // Shader must be valid and compiled to be attached to a program.
 
111
    if (!valid_ || !ready_)
 
112
    {
 
113
        return;
 
114
    }
 
115
    glAttachShader(program, handle_);
 
116
}
 
117
 
 
118
void
 
119
Shader::release()
 
120
{
 
121
    if (handle_)
 
122
    {
 
123
        glDeleteShader(handle_);
 
124
    }
 
125
    handle_ = 0;
 
126
    type_ = 0;
 
127
    ready_ = false;
 
128
    valid_ = false;
 
129
}
 
130
 
 
131
Program::Program() :
 
132
    handle_(0),
 
133
    ready_(false),
 
134
    valid_(false)
 
135
{
 
136
}
 
137
 
 
138
Program::~Program()
 
139
{
 
140
    // First release all of the shader resources attached to us and clean up
 
141
    // our handle.
 
142
    release();
 
143
}
 
144
 
 
145
void
 
146
Program::init()
 
147
{
 
148
    handle_ = glCreateProgram();
 
149
    if (!handle_)
 
150
    {
 
151
        message_ = string("Failed to create the new program");
 
152
        return;
 
153
    }
 
154
 
 
155
    valid_ = true;
 
156
}
 
157
 
 
158
void
 
159
Program::release()
 
160
{
 
161
    // First delete all of the shader resources attached to us.
 
162
    for (std::vector<Shader>::iterator shaderIt = shaders_.begin(); shaderIt != shaders_.end(); shaderIt++)
 
163
    {
 
164
        shaderIt->release();
 
165
    }
 
166
 
 
167
    // Clear out the shader vector so we're ready to reuse it.
 
168
    shaders_.clear();
 
169
 
 
170
    // Clear out the error string to make sure we don't return anything stale.
 
171
    message_.clear();
 
172
 
 
173
    if (handle_)
 
174
    {
 
175
        glDeleteProgram(handle_);
 
176
    }
 
177
    handle_ = 0;
 
178
    ready_ = false;
 
179
    valid_ = false;
 
180
}
 
181
void
 
182
Program::addShader(unsigned int type, const string& source)
 
183
{
 
184
    if (!valid_)
 
185
    {
 
186
        return;
 
187
    }
 
188
 
 
189
    Shader shader(type, source);
 
190
    if (!shader.valid())
 
191
    {
 
192
        message_ = shader.errorMessage();
 
193
        valid_ = false;
 
194
        return;
 
195
    }
 
196
 
 
197
    shader.compile();
 
198
 
 
199
    if (!shader.ready())
 
200
    {
 
201
        message_ = shader.errorMessage();
 
202
        valid_ = false;
 
203
        return;
 
204
    }
 
205
 
 
206
    shader.attach(handle_);
 
207
    shaders_.push_back(shader);
 
208
    return;
 
209
}
 
210
 
 
211
void
 
212
Program::build()
 
213
{
 
214
    if (!valid_ || ready_)
 
215
    {
 
216
        return;
 
217
    }
 
218
 
 
219
    if (shaders_.empty())
 
220
    {
 
221
        message_ = string("There are no shaders attached to this program");
 
222
        return;
 
223
    }
 
224
 
 
225
    glLinkProgram(handle_);
 
226
    GLint param = 1;
 
227
    glGetProgramiv(handle_, GL_LINK_STATUS, &param);
 
228
    if (param == GL_FALSE)
 
229
    {
 
230
        glGetProgramiv(handle_, GL_INFO_LOG_LENGTH, &param);
 
231
        GLchar* infoLog = new GLchar[param + 1];
 
232
        glGetProgramInfoLog(handle_, param + 1, NULL, infoLog);
 
233
        message_ = infoLog;
 
234
        delete [] infoLog;
 
235
        return;
 
236
    }
 
237
    ready_ = true;
 
238
}
 
239
 
 
240
void
 
241
Program::start()
 
242
{
 
243
    if (!valid_ || !ready_)
 
244
    {
 
245
        return;
 
246
    }
 
247
    glUseProgram(handle_);
 
248
}
 
249
 
 
250
void
 
251
Program::stop()
 
252
{
 
253
    glUseProgram(0);
 
254
}
 
255
 
 
256
void
 
257
Program::loadUniformMatrix(const mat4& m, const string& name)
 
258
{
 
259
    ready_ = false;
 
260
    GLint location = glGetUniformLocation(handle_, name.c_str());
 
261
    if (location < 0)
 
262
    {
 
263
        message_ = string("Failed to get uniform location for \"") + name +
 
264
            string("\"");
 
265
        return;
 
266
    }
 
267
 
 
268
    // Our matrix representation is column-major, so transpose is false here.
 
269
    glUniformMatrix4fv(location, 1, GL_FALSE, m);
 
270
    ready_ = true;
 
271
}
 
272
 
 
273
void
 
274
Program::loadUniformVector(const vec2& v, const string& name)
 
275
{
 
276
    ready_ = false;
 
277
    GLint location = glGetUniformLocation(handle_, name.c_str());
 
278
    if (location < 0)
 
279
    {
 
280
        message_ = string("Failed to get uniform location for \"") + name +
 
281
            string("\"");
 
282
        return;
 
283
    }
 
284
 
 
285
    glUniform2fv(location, 1, v);
 
286
    ready_ = true;
 
287
}
 
288
 
 
289
void
 
290
Program::loadUniformVector(const vec3& v, const string& name)
 
291
{
 
292
    ready_ = false;
 
293
    GLint location = glGetUniformLocation(handle_, name.c_str());
 
294
    if (location < 0)
 
295
    {
 
296
        message_ = string("Failed to get uniform location for \"") + name +
 
297
            string("\"");
 
298
        return;
 
299
    }
 
300
 
 
301
    glUniform3fv(location, 1, v);
 
302
    ready_ = true;
 
303
}
 
304
 
 
305
void
 
306
Program::loadUniformVector(const vec4& v, const string& name)
 
307
{
 
308
    ready_ = false;
 
309
    GLint location = glGetUniformLocation(handle_, name.c_str());
 
310
    if (location < 0)
 
311
    {
 
312
        message_ = string("Failed to get uniform location for \"") + name +
 
313
            string("\"");
 
314
        return;
 
315
    }
 
316
 
 
317
    glUniform4fv(location, 1, v);
 
318
    ready_ = true;
 
319
}
 
320
 
 
321
void
 
322
Program::loadUniformScalar(const float& f, const string& name)
 
323
{
 
324
    ready_ = false;
 
325
    GLint location = glGetUniformLocation(handle_, name.c_str());
 
326
    if (location < 0)
 
327
    {
 
328
        message_ = string("Failed to get uniform location for \"") + name +
 
329
            string("\"");
 
330
        return;
 
331
    }
 
332
 
 
333
    glUniform1f(location, f);
 
334
    ready_ = true;
 
335
}
 
336
 
 
337
void
 
338
Program::loadUniformScalar(const int& i, const string& name)
 
339
{
 
340
    ready_ = false;
 
341
    GLint location = glGetUniformLocation(handle_, name.c_str());
 
342
    if (location < 0)
 
343
    {
 
344
        message_ = string("Failed to get uniform location for \"") + name +
 
345
            string("\"");
 
346
        return;
 
347
    }
 
348
 
 
349
    glUniform1i(location, i);
 
350
    ready_ = true;
 
351
}
 
352
 
 
353
int
 
354
Program::getAttribIndex(const string& name)
 
355
{
 
356
    GLint index = glGetAttribLocation(handle_, name.c_str());
 
357
    if (index < 0)
 
358
    {
 
359
        message_ = string("Failed to get attribute location for \"") + name +
 
360
            string("\"");
 
361
    }
 
362
    return index;
 
363
}