1 // license:BSD-3-Clause
2 // copyright-holders:Sven Gothel
3 /***
4  *
5  * GL Shader Tool - Convenient Basic Shader functionality
6  *
7  * Copyright (c) 2007, Sven Gothel
8  *
9  * OpenGL GLSL ARB extensions:
10  *
11  *  GL_ARB_shader_objects
12  *  GL_ARB_shading_language_100
13  *  GL_ARB_vertex_shader
14  *  GL_ARB_fragment_shader
15  *
16  */
17 
18 #include "emu.h"
19 #include "gl_shader_tool.h"
20 
21 PFNGLGETOBJECTPARAMETERIVARBPROC pfn_glGetObjectParameterivARB= nullptr;
22 PFNGLGETINFOLOGARBPROC pfn_glGetInfoLogARB= nullptr;
23 PFNGLDELETEOBJECTARBPROC pfn_glDeleteObjectARB= nullptr;
24 PFNGLCREATESHADEROBJECTARBPROC pfn_glCreateShaderObjectARB= nullptr;
25 PFNGLSHADERSOURCEARBPROC pfn_glShaderSourceARB= nullptr;
26 PFNGLCOMPILESHADERARBPROC pfn_glCompileShaderARB= nullptr;
27 PFNGLCREATEPROGRAMOBJECTARBPROC pfn_glCreateProgramObjectARB= nullptr;
28 PFNGLATTACHOBJECTARBPROC pfn_glAttachObjectARB= nullptr;
29 PFNGLLINKPROGRAMARBPROC pfn_glLinkProgramARB= nullptr;
30 PFNGLVALIDATEPROGRAMARBPROC pfn_glValidateProgramARB= nullptr;
31 PFNGLUSEPROGRAMOBJECTARBPROC pfn_glUseProgramObjectARB= nullptr;
32 PFNGLGETUNIFORMLOCATIONARBPROC pfn_glGetUniformLocationARB= nullptr;
33 PFNGLUNIFORM1FARBPROC pfn_glUniform1fARB= nullptr;
34 PFNGLUNIFORM1IARBPROC pfn_glUniform1iARB= nullptr;
35 PFNGLUNIFORM1FVARBPROC pfn_glUniform1fvARB= nullptr;
36 PFNGLUNIFORM2FVARBPROC pfn_glUniform2fvARB= nullptr;
37 PFNGLUNIFORM3FVARBPROC pfn_glUniform3fvARB= nullptr;
38 PFNGLUNIFORM4FVARBPROC pfn_glUniform4fvARB= nullptr;
39 PFNGLUNIFORM1IVARBPROC pfn_glUniform1ivARB= nullptr;
40 PFNGLUNIFORM2IVARBPROC pfn_glUniform2ivARB= nullptr;
41 PFNGLUNIFORM3IVARBPROC pfn_glUniform3ivARB= nullptr;
42 PFNGLUNIFORM4IVARBPROC pfn_glUniform4ivARB= nullptr;
43 
44 
gl_shader_loadExtention(osd_gl_context * gl_ctx)45 int gl_shader_loadExtention(osd_gl_context *gl_ctx)
46 {
47 	pfn_glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) gl_ctx->getProcAddress("glGetObjectParameterivARB");
48 	pfn_glGetInfoLogARB           = (PFNGLGETINFOLOGARBPROC) gl_ctx->getProcAddress ("glGetInfoLogARB");
49 	pfn_glDeleteObjectARB         = (PFNGLDELETEOBJECTARBPROC) gl_ctx->getProcAddress ("glDeleteObjectARB");
50 	pfn_glCreateShaderObjectARB   = (PFNGLCREATESHADEROBJECTARBPROC) gl_ctx->getProcAddress ("glCreateShaderObjectARB");
51 	pfn_glShaderSourceARB         = (PFNGLSHADERSOURCEARBPROC) gl_ctx->getProcAddress ("glShaderSourceARB");
52 	pfn_glCompileShaderARB        = (PFNGLCOMPILESHADERARBPROC) gl_ctx->getProcAddress ("glCompileShaderARB");
53 	pfn_glCreateProgramObjectARB  = (PFNGLCREATEPROGRAMOBJECTARBPROC) gl_ctx->getProcAddress ("glCreateProgramObjectARB");
54 	pfn_glAttachObjectARB         = (PFNGLATTACHOBJECTARBPROC) gl_ctx->getProcAddress ("glAttachObjectARB");
55 	pfn_glLinkProgramARB          = (PFNGLLINKPROGRAMARBPROC) gl_ctx->getProcAddress ("glLinkProgramARB");
56 	pfn_glValidateProgramARB      = (PFNGLVALIDATEPROGRAMARBPROC) gl_ctx->getProcAddress ("glValidateProgramARB");
57 	pfn_glUseProgramObjectARB     = (PFNGLUSEPROGRAMOBJECTARBPROC) gl_ctx->getProcAddress ("glUseProgramObjectARB");
58 	pfn_glGetUniformLocationARB   = (PFNGLGETUNIFORMLOCATIONARBPROC) gl_ctx->getProcAddress ("glGetUniformLocationARB");
59 	pfn_glUniform1fARB            = (PFNGLUNIFORM1FARBPROC) gl_ctx->getProcAddress ("glUniform1fARB");
60 	pfn_glUniform1iARB            = (PFNGLUNIFORM1IARBPROC) gl_ctx->getProcAddress ("glUniform1iARB");
61 	pfn_glUniform1fvARB           = (PFNGLUNIFORM1FVARBPROC) gl_ctx->getProcAddress ("glUniform1fvARB");
62 	pfn_glUniform2fvARB           = (PFNGLUNIFORM2FVARBPROC) gl_ctx->getProcAddress ("glUniform2fvARB");
63 	pfn_glUniform3fvARB           = (PFNGLUNIFORM3FVARBPROC) gl_ctx->getProcAddress ("glUniform3fvARB");
64 	pfn_glUniform4fvARB           = (PFNGLUNIFORM4FVARBPROC) gl_ctx->getProcAddress ("glUniform4fvARB");
65 	pfn_glUniform1ivARB           = (PFNGLUNIFORM1IVARBPROC) gl_ctx->getProcAddress ("glUniform1ivARB");
66 	pfn_glUniform2ivARB           = (PFNGLUNIFORM2IVARBPROC) gl_ctx->getProcAddress ("glUniform2ivARB");
67 	pfn_glUniform3ivARB           = (PFNGLUNIFORM3IVARBPROC) gl_ctx->getProcAddress ("glUniform3ivARB");
68 	pfn_glUniform4ivARB           = (PFNGLUNIFORM4IVARBPROC) gl_ctx->getProcAddress ("glUniform4ivARB");
69 
70 	if ( pfn_glGetObjectParameterivARB && pfn_glGetInfoLogARB && pfn_glDeleteObjectARB && pfn_glCreateShaderObjectARB &&
71 			pfn_glShaderSourceARB && pfn_glCompileShaderARB && pfn_glCreateProgramObjectARB && pfn_glAttachObjectARB &&
72 			pfn_glLinkProgramARB && pfn_glValidateProgramARB && pfn_glUseProgramObjectARB &&
73 			pfn_glGetUniformLocationARB && pfn_glUniform1fARB && pfn_glUniform1iARB &&
74 			pfn_glUniform1fvARB && pfn_glUniform2fvARB && pfn_glUniform3fvARB && pfn_glUniform4fvARB &&
75 			pfn_glUniform1ivARB && pfn_glUniform2ivARB && pfn_glUniform3ivARB && pfn_glUniform4ivARB
76 		)
77 	{
78 		return 0;
79 	}
80 
81 	osd_printf_error("OpenGL: missing ARB shader function: ");
82 	if (!pfn_glGetObjectParameterivARB) osd_printf_error("glGetObjectParameterivARB, ");
83 	if (!pfn_glGetInfoLogARB) osd_printf_error("glGetInfoLogARB, ");
84 	if (!pfn_glDeleteObjectARB) osd_printf_error("glDeleteObjectARB, ");
85 	if (!pfn_glCreateShaderObjectARB) osd_printf_error("glCreateShaderObjectARB, ");
86 	if (!pfn_glShaderSourceARB) osd_printf_error("glShaderSourceARB, ");
87 	if (!pfn_glCompileShaderARB) osd_printf_error("glCompileShaderARB, ");
88 	if (!pfn_glCreateProgramObjectARB) osd_printf_error("glCreateProgramObjectARB, ");
89 	if (!pfn_glAttachObjectARB) osd_printf_error("glAttachObjectARB, ");
90 	if (!pfn_glLinkProgramARB) osd_printf_error("glLinkProgramARB, ");
91 	if (!pfn_glValidateProgramARB) osd_printf_error("glValidateProgramARB, ");
92 	if (!pfn_glUseProgramObjectARB) osd_printf_error("glUseProgramObjectARB, ");
93 	if (!pfn_glGetUniformLocationARB) osd_printf_error("glGetUniformLocationARB, ");
94 	if (!pfn_glUniform1fARB) osd_printf_error("glUniform1fARB, ");
95 	if (!pfn_glUniform1iARB) osd_printf_error("glUniform1iARB");
96 	if (!pfn_glUniform1fvARB) osd_printf_error("glUniform1fvARB, ");
97 	if (!pfn_glUniform2fvARB) osd_printf_error("glUniform2fvARB, ");
98 	if (!pfn_glUniform3fvARB) osd_printf_error("glUniform3fvARB, ");
99 	if (!pfn_glUniform4fvARB) osd_printf_error("glUniform4fvARB, ");
100 	if (!pfn_glUniform1ivARB) osd_printf_error("glUniform1ivARB");
101 	if (!pfn_glUniform2ivARB) osd_printf_error("glUniform2ivARB");
102 	if (!pfn_glUniform3ivARB) osd_printf_error("glUniform3ivARB");
103 	if (!pfn_glUniform4ivARB) osd_printf_error("glUniform4ivARB");
104 	osd_printf_error("\n");
105 
106 	return -1;
107 }
108 
gl_check_error(GLSLCheckMode m,const char * file,const int line)109 int gl_check_error(GLSLCheckMode m, const char *file, const int line)
110 {
111 		GLenum glerr = glGetError();
112 
113 		if (GL_NO_ERROR != glerr)
114 		{
115 				if ( CHECK_VERBOSE <= m )
116 				{
117 			osd_printf_warning( "%s:%d: GL Error: %d 0x%X\n", file, line, (int)glerr, (unsigned int)glerr);
118 				}
119 		}
120 	return (GL_NO_ERROR != glerr)? glerr : 0;
121 }
122 
gl_shader_check_error(GLhandleARB obj,GLenum obj_query,GLSLCheckMode m,const char * file,const int line)123 int gl_shader_check_error(GLhandleARB obj, GLenum obj_query, GLSLCheckMode m, const char *file, const int line)
124 {
125 	GLsizei length;
126 	GLcharARB buffer[255];
127 	GLenum glerr;
128 	GLint  param;
129 	int    res=0;
130 
131 	glerr = gl_check_error(m, file, line);
132 
133 	if(!obj)
134 		return glerr;
135 
136 	if(obj_query != GL_OBJECT_TYPE_ARB            &&
137 		obj_query != GL_OBJECT_DELETE_STATUS_ARB   &&
138 		obj_query != GL_OBJECT_COMPILE_STATUS_ARB  &&
139 		obj_query != GL_OBJECT_LINK_STATUS_ARB     &&
140 		obj_query != GL_OBJECT_VALIDATE_STATUS_ARB
141 		)
142 	{
143 		osd_printf_warning("%s:%d: GL Error: gl_shader_check_error unsupported object query 0x%X\n", file, line, (unsigned int)obj_query);
144 		return -1;
145 	}
146 
147 	pfn_glGetObjectParameterivARB(obj, obj_query, &param);
148 
149 	switch(obj_query)
150 	{
151 		case GL_OBJECT_TYPE_ARB:
152 		if( param!=GL_PROGRAM_OBJECT_ARB && param!=GL_SHADER_OBJECT_ARB )
153 		{
154 			if ( CHECK_VERBOSE <= m )
155 				osd_printf_warning("%s:%d: GL Error: object type 0x%X generation failed\n", file, line, (unsigned int)(uintptr_t)obj);
156 			res=-1;
157 		} else if ( CHECK_ALWAYS_VERBOSE <= m )
158 		{
159 			if(param==GL_PROGRAM_OBJECT_ARB)
160 				osd_printf_warning("%s:%d: GL Error: object type 0x%X is PROGRAM, successful\n", file, line, (unsigned int)(uintptr_t)obj);
161 			else
162 				osd_printf_warning("%s:%d: GL Info: object type 0x%X is SHADER, successful\n", file, line, (unsigned int)(uintptr_t)obj);
163 		}
164 		break;
165 		case GL_OBJECT_DELETE_STATUS_ARB:
166 		if(param!=1)
167 		{
168 			if ( CHECK_ALWAYS_VERBOSE <= m )
169 				osd_printf_warning("%s:%d: GL Info: object 0x%X not yet marked for deletion\n", file, line, (unsigned int)(uintptr_t)obj);
170 		} else if ( CHECK_ALWAYS_VERBOSE <= m )
171 		{
172 			osd_printf_warning("%s:%d: GL Info: object 0x%X deletion successful\n", file, line, (unsigned int)(uintptr_t)obj);
173 		}
174 		break;
175 		case GL_OBJECT_COMPILE_STATUS_ARB:
176 		if(param!=1)
177 		{
178 			if ( CHECK_VERBOSE <= m )
179 				osd_printf_warning("%s:%d: GL Error: object 0x%X compilation failed\n", file, line, (unsigned int)(uintptr_t)obj);
180 			res=-1;
181 		} else if ( CHECK_ALWAYS_VERBOSE <= m )
182 		{
183 			osd_printf_warning("%s:%d: GL Info: object 0x%X compiled successful\n", file, line, (unsigned int)(uintptr_t)obj);
184 		}
185 		break;
186 		case GL_OBJECT_LINK_STATUS_ARB:
187 		if(param!=1)
188 		{
189 			if ( CHECK_VERBOSE <= m )
190 				osd_printf_warning("%s:%d: GL Error: object 0x%X linking failed\n", file, line, (unsigned int)(uintptr_t)obj);
191 			res=-1;
192 		} else if ( CHECK_ALWAYS_VERBOSE <= m )
193 		{
194 			osd_printf_warning("%s:%d: GL Info: object 0x%X linked successful\n", file, line, (unsigned int)(uintptr_t)obj);
195 		}
196 		break;
197 		case GL_OBJECT_VALIDATE_STATUS_ARB:
198 		if(param!=1)
199 		{
200 			if ( CHECK_VERBOSE <= m )
201 				osd_printf_warning("%s:%d: GL Error: object 0x%X validation failed\n", file, line, (unsigned int)(uintptr_t)obj);
202 			res=-1;
203 		} else if ( CHECK_ALWAYS_VERBOSE <= m )
204 		{
205 			osd_printf_warning("%s:%d: GL Info: object 0x%X validation successful\n", file, line, (unsigned int)(uintptr_t)obj);
206 		}
207 		break;
208 		}
209 
210 	if ( res<0 || CHECK_ALWAYS_VERBOSE <= m )
211 	{
212 		length=0;
213 		pfn_glGetInfoLogARB(obj, sizeof(buffer), &length, buffer);
214 		if(length>0)
215 			osd_printf_warning("%s:%d glInfoLog: %s\n", file, line, buffer);
216 	}
217 
218 	(void) glGetError(); // ;-)
219 
220 
221 	return res;
222 }
223 
gl_round_to_pow2(int v)224 int gl_round_to_pow2(int v)
225 {
226 	if (v & (v - 1))
227 	{
228 		v |= v >> 1;
229 		v |= v >> 2;
230 		v |= v >> 4;
231 		v |= v >> 8;
232 		v++;
233 	}
234 	return v;
235 }
236 
gl_texture_check_size(GLenum target,GLint level,GLint internalFormat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,GLint * avail_width,GLint * avail_height,int verbose)237 int gl_texture_check_size(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height,
238 							GLint border, GLenum format, GLenum type,
239 				GLint *avail_width, GLint *avail_height,
240 				int verbose)
241 {
242 	int err=1;
243 	GLenum texTargetProxy = (target==GL_TEXTURE_RECTANGLE_ARB)?GL_PROXY_TEXTURE_RECTANGLE_ARB:GL_PROXY_TEXTURE_2D;
244 
245 	if ( !avail_width || !avail_height)
246 	return -1;
247 
248 	*avail_width  = 0;
249 	*avail_height = 0;
250 
251 	GL_CHECK_ERROR_QUIET();
252 
253 	/* Test the max texture size */
254 	while(err && width>=1 && height>=1 /* && width>=64 && height>=64 */)
255 	{
256 	glTexImage2D (texTargetProxy, level,
257 			internalFormat,
258 			width, height,
259 			border, format, type, nullptr);
260 	if ( 0!=(err=GL_CHECK_ERROR_NORMAL() )) return err;
261 
262 	glGetTexLevelParameteriv( texTargetProxy, level, GL_TEXTURE_WIDTH,  avail_width);
263 	glGetTexLevelParameteriv( texTargetProxy, level, GL_TEXTURE_HEIGHT, avail_height);
264 	if ( 0!=(err=GL_CHECK_ERROR_NORMAL() )) return err;
265 
266 	if ( (*avail_width) != width || (*avail_height) != height )
267 	{
268 		err=1;
269 
270 		if(verbose)
271 		{
272 			osd_printf_warning("gl_texture_size_check: "
273 				"TexImage2D(0x%X, %d, 0x%X, %d, %d, %d, 0x%X, 0x%X): returned size does not match: %dx%d\n",
274 				(unsigned int)target, (int)level, (int)internalFormat,
275 				(int)width, (int)height, (int)border, (unsigned int)format, (unsigned int)type,
276 								(int)*avail_width, (int)*avail_height);
277 		}
278 
279 		if ( (*avail_width)  == width   )
280 			height /= 2;
281 		else if ( (*avail_height) == height )
282 			width /= 2;
283 		else if (width > height)
284 				width /= 2;
285 		else
286 				height /= 2;
287 		if(verbose)
288 		{
289 			fprintf (stderr, "gl_texture_size_check: trying [%dx%d] !\n", (int)height, (int)width);
290 		}
291 	} else {
292 		err=0;
293 	}
294 	}
295 	if(!err)
296 	{
297 		*avail_width  = width;
298 		*avail_height = height;
299 	}
300 	return err;
301 }
302 
delete_shader_tool(GLhandleARB * program,GLhandleARB * vertex_shader,GLhandleARB * fragment_shader,int externalcall)303 static int delete_shader_tool( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader, int externalcall)
304 {
305 	int res=0;
306 
307 	GL_CHECK_ERROR_QUIET();
308 	if(program!= nullptr && *program!=0)
309 	{
310 		pfn_glDeleteObjectARB(*program);
311 		if(externalcall)
312 		{
313 			res |= GL_SHADER_CHECK(*program, GL_OBJECT_DELETE_STATUS_ARB);
314 		}
315 		*program=0;
316 	}
317 	if(vertex_shader!= nullptr && *vertex_shader!=0)
318 	{
319 		pfn_glDeleteObjectARB(*vertex_shader);
320 		if(externalcall)
321 		{
322 			res |= GL_SHADER_CHECK(*vertex_shader, GL_OBJECT_DELETE_STATUS_ARB);
323 		}
324 		*vertex_shader=0;
325 	}
326 	if(fragment_shader!= nullptr && *fragment_shader!=0)
327 	{
328 		pfn_glDeleteObjectARB(*fragment_shader);
329 		if(externalcall)
330 		{
331 			res |= GL_SHADER_CHECK(*fragment_shader, GL_OBJECT_DELETE_STATUS_ARB);
332 		}
333 		*fragment_shader=0;
334 	}
335 
336 		return res;
337 }
338 
gl_compile_shader_source(GLhandleARB * shader,GLenum type,const char * shader_source,int verbose)339 int gl_compile_shader_source( GLhandleARB *shader, GLenum type, const char * shader_source, int verbose )
340 {
341 		int err = 0;
342 
343 	if(shader== nullptr || shader_source== nullptr)
344 	{
345 		if(shader== nullptr)
346 			osd_printf_warning("error: gl_compile_shader_source: nullptr shader passed\n");
347 		if(shader_source== nullptr)
348 			osd_printf_warning("error: gl_compile_shader_source: nullptr shader source passed\n");
349 		return -1;
350 	}
351 		*shader = pfn_glCreateShaderObjectARB(type);
352 	err=GL_SHADER_CHECK(*shader, GL_OBJECT_TYPE_ARB);
353 		if(err) goto errout;
354 
355 		pfn_glShaderSourceARB(*shader, 1, (const GLcharARB **)&shader_source, nullptr);
356 
357 		pfn_glCompileShaderARB(*shader);
358 		err=GL_SHADER_CHECK(*shader, GL_OBJECT_COMPILE_STATUS_ARB);
359 		if(err) goto errout;
360 
361 	if(verbose)
362 		osd_printf_warning( "<%s>\n", shader_source);
363 
364 	return 0;
365 
366 errout:
367 	if(*shader!=0)
368 	{
369 		pfn_glDeleteObjectARB(*shader);
370 	}
371 	osd_printf_warning("failed to process shader: <%s>\n", shader_source);
372 		return err;
373 }
374 
gl_compile_shader_file(GLhandleARB * shader,GLenum type,const char * shader_file,int verbose)375 int gl_compile_shader_file( GLhandleARB *shader, GLenum type, const char * shader_file, int verbose )
376 {
377 	if(shader== nullptr || shader_file== nullptr)
378 	{
379 		if(shader== nullptr)
380 			osd_printf_warning("error: gl_compile_shader_source: nullptr shader passed\n");
381 		if(shader_file== nullptr)
382 			osd_printf_warning("error: gl_compile_shader_source: nullptr shader file passed\n");
383 		return -1;
384 	}
385 
386 	FILE *const file = fopen(shader_file, "r");
387 	if(!file)
388 	{
389 		osd_printf_warning("cannot open shader_file: %s\n", shader_file);
390 		return -1;
391 	}
392 
393 	// get the real file size
394 	fseek(file, 0, SEEK_END);
395 	int const buffer_len = (int)ftell(file);
396 	fseek(file, 0, SEEK_SET);
397 
398 	auto *const buffer = (GLcharARB *)malloc(buffer_len + 1);
399 	memset(buffer, 0, buffer_len + 1);
400 
401 	/* Load Shader Sources */
402 	for( int i = 0, c = 0; i<buffer_len && EOF!=(c=fgetc(file)); i++ )
403 		buffer[i]=(char)c;
404 	fclose(file);
405 
406 	int const err=gl_compile_shader_source(shader, type, buffer, verbose);
407 	free(buffer);
408 	if(err) goto errout;
409 
410 	if(verbose)
411 		osd_printf_warning("shader file: %s\n", shader_file);
412 
413 	return 0;
414 
415 errout:
416 	osd_printf_warning("failed to process shader_file: %s\n", shader_file);
417 	return err;
418 }
419 
420 
gl_compile_shader_files(GLhandleARB * program,GLhandleARB * vertex_shader,GLhandleARB * fragment_shader,const char * vertex_shader_file,const char * fragment_shader_file,int verbose)421 int gl_compile_shader_files( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader,
422 								const char * vertex_shader_file,
423 								const char * fragment_shader_file,
424 					int verbose
425 							)
426 {
427 	int err;
428 
429 	if (!program)
430 	{
431 		err=-1;
432 		osd_printf_warning("no program ptr passed\n");
433 		goto errout;
434 	}
435 	if (!vertex_shader)
436 	{
437 		err=-1;
438 		osd_printf_warning("no vertex_shader ptr passed\n");
439 		goto errout;
440 	}
441 	if (!fragment_shader)
442 	{
443 		err=-1;
444 		osd_printf_warning("no fragment_shader ptr passed\n");
445 		goto errout;
446 	}
447 
448 		*program = pfn_glCreateProgramObjectARB();
449 		err=GL_SHADER_CHECK(*program, GL_OBJECT_TYPE_ARB);
450 		if(err) goto errout;
451 
452 	if(!vertex_shader_file)
453 	{
454 		if (!(*vertex_shader))
455 		{
456 			err=-1;
457 			osd_printf_warning("no vertex_shader_file, nor vertex_shader id passed\n");
458 			goto errout;
459 		}
460 		err=GL_SHADER_CHECK(*vertex_shader, GL_OBJECT_TYPE_ARB);
461 		if(err) goto errout;
462 	} else {
463 		err = gl_compile_shader_file(vertex_shader, GL_VERTEX_SHADER_ARB, vertex_shader_file, verbose);
464 		if(err) return err;
465 	}
466 		pfn_glAttachObjectARB(*program, *vertex_shader);
467 
468 	if(!fragment_shader_file)
469 	{
470 		if (!(*fragment_shader))
471 		{
472 			err=-1;
473 			osd_printf_warning("no fragment_shader_file, nor fragment_shader id passed\n");
474 			goto errout;
475 		}
476 		err=GL_SHADER_CHECK(*fragment_shader, GL_OBJECT_TYPE_ARB);
477 		if(err) goto errout;
478 	} else {
479 		err = gl_compile_shader_file(fragment_shader, GL_FRAGMENT_SHADER_ARB, fragment_shader_file, verbose);
480 		if(err) return err;
481 	}
482 		pfn_glAttachObjectARB(*program, *fragment_shader);
483 
484 		pfn_glLinkProgramARB(*program);
485 		err=GL_SHADER_CHECK(*program, GL_OBJECT_LINK_STATUS_ARB);
486 		if(err) goto errout;
487 
488 		pfn_glValidateProgramARB(*program);
489 		err=GL_SHADER_CHECK(*program, GL_OBJECT_VALIDATE_STATUS_ARB);
490 		if(err) goto errout;
491 
492 		return 0;
493 
494 errout:
495 		delete_shader_tool(program, vertex_shader, fragment_shader, 0);
496 		return err;
497 
498 }
499 
gl_compile_shader_sources(GLhandleARB * program,GLhandleARB * vertex_shader,GLhandleARB * fragment_shader,const GLcharARB * vertex_shader_source,const GLcharARB * fragment_shader_source)500 int gl_compile_shader_sources( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader,
501 								const GLcharARB * vertex_shader_source,
502 								const GLcharARB * fragment_shader_source
503 								)
504 {
505 		int err = 0;
506 
507 	if (!program)
508 	{
509 		err=-1;
510 		osd_printf_warning("no program ptr passed\n");
511 		goto errout;
512 	}
513 	if (!vertex_shader)
514 	{
515 		err=-1;
516 		osd_printf_warning("no vertex_shader ptr passed\n");
517 		goto errout;
518 	}
519 	if (!fragment_shader)
520 	{
521 		err=-1;
522 		osd_printf_warning("no fragment_shader ptr passed\n");
523 		goto errout;
524 	}
525 
526 		*program = pfn_glCreateProgramObjectARB();
527 		err=GL_SHADER_CHECK(*program, GL_OBJECT_TYPE_ARB);
528 		if(err) goto errout;
529 
530 	if(!vertex_shader_source)
531 	{
532 		if (!(*vertex_shader))
533 		{
534 			err=-1;
535 			osd_printf_warning("no vertex_shader_source nor a vertex_shader id passed\n");
536 			goto errout;
537 		}
538 		err=GL_SHADER_CHECK(*vertex_shader, GL_OBJECT_TYPE_ARB);
539 		if(err) goto errout;
540 	}
541 	if(!fragment_shader_source)
542 	{
543 		if (!(*fragment_shader))
544 		{
545 			err=-1;
546 			osd_printf_warning("no fragment_shader_source nor a fragment_shader id passed\n");
547 			goto errout;
548 		}
549 		err=GL_SHADER_CHECK(*fragment_shader, GL_OBJECT_TYPE_ARB);
550 		if(err) goto errout;
551 	}
552 
553 	if(vertex_shader_source)
554 	{
555 		err=gl_compile_shader_source(vertex_shader, GL_VERTEX_SHADER_ARB, vertex_shader_source, 0);
556 		if(err) goto errout;
557 	}
558 		pfn_glAttachObjectARB(*program, *vertex_shader);
559 
560 	if(fragment_shader_source)
561 	{
562 		err=gl_compile_shader_source(fragment_shader, GL_FRAGMENT_SHADER_ARB, fragment_shader_source, 0);
563 		if(err) goto errout;
564 	}
565 		pfn_glAttachObjectARB(*program, *fragment_shader);
566 
567 		pfn_glLinkProgramARB(*program);
568 		err=GL_SHADER_CHECK(*program, GL_OBJECT_LINK_STATUS_ARB);
569 		if(err) {
570 		osd_printf_warning("failed to link program\n");
571 		osd_printf_warning("vertex shader: <%s>\n", vertex_shader_source);
572 		osd_printf_warning("fragment shader: <%s>\n", fragment_shader_source);
573 		goto errout;
574 	}
575 
576 		pfn_glValidateProgramARB(*program);
577 		err=GL_SHADER_CHECK(*program, GL_OBJECT_VALIDATE_STATUS_ARB);
578 		if(err) {
579 		osd_printf_warning("failed to validate program\n");
580 		osd_printf_warning("vertex shader: <%s>\n", vertex_shader_source);
581 		osd_printf_warning("fragment shader: <%s>\n", fragment_shader_source);
582 		goto errout;
583 	}
584 
585 		return 0;
586 
587 errout:
588 		delete_shader_tool(program, vertex_shader, fragment_shader, 0);
589 		return err;
590 
591 }
592 
593 
gl_delete_shader(GLhandleARB * program,GLhandleARB * vertex_shader,GLhandleARB * fragment_shader)594 int gl_delete_shader( GLhandleARB *program, GLhandleARB *vertex_shader, GLhandleARB *fragment_shader )
595 {
596 	return delete_shader_tool(program, vertex_shader, fragment_shader, 1);
597 }
598