1 /*
2      File: shader_util.c
3  Abstract: Functions that compile, link and validate shader programs.
4   Version: 1.13
5 
6  Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
7  Inc. ("Apple") in consideration of your agreement to the following
8  terms, and your use, installation, modification or redistribution of
9  this Apple software constitutes acceptance of these terms.  If you do
10  not agree with these terms, please do not use, install, modify or
11  redistribute this Apple software.
12 
13  In consideration of your agreement to abide by the following terms, and
14  subject to these terms, Apple grants you a personal, non-exclusive
15  license, under Apple's copyrights in this original Apple software (the
16  "Apple Software"), to use, reproduce, modify and redistribute the Apple
17  Software, with or without modifications, in source and/or binary forms;
18  provided that if you redistribute the Apple Software in its entirety and
19  without modifications, you must retain this notice and the following
20  text and disclaimers in all such redistributions of the Apple Software.
21  Neither the name, trademarks, service marks or logos of Apple Inc. may
22  be used to endorse or promote products derived from the Apple Software
23  without specific prior written permission from Apple.  Except as
24  expressly stated in this notice, no other rights or licenses, express or
25  implied, are granted by Apple herein, including but not limited to any
26  patent rights that may be infringed by your derivative works or by other
27  works in which the Apple Software may be incorporated.
28 
29  The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
30  MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
31  THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
32  FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
33  OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
34 
35  IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
36  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38  INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
39  MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
40  AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
41  STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
42  POSSIBILITY OF SUCH DAMAGE.
43 
44  Copyright (C) 2014 Apple Inc. All Rights Reserved.
45 
46  Original file modified by Belledonne Communications, Grenoble, France
47  Copyright (C) 2017
48 */
49 
50 #include <stdlib.h>
51 #include <stdio.h>
52 #include <string.h>
53 #include <sys/stat.h>
54 
55 #include "shader_util.h"
56 #include "opengl_debug.h"
57 
58 #define LogInfo printf
59 #define LogError printf
60 
61 /* Compile a shader from the provided source(s) */
glueCompileShader(const OpenGlFunctions * f,GLenum target,GLsizei count,const GLchar * sources,GLuint * shader)62 GLint glueCompileShader (const OpenGlFunctions *f, GLenum target, GLsizei count, const GLchar *sources, GLuint *shader) {
63   GLint logLength, status;
64 
65   *shader = f->glCreateShader(target);
66   f->glShaderSource(*shader, count, &sources, NULL);
67   f->glCompileShader(*shader);
68 
69   f->glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
70   if (logLength > 0) {
71     GLchar *log = (GLchar *)malloc(logLength);
72     f->glGetShaderInfoLog(*shader, logLength, &logLength, log);
73     LogInfo("Shader compile log:\n%s", log);
74     free(log);
75   }
76 
77   f->glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
78   if (status == 0) {
79     int i;
80 
81     LogError("Failed to compile shader:\n");
82     for (i = 0; i < count; i++)
83       LogInfo("%s", &sources[i]);
84   }
85 
86   glError(f);
87 
88   return status;
89 }
90 
91 /* Link a program with all currently attached shaders */
glueLinkProgram(const OpenGlFunctions * f,GLuint program)92 GLint glueLinkProgram (const OpenGlFunctions *f, GLuint program) {
93   GLint logLength, status;
94 
95   f->glLinkProgram(program);
96   f->glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
97   if (logLength > 0) {
98     GLchar *log = (GLchar *)malloc(logLength);
99     f->glGetProgramInfoLog(program, logLength, &logLength, log);
100     LogInfo("Program link log:\n%s", log);
101     free(log);
102   }
103 
104   f->glGetProgramiv(program, GL_LINK_STATUS, &status);
105   if (status == 0)
106     LogError("Failed to link program %d", program);
107 
108   glError(f);
109 
110   return status;
111 }
112 
113 /* Validate a program (for i.e. inconsistent samplers) */
glueValidateProgram(const OpenGlFunctions * f,GLuint program)114 GLint glueValidateProgram (const OpenGlFunctions *f, GLuint program) {
115   GLint logLength, status;
116 
117   f->glValidateProgram(program);
118   f->glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
119   if (logLength > 0) {
120     GLchar *log = (GLchar *)malloc(logLength);
121     f->glGetProgramInfoLog(program, logLength, &logLength, log);
122     LogInfo("Program validate log:\n%s", log);
123     free(log);
124   }
125 
126   f->glGetProgramiv(program, GL_VALIDATE_STATUS, &status);
127   if (status == 0)
128     LogError("Failed to validate program %d", program);
129 
130   glError(f);
131 
132   return status;
133 }
134 
135 /* Return named uniform location after linking */
glueGetUniformLocation(const OpenGlFunctions * f,GLuint program,const GLchar * uniformName)136 GLint glueGetUniformLocation (const OpenGlFunctions *f, GLuint program, const GLchar *uniformName) {
137   return f->glGetUniformLocation(program, uniformName);
138 }
139 
140 /* Convenience wrapper that compiles, links, enumerates uniforms and attribs */
glueCreateProgram(const OpenGlFunctions * f,const GLchar * vertSource,const GLchar * fragSource,GLsizei attribNameCt,const GLchar ** attribNames,const GLint * attribLocations,GLsizei uniformNameCt,const GLchar ** uniformNames,GLint * uniformLocations,GLuint * program)141 GLint glueCreateProgram (
142   const OpenGlFunctions *f,
143   const GLchar *vertSource,
144   const GLchar *fragSource,
145   GLsizei attribNameCt,
146   const GLchar **attribNames,
147   const GLint *attribLocations,
148   GLsizei uniformNameCt,
149   const GLchar **uniformNames,
150   GLint *uniformLocations,
151   GLuint *program
152 ) {
153   GLuint vertShader = 0, fragShader = 0, prog = 0, status = 1;
154   GLint i;
155 
156   prog = f->glCreateProgram();
157 
158   status *= glueCompileShader(f, GL_VERTEX_SHADER, 1, vertSource, &vertShader);
159   status *= glueCompileShader(f, GL_FRAGMENT_SHADER, 1, fragSource, &fragShader);
160   f->glAttachShader(prog, vertShader);
161   f->glAttachShader(prog, fragShader);
162 
163   for (i = 0; i < attribNameCt; i++) {
164     if (strlen(attribNames[i]))
165       f->glBindAttribLocation(prog, attribLocations[i], attribNames[i]);
166   }
167 
168   status *= glueLinkProgram(f, prog);
169   status *= glueValidateProgram(f, prog);
170 
171   if (status) {
172     for (i = 0; i < uniformNameCt; i++) {
173       if (strlen(uniformNames[i]))
174         uniformLocations[i] = glueGetUniformLocation(f, prog, uniformNames[i]);
175     }
176 
177     *program = prog;
178   }
179 
180   if (vertShader)
181     f->glDeleteShader(vertShader);
182   if (fragShader)
183     f->glDeleteShader(fragShader);
184 
185   glError(f);
186 
187   return status;
188 }
189