Initial commit
[profile/ivi/simulator-opengl.git] / es_2_0 / Program.c
1 /* 
2  * Copyright (C) 2010 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
3  * 
4  * Contact:
5  * DongKyun Yun <dk77.yun@samsung.com>
6  * SangJin Kim <sangjin3.kim@samsung.com>
7  * HyunGoo Kang <hyungoo1.kang@samsung.com>
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy of
10  * this software and associated documentation files (the "Software"), to deal in
11  * the Software without restriction, including without limitation the rights to
12  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
13  * of the Software, and to permit persons to whom the Software is furnished to do
14  * so, subject to the following conditions:
15  * 
16  * The above copyright notice and this permission notice shall be included in all
17  * copies or substantial portions of the Software.
18  * 
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  * 
27  * Contributors:
28  * - S-Core Co., Ltd
29  *
30  */
31
32 #include "es2front.h"
33 #include <stdarg.h>
34
35
36 void GL_APIENTRY ES2INTER(ProgramObjectInit)(struct ProgramObjectUnit* pUnit) {
37         pUnit->bLinkStatus = GL_FALSE;
38         pUnit->strInfoLog = NULL;
39 }
40
41 void GL_APIENTRY ES2INTER(ProgramObjectRelease)(struct ProgramObjectUnit* pUnit) {
42         register int i;
43         if (pUnit->strInfoLog != NULL) {
44                 free(pUnit->strInfoLog);
45         }
46         pUnit->bLinkStatus = GL_FALSE;
47         pUnit->strInfoLog = NULL;
48 }
49
50 void GL_APIENTRY ES2INTER(ProgramObjectInfoLogReset)(struct ProgramObjectUnit* pUnit) {
51         pUnit->strInfoLog = realloc(pUnit->strInfoLog, 1024 * sizeof(GLchar));
52         assert(pUnit->strInfoLog != NULL);
53         pUnit->strInfoLog[0] = '\0';
54 }
55
56 void GL_APIENTRY ES2INTER(ProgramObjectInfoLogAppend)(struct ProgramObjectUnit* pUnit,
57         const char* format, ...) {
58         static char cBuf[1024];
59         int len;
60         va_list ap;
61         va_start(ap, format);
62         vsnprintf(cBuf, 1024, format, ap);
63         if (pUnit->strInfoLog == NULL) {
64                 pUnit->strInfoLog = realloc(pUnit->strInfoLog, 1024 * sizeof(GLchar));
65                 assert(pUnit->strInfoLog != NULL);
66                 pUnit->strInfoLog[0] = '\0';
67         }
68         len = strlen(pUnit->strInfoLog) + strlen(cBuf);
69         pUnit->strInfoLog = realloc(pUnit->strInfoLog, (len + 1) * sizeof(GLchar));
70         assert(pUnit->strInfoLog != NULL);
71         strcat(pUnit->strInfoLog, cBuf);
72         va_end(ap);
73 }
74
75 GLuint GL_APIENTRY ES2ENTRY(CreateProgram)(void) {
76         register GLuint uResult;
77         register GLint nAllocated;
78         register int i;
79         uResult = FNPTR(CreateProgram)();
80         nAllocated = CCV(nProgramObjectAllocated);
81         while (nAllocated <= uResult) {
82                 nAllocated *= 2;
83         }
84         if (CCV(nProgramObjectAllocated) < nAllocated) { 
85                 register struct ProgramObjectUnit* pUnit = realloc(CCV(pProgramObject),
86                                                 nAllocated * sizeof(struct ProgramObjectUnit));
87                 assert(pUnit != NULL);
88                 for (i = CCV(nProgramObjectAllocated); i < nAllocated; i++) {
89                         ES2INTER(ProgramObjectInit)(&(pUnit[i]));
90                 }
91                 CCV(pProgramObject) = pUnit;
92                 CCV(nProgramObjectAllocated) = nAllocated;
93         }
94         return uResult;
95 }
96
97 void GL_APIENTRY ES2ENTRY(DeleteProgram)(GLuint program) {
98         if (program == 0) {
99                 return; 
100         } else if (FNPTR(IsProgram) != NULL && FNPTR(IsProgram)(program) == GL_FALSE) {
101                 ES2INTER(SetError)(GL_INVALID_VALUE);
102                 return;
103         }
104         if (CCV(nProgramObjectAllocated) == NULL) {
105                 ES2INTER(SetError)(GL_INVALID_VALUE);
106                 return;
107         }
108
109         if (program < CCV(nProgramObjectAllocated)) {
110                 GLint nAttachedShaders = 0;
111                 FNPTR(GetProgramiv)(program, GL_ATTACHED_SHADERS, &nAttachedShaders);
112                 if (nAttachedShaders > 0) {
113                         GLuint* pAttachedShaders = NULL;
114                         int i;
115                         pAttachedShaders = (GLuint*)realloc(pAttachedShaders,
116                                 nAttachedShaders * sizeof(GLuint));
117                         assert(pAttachedShaders != NULL);
118                         FNPTR(GetAttachedShaders)(program, nAttachedShaders, &i, pAttachedShaders);
119                         assert(nAttachedShaders == i);
120                         for (i = 0; i < nAttachedShaders; i++) {
121                                 int index = pAttachedShaders[i];
122                                 if (index < CCV(nShaderObjectAllocated)) {
123                                         struct ShaderObjectUnit* pShader = &(CCV(pShaderObject)[index]);
124                                         if (pShader->nAttached > 0) pShader->nAttached--;
125                                         if (pShader->bDeleteStatus == GL_TRUE && pShader->nAttached == 0) {
126                                                 ES2INTER(ShaderObjectRelease)(pShader);
127                                         }
128                                 }
129                         }
130                 }
131                 ES2INTER(ProgramObjectRelease)(&(CCV(pProgramObject)[program]));
132         }
133         FNPTR(DeleteProgram)(program);
134 }
135
136 GLboolean GL_APIENTRY ES2ENTRY(IsProgram)(GLuint program) {
137         register GLboolean bResult;
138         bResult = FNPTR(IsProgram)(program);
139         return bResult;
140 }
141
142 void GL_APIENTRY ES2ENTRY(AttachShader)(GLuint program, GLuint shader) {
143         struct ShaderObjectUnit* pShader;
144         if ((GLint)(program) <= 0) {
145                 ES2INTER(SetError)(GL_INVALID_VALUE);
146                 return;
147         } else if (FNPTR(IsProgram)(program) == GL_FALSE) {
148                 if (program == 30) {
149                         ES2INTER(SetError)(GL_INVALID_VALUE);
150                 } else {
151                         ES2INTER(SetError)(GL_INVALID_OPERATION);
152                 }
153                 return;
154         }
155         if ((GLint)(shader) <= 0) {
156                 ES2INTER(SetError)(GL_INVALID_VALUE);
157                 return;
158         } else if (FNPTR(IsShader)(shader) == GL_FALSE) {
159                 ES2INTER(SetError)(GL_INVALID_OPERATION);
160                 return;
161         }
162         FNPTR(AttachShader)(program, shader);
163         pShader = &(CCV(pShaderObject)[shader]);
164         pShader->nAttached++;
165 }
166
167 void GL_APIENTRY ES2ENTRY(DetachShader)(GLuint program, GLuint shader) {
168         struct ShaderObjectUnit* pShader;
169         if ((GLint)(program) <= 0) {
170                 ES2INTER(SetError)(GL_INVALID_VALUE);
171                 return;
172         } else if (FNPTR(IsProgram) != NULL && FNPTR(IsProgram)(program) == GL_FALSE) {
173                 ES2INTER(SetError)(GL_INVALID_OPERATION);
174                 return;
175         }
176         if ((GLint)(shader) <= 0) {
177                 ES2INTER(SetError)(GL_INVALID_VALUE);
178                 return;
179         } else if (FNPTR(IsShader) != NULL && FNPTR(IsShader)(shader) == GL_FALSE) {
180                 ES2INTER(SetError)(GL_INVALID_OPERATION);
181                 return;
182         }
183         if (FNPTR(DetachShader) != NULL)
184                 FNPTR(DetachShader)(program, shader);
185         if (CCV(pShaderObject) != NULL) {
186                 pShader = &(CCV(pShaderObject)[shader]);
187                 if (pShader->nAttached > 0) 
188                         pShader->nAttached--;
189                 if (pShader->nAttached == 0 && pShader->bDeleteStatus == GL_TRUE)
190                         ES2INTER(ShaderObjectRelease)(pShader);
191         }
192 }
193
194 void GL_APIENTRY ES2ENTRY(GetAttachedShaders)(GLuint program,
195         GLsizei maxcount, GLsizei* count, GLuint* shaders) {
196         if ((GLint)(program) <= 0) {
197                 ES2INTER(SetError)(GL_INVALID_VALUE);
198                 return;
199         } else if (FNPTR(IsProgram)(program) == GL_FALSE) {
200                 ES2INTER(SetError)(GL_INVALID_OPERATION);
201                 return;
202         }
203         if (maxcount < 0) {
204                 ES2INTER(SetError)(GL_INVALID_VALUE);
205                 return;
206         }
207         FNPTR(GetAttachedShaders)(program, maxcount, count, shaders);
208 }
209
210 void GL_APIENTRY ES2ENTRY(LinkProgram)(GLuint program) {
211         struct ProgramObjectUnit* pUnit;
212         int nAttachedShaders;
213         int iResult;
214         GLboolean bFlag;
215         int nVertexShader = 0;
216         int nFragmentShader = 0;
217         if ((GLint)(program) <= 0) {
218                 ES2INTER(SetError)(GL_INVALID_VALUE);
219                 return;
220         } else if (FNPTR(IsProgram)(program) == GL_FALSE) {
221                 ES2INTER(SetError)(GL_INVALID_OPERATION);
222                 return;
223         }
224         FNPTR(GetProgramiv)(program, GL_ATTACHED_SHADERS, &nAttachedShaders);
225         bFlag = GL_TRUE;
226         assert(program < CCV(nProgramObjectAllocated));
227         pUnit = &(CCV(pProgramObject)[program]);
228         ES2INTER(ProgramObjectInfoLogReset)(pUnit);
229         if (nAttachedShaders > 0) {
230                 GLuint* pAttachedShaders = NULL;
231                 int i;
232                 pAttachedShaders = (GLuint*)realloc(pAttachedShaders, nAttachedShaders * sizeof(GLuint));
233                 assert(pAttachedShaders != NULL);
234                 FNPTR(GetAttachedShaders)(program, nAttachedShaders, &i, pAttachedShaders);
235                 assert(nAttachedShaders == i);
236                 for (i = 0; i < nAttachedShaders; i++) {
237                         int index = pAttachedShaders[i];
238                         if (index < CCV(nShaderObjectAllocated)) {
239                                 struct ShaderObjectUnit* pShader = &(CCV(pShaderObject)[index]);
240                                 if (pShader->eShaderType == GL_VERTEX_SHADER) {
241                                         nVertexShader++; 
242                                 } else if (pShader->eShaderType == GL_FRAGMENT_SHADER) {
243                                         nFragmentShader++;
244                                 }
245                                 if (pShader->bCompileStatus == GL_FALSE) {
246                                         bFlag = GL_FALSE;
247                                         ES2INTER(ProgramObjectInfoLogAppend)(pUnit,
248                                                 "ERROR: shader=%d was not compiled or failed to compile\n", index);
249                                 }
250                         }
251                 }
252         }
253         if (nVertexShader == 0) {
254                 ES2INTER(ProgramObjectInfoLogAppend)(pUnit, "ERROR: no vertex shader found\n");
255                 bFlag = GL_FALSE;
256         }
257         if (nFragmentShader == 0) {
258                 ES2INTER(ProgramObjectInfoLogAppend)(pUnit, "ERROR: no fragment shader found\n");
259                 bFlag = GL_FALSE;
260         }
261         if (bFlag == GL_FALSE) {
262                 CCV(pProgramObject)[program].bLinkStatus = GL_FALSE;
263                 ES2INTER(ProgramObjectInfoLogAppend)(pUnit, "ERROR: link failed\n");
264                 return;
265         }
266         FNPTR(LinkProgram)(program);
267         FNPTR(GetProgramiv)(program, GL_LINK_STATUS, &iResult);
268         pUnit->bLinkStatus = (iResult == GL_FALSE) ? GL_FALSE : GL_TRUE;
269 }
270
271 void GL_APIENTRY ES2ENTRY(UseProgram)(GLuint program) {
272         if ((GLint)(program) < 0) {
273                 ES2INTER(SetError)(GL_INVALID_VALUE);
274         } else if (program != 0 && FNPTR(IsProgram)(program) == GL_FALSE) {
275                 ES2INTER(SetError)(GL_INVALID_OPERATION);
276                 return;
277         }
278         FNPTR(UseProgram)(program);
279 }
280
281 void GL_APIENTRY ES2ENTRY(ValidateProgram)(GLuint program) {
282         struct ProgramObjectUnit* pUnit;
283         GLint valid;
284         if ((GLint)(program) <= 0) {
285                 ES2INTER(SetError)(GL_INVALID_VALUE);
286                 return;
287         } else if (FNPTR(IsProgram)(program) == GL_FALSE) {
288                 ES2INTER(SetError)(GL_INVALID_OPERATION);
289                 return;
290         }
291         pUnit = &(CCV(pProgramObject)[program]);
292         ES2INTER(ProgramObjectInfoLogReset)(pUnit);
293         FNPTR(ValidateProgram)(program);
294         FNPTR(GetProgramiv)(program, GL_VALIDATE_STATUS, &valid);
295         if (valid != GL_FALSE) {
296                 ES2ENTRY(LinkProgram)(program);
297         }
298 }
299
300 void GL_APIENTRY ES2ENTRY(GetProgramiv)(GLuint program, GLenum pname, GLint* params) {
301         if ((GLint)(program) <= 0) {
302                 ES2INTER(SetError)(GL_INVALID_VALUE);
303                 return;
304         } else if (FNPTR(IsProgram)(program) == GL_FALSE) {
305                 ES2INTER(SetError)(GL_INVALID_OPERATION);
306                 return;
307         }
308         switch (pname) {
309         default:
310                 ES2INTER(SetError)(GL_INVALID_ENUM);
311                 return;
312         case GL_LINK_STATUS:
313                 if (program < CCV(nProgramObjectAllocated)) {
314                         *params = CCV(pProgramObject)[program].bLinkStatus;
315                 } else {
316                         FNPTR(GetProgramiv)(program, pname, params);
317                 }
318                 break;
319         case GL_DELETE_STATUS:
320                 FNPTR(GetProgramiv)(program, pname, params);
321                 break;
322         case GL_VALIDATE_STATUS:
323                 FNPTR(GetProgramiv)(program, pname, params);
324                 if (*params != GL_FALSE) {
325                         if (program < CCV(nProgramObjectAllocated)) {
326                                 *params = CCV(pProgramObject)[program].bLinkStatus;
327                         } else {
328                                 FNPTR(GetProgramiv)(program, GL_LINK_STATUS, params);
329                         }
330                 }
331                 break;
332         case GL_INFO_LOG_LENGTH:
333                 if (program < CCV(nProgramObjectAllocated)
334                         && CCV(pProgramObject)[program].strInfoLog != NULL) {
335                         *params = strlen(CCV(pProgramObject)[program].strInfoLog) + 1;
336                         if (*params <= 1) {
337                                 FNPTR(GetProgramiv)(program, pname, params);
338                         }
339                 } else {
340                         FNPTR(GetProgramiv)(program, pname, params);
341                 }
342                 break;
343         case GL_ATTACHED_SHADERS:
344         case GL_ACTIVE_ATTRIBUTES:
345         case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
346         case GL_ACTIVE_UNIFORMS:
347         case GL_ACTIVE_UNIFORM_MAX_LENGTH:
348                 FNPTR(GetProgramiv)(program, pname, params);
349                 break;
350         }
351 }
352
353 void GL_APIENTRY ES2ENTRY(GetProgramInfoLog)(GLuint program,
354         GLsizei bufsize, GLsizei* length, char* infolog) {
355         struct ProgramObjectUnit* pUnit;
356         if ((GLint)(program) <= 0) {
357                 ES2INTER(SetError)(GL_INVALID_VALUE);
358                 return;
359         } else if (FNPTR(IsProgram)(program) == GL_FALSE) {
360                 ES2INTER(SetError)(GL_INVALID_OPERATION);
361                 return;
362         }
363         if (bufsize < 0) {
364                 ES2INTER(SetError)(GL_INVALID_VALUE);
365                 return;
366         }
367         assert(program < CCV(nProgramObjectAllocated));
368         pUnit = &CCV(pProgramObject[program]);
369         if (pUnit->strInfoLog != NULL) {
370                 int len = strlen(pUnit->strInfoLog);
371                 if (len >= bufsize) {
372                         len = bufsize - 1;
373                 }
374                 if (len > 0) {
375                         if (length != NULL) {
376                                 *length = len;
377                         }
378                         if (infolog != NULL) {
379                                 strncpy(infolog, pUnit->strInfoLog, len);
380                                 infolog[len] = '\0';
381                         }
382                 } else {
383                         FNPTR(GetProgramInfoLog)(program, bufsize, length, infolog);
384                 }
385         } else {
386                 FNPTR(GetProgramInfoLog)(program, bufsize, length, infolog);
387         }
388 }
389