Home | History | Annotate | Download | only in app
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 #include "shader.h"
     17 
     18 #include <stdio.h>
     19 #include <memory>
     20 
     21 
     22 // Given shader source, load and compile it
     23 static GLuint loadShader(GLenum type, const char *shaderSrc, const char *name) {
     24     // Create the shader object
     25     GLuint shader = glCreateShader (type);
     26     if (shader == 0) {
     27         return 0;
     28     }
     29 
     30     // Load and compile the shader
     31     glShaderSource(shader, 1, &shaderSrc, nullptr);
     32     glCompileShader(shader);
     33 
     34     // Verify the compilation worked as expected
     35     GLint compiled = 0;
     36     glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
     37     if (!compiled) {
     38         printf("Error compiling %s shader for %s\n", (type==GL_VERTEX_SHADER) ? "vtx":"pxl", name);
     39 
     40         GLint size = 0;
     41         glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
     42         if (size > 0)
     43         {
     44             // Get and report the error message
     45             std::unique_ptr<char> infoLog(new char[size]);
     46             glGetShaderInfoLog(shader, size, NULL, infoLog.get());
     47             printf("  msg:\n%s\n", infoLog.get());
     48         }
     49 
     50         glDeleteShader(shader);
     51         return 0;
     52     }
     53 
     54     return shader;
     55 }
     56 
     57 
     58 // Create a program object given vertex and pixels shader source
     59 GLuint buildShaderProgram(const char* vtxSrc, const char* pxlSrc, const char* name) {
     60     GLuint program = glCreateProgram();
     61     if (program == 0) {
     62         printf("Failed to allocate program object\n");
     63         return 0;
     64     }
     65 
     66     // Compile the shaders and bind them to this program
     67     GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vtxSrc, name);
     68     if (vertexShader == 0) {
     69         printf("Failed to load vertex shader\n");
     70         glDeleteProgram(program);
     71         return 0;
     72     }
     73     GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pxlSrc, name);
     74     if (pixelShader == 0) {
     75         printf("Failed to load pixel shader\n");
     76         glDeleteProgram(program);
     77         glDeleteShader(vertexShader);
     78         return 0;
     79     }
     80     glAttachShader(program, vertexShader);
     81     glAttachShader(program, pixelShader);
     82 
     83     // Link the program
     84     glLinkProgram(program);
     85     GLint linked = 0;
     86     glGetProgramiv(program, GL_LINK_STATUS, &linked);
     87     if (!linked)
     88     {
     89         printf("Error linking program.\n");
     90         GLint size = 0;
     91         glGetProgramiv(program, GL_INFO_LOG_LENGTH, &size);
     92         if (size > 0)
     93         {
     94             // Get and report the error message
     95             std::unique_ptr<char> infoLog(new char[size]);
     96             glGetProgramInfoLog(program, size, NULL, infoLog.get());
     97             printf("  msg:  %s\n", infoLog.get());
     98         }
     99 
    100         glDeleteProgram(program);
    101         glDeleteShader(vertexShader);
    102         glDeleteShader(pixelShader);
    103         return 0;
    104     }
    105 
    106 
    107 #if 0 // Debug output to diagnose shader parameters
    108     GLint numShaderParams;
    109     GLchar paramName[128];
    110     GLint paramSize;
    111     GLenum paramType;
    112     const char *typeName = "?";
    113     printf("Shader parameters for %s:\n", name);
    114     glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numShaderParams);
    115     for (GLint i=0; i<numShaderParams; i++) {
    116         glGetActiveUniform(program,
    117                            i,
    118                            sizeof(paramName),
    119                            nullptr,
    120                            &paramSize,
    121                            &paramType,
    122                            paramName);
    123         switch (paramType) {
    124             case GL_FLOAT:      typeName = "GL_FLOAT"; break;
    125             case GL_FLOAT_VEC4: typeName = "GL_FLOAT_VEC4"; break;
    126             case GL_FLOAT_MAT4: typeName = "GL_FLOAT_MAT4"; break;
    127             case GL_SAMPLER_2D: typeName = "GL_SAMPLER_2D"; break;
    128         }
    129 
    130         printf("  %2d: %s\t (%d) of type %s(%d)\n", i, paramName, paramSize, typeName, paramType);
    131     }
    132 #endif
    133 
    134 
    135     return program;
    136 }
    137