2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2007 Brian Paul, Tungsten Graphics, Inc.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 * Stand-alone Shading Language compiler.
30 * Basically, a command-line program which accepts GLSL shaders and emits
31 * vertex/fragment programs (GPU instructions).
33 * This file is basically just a Mesa device driver but instead of building
34 * a shared library we build an executable.
36 * We can emit programs in three different formats:
37 * 1. ARB-style (GL_ARB_vertex/fragment_program)
38 * 2. NV-style (GL_NV_vertex/fragment_program)
39 * 3. debug-style (a slightly more sophisticated, internal format)
41 * Note that the ARB and NV program languages can't express all the
42 * features that might be used by a fragment program (examples being
43 * uniform and varying vars). So, the ARB/NV programs that are
44 * emitted aren't always legal programs in those languages.
48 #include "main/imports.h"
49 #include "main/context.h"
50 #include "main/extensions.h"
51 #include "main/framebuffer.h"
52 #include "main/shaderapi.h"
53 #include "main/shaderobj.h"
54 #include "program/prog_print.h"
55 #include "drivers/common/driverfuncs.h"
57 #include "tnl/t_context.h"
58 #include "tnl/t_pipeline.h"
59 #include "swrast/swrast.h"
60 #include "swrast_setup/swrast_setup.h"
64 static const char *Prog
= "glslcompiler";
68 GLboolean LineNumbers
;
70 gl_prog_print_mode Mode
;
74 const char *OutputFile
;
76 struct gl_sl_pragmas Pragmas
;
79 static struct options Options
;
83 * GLSL compiler driver context. (kind of an artificial thing for now)
85 struct compiler_context
87 GLcontext MesaContext
;
91 typedef struct compiler_context CompilerContext
;
96 UpdateState(GLcontext
*ctx
, GLuint new_state
)
98 /* easy - just propogate */
99 _swrast_InvalidateState( ctx
, new_state
);
100 _swsetup_InvalidateState( ctx
, new_state
);
101 _tnl_InvalidateState( ctx
, new_state
);
102 _vbo_InvalidateState( ctx
, new_state
);
110 struct dd_function_table ddFuncs
;
116 vis
= _mesa_create_visual(GL_FALSE
, GL_FALSE
, /* RGB */
117 8, 8, 8, 8, /* color */
118 0, 0, /* z, stencil */
119 0, 0, 0, 0, 1); /* accum */
120 buf
= _mesa_create_framebuffer(vis
);
122 cc
= calloc(1, sizeof(*cc
));
123 if (!vis
|| !buf
|| !cc
) {
125 _mesa_destroy_visual(vis
);
127 _mesa_destroy_framebuffer(buf
);
132 _mesa_init_driver_functions(&ddFuncs
);
133 ddFuncs
.GetString
= NULL
;/*get_string;*/
134 ddFuncs
.UpdateState
= UpdateState
;
135 ddFuncs
.GetBufferSize
= NULL
;
137 ctx
= &cc
->MesaContext
;
138 _mesa_initialize_context(ctx
, vis
, NULL
, &ddFuncs
, cc
);
139 _mesa_enable_sw_extensions(ctx
);
141 if (!_swrast_CreateContext( ctx
) ||
142 !_vbo_CreateContext( ctx
) ||
143 !_tnl_CreateContext( ctx
) ||
144 !_swsetup_CreateContext( ctx
)) {
145 _mesa_destroy_visual(vis
);
146 _mesa_destroy_framebuffer(buf
);
147 _mesa_free_context_data(ctx
);
151 TNL_CONTEXT(ctx
)->Driver
.RunPipeline
= _tnl_run_pipeline
;
152 _swsetup_Wakeup( ctx
);
154 /* Override the context's default pragma settings */
155 ctx
->Shader
.DefaultPragmas
= Options
.Pragmas
;
157 _mesa_make_current(ctx
, buf
, buf
);
164 LoadAndCompileShader(GLuint shader
, const char *text
)
167 _mesa_ShaderSourceARB(shader
, 1, (const GLchar
**) &text
, NULL
);
168 _mesa_CompileShaderARB(shader
);
169 _mesa_GetShaderiv(shader
, GL_COMPILE_STATUS
, &stat
);
173 _mesa_GetShaderInfoLog(shader
, 1000, &len
, log
);
174 fprintf(stderr
, "%s: problem compiling shader: %s\n", Prog
, log
);
178 printf("Shader compiled OK\n");
184 * Read a shader from a file.
187 ReadShader(GLuint shader
, const char *filename
)
189 const int max
= 100*1000;
191 char *buffer
= (char*) malloc(max
);
192 FILE *f
= fopen(filename
, "r");
194 fprintf(stderr
, "%s: Unable to open shader file %s\n", Prog
, filename
);
198 n
= fread(buffer
, 1, max
, f
);
200 printf("%s: read %d bytes from shader file %s\n", Prog, n, filename);
204 LoadAndCompileShader(shader
, buffer
);
213 CheckLink(GLuint v_shader
, GLuint f_shader
)
218 prog
= _mesa_CreateProgram();
220 _mesa_AttachShader(prog
, v_shader
);
221 _mesa_AttachShader(prog
, f_shader
);
223 _mesa_LinkProgramARB(prog
);
224 _mesa_GetProgramiv(prog
, GL_LINK_STATUS
, &stat
);
228 _mesa_GetProgramInfoLog(prog
, 1000, &len
, log
);
229 fprintf(stderr
, "Linker error:\n%s\n", log
);
232 fprintf(stderr
, "Link success!\n");
238 PrintShaderInstructions(GLuint shader
, FILE *f
)
240 GET_CURRENT_CONTEXT(ctx
);
241 struct gl_shader
*sh
= _mesa_lookup_shader(ctx
, shader
);
242 struct gl_program
*prog
= sh
->Program
;
243 _mesa_fprint_program_opt(stdout
, prog
, Options
.Mode
, Options
.LineNumbers
);
245 _mesa_print_program_parameters(ctx
, prog
);
250 CompileShader(const char *filename
, GLenum type
)
254 assert(type
== GL_FRAGMENT_SHADER
||
255 type
== GL_VERTEX_SHADER
||
256 type
== GL_GEOMETRY_SHADER_ARB
);
258 shader
= _mesa_CreateShader(type
);
259 ReadShader(shader
, filename
);
268 printf("Mesa GLSL stand-alone compiler\n");
270 printf(" --vs FILE vertex shader input filename\n");
271 printf(" --fs FILE fragment shader input filename\n");
272 printf(" --gs FILE geometry shader input filename\n");
273 printf(" --arb emit ARB-style instructions\n");
274 printf(" --nv emit NV-style instructions\n");
275 printf(" --link run linker\n");
276 printf(" --debug force #pragma debug(on)\n");
277 printf(" --nodebug force #pragma debug(off)\n");
278 printf(" --opt force #pragma optimize(on)\n");
279 printf(" --noopt force #pragma optimize(off)\n");
280 printf(" --number, -n emit line numbers (if --arb or --nv)\n");
281 printf(" --output, -o FILE output filename\n");
282 printf(" --params also emit program parameter info\n");
283 printf(" --help display this information\n");
288 ParseOptions(int argc
, char *argv
[])
292 Options
.LineNumbers
= GL_FALSE
;
293 Options
.Mode
= PROG_PRINT_DEBUG
;
294 Options
.VertFile
= NULL
;
295 Options
.FragFile
= NULL
;
296 Options
.GeoFile
= NULL
;
297 Options
.OutputFile
= NULL
;
298 Options
.Params
= GL_FALSE
;
299 Options
.Pragmas
.IgnoreOptimize
= GL_FALSE
;
300 Options
.Pragmas
.IgnoreDebug
= GL_FALSE
;
301 Options
.Pragmas
.Debug
= GL_FALSE
;
302 Options
.Pragmas
.Optimize
= GL_TRUE
;
309 for (i
= 1; i
< argc
; i
++) {
310 if (strcmp(argv
[i
], "--vs") == 0) {
311 Options
.VertFile
= argv
[i
+ 1];
314 else if (strcmp(argv
[i
], "--fs") == 0) {
315 Options
.FragFile
= argv
[i
+ 1];
318 else if (strcmp(argv
[i
], "--gs") == 0) {
319 Options
.GeoFile
= argv
[i
+ 1];
322 else if (strcmp(argv
[i
], "--arb") == 0) {
323 Options
.Mode
= PROG_PRINT_ARB
;
325 else if (strcmp(argv
[i
], "--nv") == 0) {
326 Options
.Mode
= PROG_PRINT_NV
;
328 else if (strcmp(argv
[i
], "--link") == 0) {
329 Options
.Link
= GL_TRUE
;
331 else if (strcmp(argv
[i
], "--debug") == 0) {
332 Options
.Pragmas
.IgnoreDebug
= GL_TRUE
;
333 Options
.Pragmas
.Debug
= GL_TRUE
;
335 else if (strcmp(argv
[i
], "--nodebug") == 0) {
336 Options
.Pragmas
.IgnoreDebug
= GL_TRUE
;
337 Options
.Pragmas
.Debug
= GL_FALSE
;
339 else if (strcmp(argv
[i
], "--opt") == 0) {
340 Options
.Pragmas
.IgnoreOptimize
= GL_TRUE
;
341 Options
.Pragmas
.Optimize
= GL_TRUE
;
343 else if (strcmp(argv
[i
], "--noopt") == 0) {
344 Options
.Pragmas
.IgnoreOptimize
= GL_TRUE
;
345 Options
.Pragmas
.Optimize
= GL_FALSE
;
347 else if (strcmp(argv
[i
], "--number") == 0 ||
348 strcmp(argv
[i
], "-n") == 0) {
349 Options
.LineNumbers
= GL_TRUE
;
351 else if (strcmp(argv
[i
], "--output") == 0 ||
352 strcmp(argv
[i
], "-o") == 0) {
353 Options
.OutputFile
= argv
[i
+ 1];
356 else if (strcmp(argv
[i
], "--params") == 0) {
357 Options
.Params
= GL_TRUE
;
359 else if (strcmp(argv
[i
], "--help") == 0) {
364 printf("Unknown option: %s\n", argv
[i
]);
370 if (Options
.Mode
== PROG_PRINT_DEBUG
) {
371 /* always print line numbers when emitting debug-style output */
372 Options
.LineNumbers
= GL_TRUE
;
378 main(int argc
, char *argv
[])
380 GLuint v_shader
= 0, f_shader
= 0, g_shader
= 0;
382 ParseOptions(argc
, argv
);
384 if (!CreateContext()) {
385 fprintf(stderr
, "%s: Failed to create compiler context\n", Prog
);
389 if (Options
.VertFile
) {
390 v_shader
= CompileShader(Options
.VertFile
, GL_VERTEX_SHADER
);
393 if (Options
.FragFile
) {
394 f_shader
= CompileShader(Options
.FragFile
, GL_FRAGMENT_SHADER
);
397 if (Options
.GeoFile
) {
398 g_shader
= CompileShader(Options
.GeoFile
, GL_GEOMETRY_SHADER_ARB
);
402 if (v_shader
|| f_shader
|| g_shader
) {
403 if (Options
.OutputFile
) {
406 /*stdout =*/ f
= freopen(Options
.OutputFile
, "w", stdout
);
408 fprintf(stderr
, "freopen error\n");
411 if (stdout
&& v_shader
) {
412 PrintShaderInstructions(v_shader
, stdout
);
414 if (stdout
&& f_shader
) {
415 PrintShaderInstructions(f_shader
, stdout
);
417 if (stdout
&& g_shader
) {
418 PrintShaderInstructions(g_shader
, stdout
);
420 if (Options
.OutputFile
) {
426 if (!v_shader
|| !f_shader
) {
428 "--link option requires both a vertex and fragment shader.\n");
432 CheckLink(v_shader
, f_shader
);