| /* |
| * Copyright 2022 Rive |
| */ |
| |
| #include "gl_utils.hpp" |
| |
| #include <stdio.h> |
| #include <sstream> |
| #include <vector> |
| |
| #include "../out/obj/generated/glsl.glsl.hpp" |
| |
| namespace glutils |
| { |
| void CompileAndAttachShader(GLuint program, |
| GLuint type, |
| const char* source, |
| const GLExtensions& extensions, |
| const char* versionString) |
| { |
| CompileAndAttachShader(program, type, nullptr, 0, &source, 1, extensions, versionString); |
| } |
| |
| void CompileAndAttachShader(GLuint program, |
| GLuint type, |
| const char* defines[], |
| size_t numDefines, |
| const char* inputSources[], |
| size_t numInputSources, |
| const GLExtensions& extensions, |
| const char* versionString) |
| { |
| GLuint shader = CompileShader(type, |
| defines, |
| numDefines, |
| inputSources, |
| numInputSources, |
| extensions, |
| versionString); |
| glAttachShader(program, shader); |
| glDeleteShader(shader); |
| } |
| |
| GLuint CompileShader(GLuint type, |
| const char* source, |
| const GLExtensions& extensions, |
| const char* versionString) |
| { |
| return CompileShader(type, nullptr, 0, &source, 1, extensions, versionString); |
| } |
| |
| GLuint CompileShader(GLuint type, |
| const char* defines[], |
| size_t numDefines, |
| const char* inputSources[], |
| size_t numInputSources, |
| const GLExtensions& extensions, |
| const char* versionString) |
| { |
| std::vector<const char*> sources; |
| sources.push_back(versionString ? versionString : "#version 300 es\n"); |
| if (type == GL_VERTEX_SHADER) |
| { |
| sources.push_back("#define " GLSL_VERTEX "\n"); |
| } |
| else if (GL_FRAGMENT_SHADER) |
| { |
| sources.push_back("#define " GLSL_FRAGMENT "\n"); |
| } |
| if (type == GL_VERTEX_SHADER && !extensions.ANGLE_base_vertex_base_instance_shader_builtin) |
| { |
| sources.push_back("#define " GLSL_ENABLE_BASE_INSTANCE_POLYFILL "\n"); |
| } |
| std::ostringstream definesStream; |
| for (size_t i = 0; i < numDefines; ++i) |
| { |
| definesStream << "#define " << defines[i] << "\n"; |
| } |
| std::string definesString; |
| if (numDefines > 0) |
| { |
| definesString = definesStream.str(); |
| sources.push_back(definesString.c_str()); |
| } |
| sources.push_back(rive::pls::glsl::glsl); |
| for (size_t i = 0; i < numInputSources; ++i) |
| { |
| sources.push_back(inputSources[i]); |
| } |
| GLuint shader = glCreateShader(type); |
| glShaderSource(shader, sources.size(), sources.data(), nullptr); |
| glCompileShader(shader); |
| GLint isCompiled = 0; |
| glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled); |
| if (isCompiled == GL_FALSE) |
| { |
| GLint maxLength = 0; |
| glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength); |
| std::vector<GLchar> infoLog(maxLength); |
| glGetShaderInfoLog(shader, maxLength, &maxLength, &infoLog[0]); |
| fprintf(stderr, "Failed to compile shader\n"); |
| int l = 1; |
| for (const char* s : sources) |
| { |
| std::stringstream stream(s); |
| std::string lineStr; |
| while (std::getline(stream, lineStr, '\n')) |
| { |
| fprintf(stderr, "%4i| %s\n", l++, lineStr.c_str()); |
| } |
| } |
| fprintf(stderr, "%s\n", &infoLog[0]); |
| fflush(stderr); |
| glDeleteShader(shader); |
| exit(-1); |
| } |
| return shader; |
| } |
| |
| void LinkProgram(GLuint program) |
| { |
| glLinkProgram(program); |
| GLint isLinked = 0; |
| glGetProgramiv(program, GL_LINK_STATUS, &isLinked); |
| if (isLinked == GL_FALSE) |
| { |
| GLint maxLength = 0; |
| glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength); |
| std::vector<GLchar> infoLog(maxLength); |
| glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]); |
| fprintf(stderr, "Failed to link program %s\n", &infoLog[0]); |
| fflush(stderr); |
| exit(-1); |
| } |
| } |
| } // namespace glutils |