blob: 62a366858c4e49ddc12fe945f74cc731178ba7c0 [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;
75};
76
77static struct options Options;
78
79
80/**
81 * GLSL compiler driver context. (kind of an artificial thing for now)
82 */
83struct compiler_context
84{
85 GLcontext MesaContext;
86 int foo;
87};
88
89typedef struct compiler_context CompilerContext;
90
91
92
93static void
94UpdateState(GLcontext *ctx, GLuint new_state)
95{
96 /* easy - just propogate */
97 _swrast_InvalidateState( ctx, new_state );
98 _swsetup_InvalidateState( ctx, new_state );
Briancc153542007-02-17 09:15:39 -070099 _tnl_InvalidateState( ctx, new_state );
Brianbc18ac42007-02-22 16:29:25 -0700100 _vbo_InvalidateState( ctx, new_state );
Briancc153542007-02-17 09:15:39 -0700101}
102
103
104
105static GLboolean
106CreateContext(void)
107{
108 struct dd_function_table ddFuncs;
109 GLvisual *vis;
110 GLframebuffer *buf;
111 GLcontext *ctx;
112 CompilerContext *cc;
113
114 vis = _mesa_create_visual(GL_TRUE, GL_FALSE, GL_FALSE, /* RGB */
115 8, 8, 8, 8, /* color */
116 0, 0, 0, /* z, stencil */
117 0, 0, 0, 0, 1); /* accum */
118 buf = _mesa_create_framebuffer(vis);
119
120 cc = _mesa_calloc(sizeof(*cc));
121 if (!vis || !buf || !cc) {
122 if (vis)
123 _mesa_destroy_visual(vis);
124 if (buf)
125 _mesa_destroy_framebuffer(buf);
126 return GL_FALSE;
127 }
128
129 _mesa_init_driver_functions(&ddFuncs);
130 ddFuncs.GetString = NULL;/*get_string;*/
131 ddFuncs.UpdateState = UpdateState;
132 ddFuncs.GetBufferSize = NULL;
133
134 ctx = &cc->MesaContext;
135 _mesa_initialize_context(ctx, vis, NULL, &ddFuncs, cc);
136 _mesa_enable_sw_extensions(ctx);
137
138 if (!_swrast_CreateContext( ctx ) ||
Brianbc18ac42007-02-22 16:29:25 -0700139 !_vbo_CreateContext( ctx ) ||
Briancc153542007-02-17 09:15:39 -0700140 !_tnl_CreateContext( ctx ) ||
141 !_swsetup_CreateContext( ctx )) {
142 _mesa_destroy_visual(vis);
143 _mesa_free_context_data(ctx);
144 _mesa_free(cc);
145 return GL_FALSE;
146 }
147 TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
148 _swsetup_Wakeup( ctx );
149
150 _mesa_make_current(ctx, buf, buf);
151
152 return GL_TRUE;
153}
154
155
156static void
157LoadAndCompileShader(GLuint shader, const char *text)
158{
159 GLint stat;
160 _mesa_ShaderSourceARB(shader, 1, (const GLchar **) &text, NULL);
161 _mesa_CompileShaderARB(shader);
162 _mesa_GetShaderiv(shader, GL_COMPILE_STATUS, &stat);
163 if (!stat) {
164 GLchar log[1000];
165 GLsizei len;
166 _mesa_GetShaderInfoLog(shader, 1000, &len, log);
167 fprintf(stderr, "%s: problem compiling shader: %s\n", Prog, log);
168 exit(1);
169 }
170 else {
171 printf("Shader compiled OK\n");
172 }
173}
174
175
176/**
177 * Read a shader from a file.
178 */
179static void
180ReadShader(GLuint shader, const char *filename)
181{
182 const int max = 100*1000;
183 int n;
184 char *buffer = (char*) malloc(max);
185 FILE *f = fopen(filename, "r");
186 if (!f) {
187 fprintf(stderr, "%s: Unable to open shader file %s\n", Prog, filename);
188 exit(1);
189 }
190
191 n = fread(buffer, 1, max, f);
192 /*
193 printf("%s: read %d bytes from shader file %s\n", Prog, n, filename);
194 */
195 if (n > 0) {
196 buffer[n] = 0;
197 LoadAndCompileShader(shader, buffer);
198 }
199
200 fclose(f);
201 free(buffer);
202}
203
204
205#if 0
206static void
207CheckLink(GLuint prog)
208{
209 GLint stat;
210 _mesa_GetProgramiv(prog, GL_LINK_STATUS, &stat);
211 if (!stat) {
212 GLchar log[1000];
213 GLsizei len;
214 _mesa_GetProgramInfoLog(prog, 1000, &len, log);
215 fprintf(stderr, "%s: Linker error:\n%s\n", Prog, log);
216 }
217 else {
218 fprintf(stderr, "%s: Link success!\n", Prog);
219 }
220}
221#endif
222
223
224static void
225PrintShaderInstructions(GLuint shader, FILE *f)
226{
227 GET_CURRENT_CONTEXT(ctx);
228 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
229 GLuint i;
230
231 for (i = 0; i < sh->NumPrograms; i++) {
232 struct gl_program *prog = sh->Programs[i];
233 _mesa_print_program_opt(prog, Options.Mode, Options.LineNumbers);
234 }
235}
236
237
238static GLuint
239CompileShader(const char *filename, GLenum type)
240{
241 GLuint shader;
242
243 assert(type == GL_FRAGMENT_SHADER ||
244 type == GL_VERTEX_SHADER);
245
246 shader = _mesa_CreateShader(type);
247 ReadShader(shader, filename);
248
249 return shader;
250}
251
252
253static void
254Usage(void)
255{
256 printf("Mesa GLSL stand-alone compiler\n");
257 printf("Usage:\n");
258 printf(" --vs FILE vertex shader input filename\n");
259 printf(" --fs FILE fragment shader input filename\n");
260 printf(" --arb emit ARB-style instructions (the default)\n");
261 printf(" --nv emit NV-style instructions\n");
262 printf(" --debug emit debug-style instructions\n");
263 printf(" --number, -n emit line numbers\n");
264 printf(" --output, -o FILE output filename\n");
265 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;
279
Brianbc18ac42007-02-22 16:29:25 -0700280 if (argc == 1) {
281 Usage();
282 exit(0);
283 }
284
Briancc153542007-02-17 09:15:39 -0700285 for (i = 1; i < argc; i++) {
286 if (strcmp(argv[i], "--vs") == 0) {
287 Options.VertFile = argv[i + 1];
288 i++;
289 }
290 else if (strcmp(argv[i], "--fs") == 0) {
291 Options.FragFile = argv[i + 1];
292 i++;
293 }
294 else if (strcmp(argv[i], "--arb") == 0) {
295 Options.Mode = PROG_PRINT_ARB;
296 }
297 else if (strcmp(argv[i], "--nv") == 0) {
298 Options.Mode = PROG_PRINT_NV;
299 }
300 else if (strcmp(argv[i], "--debug") == 0) {
301 Options.Mode = PROG_PRINT_DEBUG;
302 }
303 else if (strcmp(argv[i], "--number") == 0 ||
304 strcmp(argv[i], "-n") == 0) {
305 Options.LineNumbers = GL_TRUE;
306 }
307 else if (strcmp(argv[i], "--output") == 0 ||
308 strcmp(argv[i], "-o") == 0) {
309 Options.OutputFile = argv[i + 1];
310 i++;
311 }
312 else if (strcmp(argv[i], "--help") == 0) {
313 Usage();
314 exit(0);
315 }
316 else {
317 printf("Unknown option: %s\n", argv[i]);
318 Usage();
319 exit(1);
320 }
321 }
322}
323
324
325int
326main(int argc, char *argv[])
327{
328 GLuint shader = 0;
329
330 if (!CreateContext()) {
331 fprintf(stderr, "%s: Failed to create compiler context\n", Prog);
332 exit(1);
333 }
334
335 ParseOptions(argc, argv);
336
337 if (Options.VertFile) {
338 shader = CompileShader(Options.VertFile, GL_VERTEX_SHADER);
339 }
340 else if (Options.FragFile) {
341 shader = CompileShader(Options.FragFile, GL_FRAGMENT_SHADER);
342 }
343
344 if (shader) {
345 if (Options.OutputFile) {
346 fclose(stdout);
347 /*stdout =*/ freopen(Options.OutputFile, "w", stdout);
348 }
349 if (stdout) {
350 PrintShaderInstructions(shader, stdout);
351 }
352 if (Options.OutputFile) {
353 fclose(stdout);
354 }
355 }
356
357 return 0;
358}