blob: 54a4c1a7c6d7a7f29279f98974be87984faeeadc [file] [log] [blame]
Briancc153542007-02-17 09:15:39 -07001/*
2 * Mesa 3-D graphics library
3 * Version: 6.5.3
4 *
5 * Copyright (C) 1999-2007 Brian Paul, Tungsten Graphics, Inc.
6 * All Rights Reserved.
7 *
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:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
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.
24 */
25
26/**
27 * \mainpage
28 *
29 * Stand-alone Shading Language compiler.
30 * Basically, a command-line program which accepts GLSL shaders and emits
31 * vertex/fragment programs (GPU instructions).
32 *
33 * This file is basically just a Mesa device driver but instead of building
34 * a shared library we build an executable.
35 *
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)
40 *
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.
45 */
46
47
Brian Paul374e7fd2008-09-18 13:46:47 -060048#include "main/imports.h"
49#include "main/context.h"
50#include "main/extensions.h"
51#include "main/framebuffer.h"
52#include "main/shaders.h"
Briancc153542007-02-17 09:15:39 -070053#include "shader/shader_api.h"
54#include "shader/prog_print.h"
55#include "drivers/common/driverfuncs.h"
Briancc153542007-02-17 09:15:39 -070056#include "tnl/tnl.h"
57#include "tnl/t_context.h"
58#include "tnl/t_pipeline.h"
59#include "swrast/swrast.h"
60#include "swrast/s_context.h"
61#include "swrast/s_triangle.h"
62#include "swrast_setup/swrast_setup.h"
Brianbc18ac42007-02-22 16:29:25 -070063#include "vbo/vbo.h"
Briancc153542007-02-17 09:15:39 -070064
65
66static const char *Prog = "glslcompiler";
67
68
69struct options {
70 GLboolean LineNumbers;
71 gl_prog_print_mode Mode;
72 const char *VertFile;
73 const char *FragFile;
74 const char *OutputFile;
Brian Pauledd8cb82009-02-17 15:57:46 -070075 GLboolean Params;
Briancc153542007-02-17 09:15:39 -070076};
77
78static struct options Options;
79
80
81/**
82 * GLSL compiler driver context. (kind of an artificial thing for now)
83 */
84struct compiler_context
85{
86 GLcontext MesaContext;
87 int foo;
88};
89
90typedef struct compiler_context CompilerContext;
91
92
93
94static void
95UpdateState(GLcontext *ctx, GLuint new_state)
96{
97 /* easy - just propogate */
98 _swrast_InvalidateState( ctx, new_state );
99 _swsetup_InvalidateState( ctx, new_state );
Briancc153542007-02-17 09:15:39 -0700100 _tnl_InvalidateState( ctx, new_state );
Brianbc18ac42007-02-22 16:29:25 -0700101 _vbo_InvalidateState( ctx, new_state );
Briancc153542007-02-17 09:15:39 -0700102}
103
104
105
106static GLboolean
107CreateContext(void)
108{
109 struct dd_function_table ddFuncs;
110 GLvisual *vis;
111 GLframebuffer *buf;
112 GLcontext *ctx;
113 CompilerContext *cc;
114
115 vis = _mesa_create_visual(GL_TRUE, GL_FALSE, GL_FALSE, /* RGB */
116 8, 8, 8, 8, /* color */
117 0, 0, 0, /* z, stencil */
118 0, 0, 0, 0, 1); /* accum */
119 buf = _mesa_create_framebuffer(vis);
120
121 cc = _mesa_calloc(sizeof(*cc));
122 if (!vis || !buf || !cc) {
123 if (vis)
124 _mesa_destroy_visual(vis);
125 if (buf)
126 _mesa_destroy_framebuffer(buf);
127 return GL_FALSE;
128 }
129
130 _mesa_init_driver_functions(&ddFuncs);
131 ddFuncs.GetString = NULL;/*get_string;*/
132 ddFuncs.UpdateState = UpdateState;
133 ddFuncs.GetBufferSize = NULL;
134
135 ctx = &cc->MesaContext;
136 _mesa_initialize_context(ctx, vis, NULL, &ddFuncs, cc);
137 _mesa_enable_sw_extensions(ctx);
138
139 if (!_swrast_CreateContext( ctx ) ||
Brianbc18ac42007-02-22 16:29:25 -0700140 !_vbo_CreateContext( ctx ) ||
Briancc153542007-02-17 09:15:39 -0700141 !_tnl_CreateContext( ctx ) ||
142 !_swsetup_CreateContext( ctx )) {
143 _mesa_destroy_visual(vis);
144 _mesa_free_context_data(ctx);
145 _mesa_free(cc);
146 return GL_FALSE;
147 }
148 TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
149 _swsetup_Wakeup( ctx );
150
151 _mesa_make_current(ctx, buf, buf);
152
153 return GL_TRUE;
154}
155
156
157static void
158LoadAndCompileShader(GLuint shader, const char *text)
159{
160 GLint stat;
161 _mesa_ShaderSourceARB(shader, 1, (const GLchar **) &text, NULL);
162 _mesa_CompileShaderARB(shader);
163 _mesa_GetShaderiv(shader, GL_COMPILE_STATUS, &stat);
164 if (!stat) {
165 GLchar log[1000];
166 GLsizei len;
167 _mesa_GetShaderInfoLog(shader, 1000, &len, log);
168 fprintf(stderr, "%s: problem compiling shader: %s\n", Prog, log);
169 exit(1);
170 }
171 else {
172 printf("Shader compiled OK\n");
173 }
174}
175
176
177/**
178 * Read a shader from a file.
179 */
180static void
181ReadShader(GLuint shader, const char *filename)
182{
183 const int max = 100*1000;
184 int n;
185 char *buffer = (char*) malloc(max);
186 FILE *f = fopen(filename, "r");
187 if (!f) {
188 fprintf(stderr, "%s: Unable to open shader file %s\n", Prog, filename);
189 exit(1);
190 }
191
192 n = fread(buffer, 1, max, f);
193 /*
194 printf("%s: read %d bytes from shader file %s\n", Prog, n, filename);
195 */
196 if (n > 0) {
197 buffer[n] = 0;
198 LoadAndCompileShader(shader, buffer);
199 }
200
201 fclose(f);
202 free(buffer);
203}
204
205
206#if 0
207static void
208CheckLink(GLuint prog)
209{
210 GLint stat;
211 _mesa_GetProgramiv(prog, GL_LINK_STATUS, &stat);
212 if (!stat) {
213 GLchar log[1000];
214 GLsizei len;
215 _mesa_GetProgramInfoLog(prog, 1000, &len, log);
216 fprintf(stderr, "%s: Linker error:\n%s\n", Prog, log);
217 }
218 else {
219 fprintf(stderr, "%s: Link success!\n", Prog);
220 }
221}
222#endif
223
224
225static void
226PrintShaderInstructions(GLuint shader, FILE *f)
227{
228 GET_CURRENT_CONTEXT(ctx);
229 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
Brian Paul11008662008-10-28 17:03:35 -0600230 struct gl_program *prog = sh->Program;
Brian Paule33edaf2009-02-02 12:24:58 -0700231 _mesa_fprint_program_opt(stdout, prog, Options.Mode, Options.LineNumbers);
Brian Pauledd8cb82009-02-17 15:57:46 -0700232 if (Options.Params)
233 _mesa_print_program_parameters(ctx, prog);
Briancc153542007-02-17 09:15:39 -0700234}
235
236
237static GLuint
238CompileShader(const char *filename, GLenum type)
239{
240 GLuint shader;
241
242 assert(type == GL_FRAGMENT_SHADER ||
243 type == GL_VERTEX_SHADER);
244
245 shader = _mesa_CreateShader(type);
246 ReadShader(shader, filename);
247
248 return shader;
249}
250
251
252static void
253Usage(void)
254{
255 printf("Mesa GLSL stand-alone compiler\n");
256 printf("Usage:\n");
257 printf(" --vs FILE vertex shader input filename\n");
258 printf(" --fs FILE fragment shader input filename\n");
259 printf(" --arb emit ARB-style instructions (the default)\n");
260 printf(" --nv emit NV-style instructions\n");
261 printf(" --debug emit debug-style instructions\n");
262 printf(" --number, -n emit line numbers\n");
263 printf(" --output, -o FILE output filename\n");
Brian Pauledd8cb82009-02-17 15:57:46 -0700264 printf(" --params also emit program parameter info\n");
Briancc153542007-02-17 09:15:39 -0700265 printf(" --help display this information\n");
266}
267
268
269static void
270ParseOptions(int argc, char *argv[])
271{
272 int i;
273
274 Options.LineNumbers = GL_FALSE;
275 Options.Mode = PROG_PRINT_ARB;
276 Options.VertFile = NULL;
277 Options.FragFile = NULL;
278 Options.OutputFile = NULL;
Brian Pauledd8cb82009-02-17 15:57:46 -0700279 Options.Params = GL_FALSE;
Briancc153542007-02-17 09:15:39 -0700280
Brianbc18ac42007-02-22 16:29:25 -0700281 if (argc == 1) {
282 Usage();
283 exit(0);
284 }
285
Briancc153542007-02-17 09:15:39 -0700286 for (i = 1; i < argc; i++) {
287 if (strcmp(argv[i], "--vs") == 0) {
288 Options.VertFile = argv[i + 1];
289 i++;
290 }
291 else if (strcmp(argv[i], "--fs") == 0) {
292 Options.FragFile = argv[i + 1];
293 i++;
294 }
295 else if (strcmp(argv[i], "--arb") == 0) {
296 Options.Mode = PROG_PRINT_ARB;
297 }
298 else if (strcmp(argv[i], "--nv") == 0) {
299 Options.Mode = PROG_PRINT_NV;
300 }
301 else if (strcmp(argv[i], "--debug") == 0) {
302 Options.Mode = PROG_PRINT_DEBUG;
303 }
304 else if (strcmp(argv[i], "--number") == 0 ||
305 strcmp(argv[i], "-n") == 0) {
306 Options.LineNumbers = GL_TRUE;
307 }
308 else if (strcmp(argv[i], "--output") == 0 ||
309 strcmp(argv[i], "-o") == 0) {
310 Options.OutputFile = argv[i + 1];
311 i++;
312 }
Brian Pauledd8cb82009-02-17 15:57:46 -0700313 else if (strcmp(argv[i], "--params") == 0) {
314 Options.Params = GL_TRUE;
315 }
Briancc153542007-02-17 09:15:39 -0700316 else if (strcmp(argv[i], "--help") == 0) {
317 Usage();
318 exit(0);
319 }
320 else {
321 printf("Unknown option: %s\n", argv[i]);
322 Usage();
323 exit(1);
324 }
325 }
326}
327
328
329int
330main(int argc, char *argv[])
331{
332 GLuint shader = 0;
333
334 if (!CreateContext()) {
335 fprintf(stderr, "%s: Failed to create compiler context\n", Prog);
336 exit(1);
337 }
338
339 ParseOptions(argc, argv);
340
341 if (Options.VertFile) {
342 shader = CompileShader(Options.VertFile, GL_VERTEX_SHADER);
343 }
344 else if (Options.FragFile) {
345 shader = CompileShader(Options.FragFile, GL_FRAGMENT_SHADER);
346 }
347
348 if (shader) {
349 if (Options.OutputFile) {
350 fclose(stdout);
351 /*stdout =*/ freopen(Options.OutputFile, "w", stdout);
352 }
353 if (stdout) {
354 PrintShaderInstructions(shader, stdout);
355 }
356 if (Options.OutputFile) {
357 fclose(stdout);
358 }
359 }
360
361 return 0;
362}