void State::useProgram(ProgramPtr prog) { if (prog) glRun(glUseProgram(prog->id())); else glRun(glUseProgram(0)); m_data.back().m_prog = prog; }
void State::pop() { glRun(glPopClientAttrib()); glRun(glPopAttrib()); if (m_data.size() <= 1) { Log::error("State push/pop mismatch"); } else { m_data.pop_back(); } }
unsigned int State::pickingQuery() { /// @todo is static so great idea? not static unsigned int s_picking_query = 0; if (s_picking_query == 0) { glRun(glGenQueries(1, &s_picking_query)); } return s_picking_query; }
AttributeVar::List GLProgram::getAttributeList() { glCheck("GLProgram::getAttributeList"); AttributeVar::List list; GLint num = 0, buffer_size = 0; glRun(glGetProgramiv(m_prog, GL_ACTIVE_ATTRIBUTES, &num)); glRun(glGetProgramiv(m_prog, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &buffer_size)); std::vector<GLchar> name(buffer_size); for (GLint i = 0; i < num; i++) { GLsizei length; GLint size; GLenum type; glRun(glGetActiveAttrib(m_prog, i, buffer_size, &length, &size, &type, name.data())); list.push_back(AttributeVar(shared_from_this(), name.data(), type)); } return list; }
bool GLProgram::removeShader(ShaderPtr shader) { if (!m_shaders.contains(shader)) return false; disconnect(shader.get(), SIGNAL(changed(ShaderPtr)), this, SIGNAL(shaderChanged(ShaderPtr))); m_shaders.remove(shader); if (m_prog) glRun(glDetachShader(m_prog, shader->id())); shader->setProgram(ProgramPtr()); m_compiled = false; m_relink = true; emit changed(); return true; }
Shader::CompileStatus Shader::compile(ShaderErrorList& errors) { glCheck("Shader::compile"); if (m_needCompile) { m_needCompile = false; if (!m_shader) { m_shader = glRun2(glCreateShader(m_type)); if (!m_shader) { Log::error("Shader: could not create shader"); return ERRORS; } } QByteArray src_ = m_src.toUtf8(); #ifndef _WIN32 if (s_sandbox_compile && !SandboxCompiler::check(shared_from_this(), src_, errors)) { return ERRORS; } #endif const char* src = src_.data(); GLint len = src_.length(); glRun(glShaderSource(m_shader, 1, &src, &len)); glRun(glCompileShader(m_shader)); GLint ok = 0; glRun(glGetShaderiv(m_shader, GL_COMPILE_STATUS, &ok)); glRun(glGetShaderiv(m_shader, GL_INFO_LOG_LENGTH, &len)); int error_count = errors.size(); // len may include the zero byte if (len > 1 && !handleCompilerOutput(errors)) { Log::error("Failed to parse GLSL compiler output"); } error_count = errors.size() - error_count; return ok ? error_count ? WARNINGS : OK : ERRORS; } else { return NONE; } }
void GLProgram::link(State* state) { glCheck("GLProgram::link"); m_relink = false; GLint prog = 0; glRun(glGetIntegerv(GL_CURRENT_PROGRAM, &prog)); if (isLinked()) { glRun(glUseProgram(m_prog)); /// @todo Do we need this? m_uniformList = getUniformList(); } ShaderErrorList errors(state ? state->material() : MaterialPtr(), name()); if (!m_transformFeedback.isEmpty()) { const char* names[10]; int m = std::min(m_transformFeedback.size(), 10); for (int i = 0; i < m; ++i) { names[i] = m_transformFeedback[i].data(); } glRun(glTransformFeedbackVaryings(m_prog, m, names, GL_SEPARATE_ATTRIBS)); } glRun(glLinkProgram(m_prog)); GLint ok = 0; glRun(glGetProgramiv(m_prog, GL_LINK_STATUS, &ok)); GLint len = 0; glRun(glGetProgramiv(m_prog, GL_INFO_LOG_LENGTH, &len)); // len may include the zero byte if (len > 1) { std::vector<GLchar> log(len); GLsizei size = len; glRun(glGetProgramInfoLog(m_prog, size, &size, &log[0])); ShaderCompilerOutputParser::instance().parse(QString::fromUtf8(&log[0], size), errors); } if (ok) { glRun(glUseProgram(m_prog)); /// @todo Do we need this? setUniform(m_uniformList); } emit linked(errors); glRun(glUseProgram(prog)); }
bool GLProgram::isLinked() { glCheck("GLProgram::isLinked"); if (!m_prog) return false; /// for example i915_program_error: Exceeded max instructions etc can be /// checked with this if (!glRun2(glIsProgram(m_prog))) return false; GLint b = 0; glRun(glGetProgramiv(m_prog, GL_LINK_STATUS, &b)); return b; }
UniformVar::List GLProgram::getUniformList() { glCheck("GLProgram::getUniformList"); UniformVar::List list; GLint num = 0, buffer_size = 0; glRun(glGetProgramiv(m_prog, GL_ACTIVE_UNIFORMS, &num)); glRun(glGetProgramiv(m_prog, GL_ACTIVE_UNIFORM_MAX_LENGTH, &buffer_size)); std::vector<GLchar> name(buffer_size); for (GLint i = 0; i < num; i++) { GLsizei length; GLint size; GLenum type; glRun(glGetActiveUniform(m_prog, i, buffer_size, &length, &size, &type, &name[0])); // For now skip build-in uniforms, since those can't be changed the same way as others. if (strncmp(&name[0], "gl_", 3) != 0) list.push_back(UniformVar(shared_from_this(), &name[0], type)); } return list; }
bool Shader::getBuiltinMacro(QString name, float& out) { /// @todo use cleaned up version of the actual shader here QString src = "#version 150\n" "out float x;\n" "void main() {\n" " x = %1;\n" "}\n"; QueryShader& s = QueryShader::instance(); bool ok = false; if (s.compile(Vertex, src.arg(name)) && s.bind("x")) { glRun(glDrawArrays(GL_POINTS, 0, 1)); ok = s.unbind(out); } return ok; }
bool QueryShader::compile(Shader::Type type, QString src) { if (!m_shader) { /// @todo handle different sets of shaders depending on the type m_shader = glRun2(glCreateShader(type)); if (!m_shader) { Log::error("QueryShader: could not create shader object"); return false; } } if (!m_prog) { m_prog = glRun2(glCreateProgram()); if (!m_prog) { Log::error("QueryShader: could not create program object"); return false; } } QByteArray bytes = src.toAscii(); const char* data = bytes.data(); GLint len = bytes.length(); glRun(glShaderSource(m_shader, 1, &data, &len)); glRun(glCompileShader(m_shader)); GLint ok = 0; glRun(glGetShaderiv(m_shader, GL_COMPILE_STATUS, &ok)); if (!ok) { glRun(glGetShaderiv(m_shader, GL_INFO_LOG_LENGTH, &len)); std::vector<GLchar> log(len); glRun(glGetShaderInfoLog(m_shader, len, &len, &log[0])); Log::error("Compile log: %s", &log[0]); return false; } if (!m_attached) glRun(glAttachShader(m_prog, m_shader)); m_attached = true; return true; }
bool QueryShader::bind(const char* name) { GLint ok = 0; glRun(glTransformFeedbackVaryings(m_prog, 1, &name, GL_SEPARATE_ATTRIBS)); glRun(glLinkProgram(m_prog)); glRun(glGetProgramiv(m_prog, GL_LINK_STATUS, &ok)); if (!ok) { GLint len = 0; glRun(glGetProgramiv(m_prog, GL_INFO_LOG_LENGTH, &len)); std::vector<GLchar> log(len); GLsizei size = len; glRun(glGetProgramInfoLog(m_prog, size, &size, &log[0])); Log::error("Link log: %s", &log[0]); return false; } glRun(glUseProgram(m_prog)); m_feedback.begin(GL_POINTS, 1); return true; }
bool QueryShader::unbind(float& out) { bool ok = m_feedback.end(&out, 1); glRun(glUseProgram(0)); return ok; }