Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1901 serge 1
/*
2
 * Copyright © 2008, 2009 Intel Corporation
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the "Software"),
6
 * to deal in the Software without restriction, including without limitation
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice (including the next
12
 * paragraph) shall be included in all copies or substantial portions of the
13
 * Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
 * DEALINGS IN THE SOFTWARE.
22
 */
23
#include 
24
#include 
25
#include 
26
 
27
#include 
28
#include 
29
#include 
30
#include 
31
 
32
#include "ast.h"
33
#include "glsl_parser_extras.h"
34
#include "glsl_parser.h"
35
#include "ir_optimization.h"
36
#include "ir_print_visitor.h"
37
#include "program.h"
38
#include "loop_analysis.h"
39
 
40
extern "C" struct gl_shader *
41
_mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type);
42
 
43
extern "C" void
44
_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
45
                       struct gl_shader *sh);
46
 
47
/* Copied from shader_api.c for the stand-alone compiler.
48
 */
49
void
50
_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
51
                       struct gl_shader *sh)
52
{
53
   *ptr = sh;
54
}
55
 
56
struct gl_shader *
57
_mesa_new_shader(struct gl_context *ctx, GLuint name, GLenum type)
58
{
59
   struct gl_shader *shader;
60
 
61
   (void) ctx;
62
 
63
   assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
64
   shader = rzalloc(NULL, struct gl_shader);
65
   if (shader) {
66
      shader->Type = type;
67
      shader->Name = name;
68
      shader->RefCount = 1;
69
   }
70
   return shader;
71
}
72
 
73
static void
74
initialize_context(struct gl_context *ctx, gl_api api)
75
{
76
   memset(ctx, 0, sizeof(*ctx));
77
 
78
   ctx->API = api;
79
 
80
   ctx->Extensions.ARB_ES2_compatibility = GL_TRUE;
81
   ctx->Extensions.ARB_draw_buffers = GL_TRUE;
82
   ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE;
83
   ctx->Extensions.EXT_texture_array = GL_TRUE;
84
   ctx->Extensions.NV_texture_rectangle = GL_TRUE;
85
 
86
   /* GLSL 1.30 isn't fully supported, but we need to advertise 1.30 so that
87
    * the built-in functions for 1.30 can be built.
88
    */
89
   ctx->Const.GLSLVersion = 130;
90
 
91
   /* 1.10 minimums. */
92
   ctx->Const.MaxLights = 8;
93
   ctx->Const.MaxClipPlanes = 8;
94
   ctx->Const.MaxTextureUnits = 2;
95
 
96
   /* More than the 1.10 minimum to appease parser tests taken from
97
    * apps that (hopefully) already checked the number of coords.
98
    */
99
   ctx->Const.MaxTextureCoordUnits = 4;
100
 
101
   ctx->Const.VertexProgram.MaxAttribs = 16;
102
   ctx->Const.VertexProgram.MaxUniformComponents = 512;
103
   ctx->Const.MaxVarying = 8;
104
   ctx->Const.MaxVertexTextureImageUnits = 0;
105
   ctx->Const.MaxCombinedTextureImageUnits = 2;
106
   ctx->Const.MaxTextureImageUnits = 2;
107
   ctx->Const.FragmentProgram.MaxUniformComponents = 64;
108
 
109
   ctx->Const.MaxDrawBuffers = 2;
110
 
111
   ctx->Driver.NewShader = _mesa_new_shader;
112
}
113
 
114
/* Returned string will have 'ctx' as its ralloc owner. */
115
static char *
116
load_text_file(void *ctx, const char *file_name)
117
{
118
	char *text = NULL;
119
	struct stat st;
120
	ssize_t total_read = 0;
121
	int fd = open(file_name, O_RDONLY);
122
 
123
	if (fd < 0) {
124
		return NULL;
125
	}
126
 
127
	if (fstat(fd, & st) == 0) {
128
	   text = (char *) ralloc_size(ctx, st.st_size + 1);
129
		if (text != NULL) {
130
			do {
131
				ssize_t bytes = read(fd, text + total_read,
132
						     st.st_size - total_read);
133
				if (bytes < 0) {
134
					free(text);
135
					text = NULL;
136
					break;
137
				}
138
 
139
				if (bytes == 0) {
140
					break;
141
				}
142
 
143
				total_read += bytes;
144
			} while (total_read < st.st_size);
145
 
146
			text[total_read] = '\0';
147
		}
148
	}
149
 
150
	close(fd);
151
 
152
	return text;
153
}
154
 
155
int glsl_es = 0;
156
int dump_ast = 0;
157
int dump_hir = 0;
158
int dump_lir = 0;
159
int do_link = 0;
160
 
161
const struct option compiler_opts[] = {
162
   { "glsl-es",  0, &glsl_es,  1 },
163
   { "dump-ast", 0, &dump_ast, 1 },
164
   { "dump-hir", 0, &dump_hir, 1 },
165
   { "dump-lir", 0, &dump_lir, 1 },
166
   { "link",     0, &do_link,  1 },
167
   { NULL, 0, NULL, 0 }
168
};
169
 
170
/**
171
 * \brief Print proper usage and exit with failure.
172
 */
173
void
174
usage_fail(const char *name)
175
{
176
 
177
   const char *header =
178
      "usage: %s [options] \n"
179
      "\n"
180
      "Possible options are:\n";
181
   printf(header, name, name);
182
   for (const struct option *o = compiler_opts; o->name != 0; ++o) {
183
      printf("    --%s\n", o->name);
184
   }
185
   exit(EXIT_FAILURE);
186
}
187
 
188
 
189
void
190
compile_shader(struct gl_context *ctx, struct gl_shader *shader)
191
{
192
   struct _mesa_glsl_parse_state *state =
193
      new(shader) _mesa_glsl_parse_state(ctx, shader->Type, shader);
194
 
195
   const char *source = shader->Source;
196
   state->error = preprocess(state, &source, &state->info_log,
197
			     state->extensions, ctx->API);
198
 
199
   if (!state->error) {
200
      _mesa_glsl_lexer_ctor(state, source);
201
      _mesa_glsl_parse(state);
202
      _mesa_glsl_lexer_dtor(state);
203
   }
204
 
205
   if (dump_ast) {
206
      foreach_list_const(n, &state->translation_unit) {
207
	 ast_node *ast = exec_node_data(ast_node, n, link);
208
	 ast->print();
209
      }
210
      printf("\n\n");
211
   }
212
 
213
   shader->ir = new(shader) exec_list;
214
   if (!state->error && !state->translation_unit.is_empty())
215
      _mesa_ast_to_hir(shader->ir, state);
216
 
217
   /* Print out the unoptimized IR. */
218
   if (!state->error && dump_hir) {
219
      validate_ir_tree(shader->ir);
220
      _mesa_print_ir(shader->ir, state);
221
   }
222
 
223
   /* Optimization passes */
224
   if (!state->error && !shader->ir->is_empty()) {
225
      bool progress;
226
      do {
227
	 progress = do_common_optimization(shader->ir, false, 32);
228
      } while (progress);
229
 
230
      validate_ir_tree(shader->ir);
231
   }
232
 
233
 
234
   /* Print out the resulting IR */
235
   if (!state->error && dump_lir) {
236
      _mesa_print_ir(shader->ir, state);
237
   }
238
 
239
   shader->symbols = state->symbols;
240
   shader->CompileStatus = !state->error;
241
   shader->Version = state->language_version;
242
   memcpy(shader->builtins_to_link, state->builtins_to_link,
243
	  sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link);
244
   shader->num_builtins_to_link = state->num_builtins_to_link;
245
 
246
   if (shader->InfoLog)
247
      ralloc_free(shader->InfoLog);
248
 
249
   shader->InfoLog = state->info_log;
250
 
251
   /* Retain any live IR, but trash the rest. */
252
   reparent_ir(shader->ir, shader);
253
 
254
   ralloc_free(state);
255
 
256
   return;
257
}
258
 
259
int
260
main(int argc, char **argv)
261
{
262
   int status = EXIT_SUCCESS;
263
   struct gl_context local_ctx;
264
   struct gl_context *ctx = &local_ctx;
265
 
266
   int c;
267
   int idx = 0;
268
   while ((c = getopt_long(argc, argv, "", compiler_opts, &idx)) != -1)
269
      /* empty */ ;
270
 
271
 
272
   if (argc <= optind)
273
      usage_fail(argv[0]);
274
 
275
   initialize_context(ctx, (glsl_es) ? API_OPENGLES2 : API_OPENGL);
276
 
277
   struct gl_shader_program *whole_program;
278
 
279
   whole_program = rzalloc (NULL, struct gl_shader_program);
280
   assert(whole_program != NULL);
281
 
282
   for (/* empty */; argc > optind; optind++) {
283
      whole_program->Shaders =
284
	 reralloc(whole_program, whole_program->Shaders,
285
		  struct gl_shader *, whole_program->NumShaders + 1);
286
      assert(whole_program->Shaders != NULL);
287
 
288
      struct gl_shader *shader = rzalloc(whole_program, gl_shader);
289
 
290
      whole_program->Shaders[whole_program->NumShaders] = shader;
291
      whole_program->NumShaders++;
292
 
293
      const unsigned len = strlen(argv[optind]);
294
      if (len < 6)
295
	 usage_fail(argv[0]);
296
 
297
      const char *const ext = & argv[optind][len - 5];
298
      if (strncmp(".vert", ext, 5) == 0)
299
	 shader->Type = GL_VERTEX_SHADER;
300
      else if (strncmp(".geom", ext, 5) == 0)
301
	 shader->Type = GL_GEOMETRY_SHADER;
302
      else if (strncmp(".frag", ext, 5) == 0)
303
	 shader->Type = GL_FRAGMENT_SHADER;
304
      else
305
	 usage_fail(argv[0]);
306
 
307
      shader->Source = load_text_file(whole_program, argv[optind]);
308
      if (shader->Source == NULL) {
309
	 printf("File \"%s\" does not exist.\n", argv[optind]);
310
	 exit(EXIT_FAILURE);
311
      }
312
 
313
      compile_shader(ctx, shader);
314
 
315
      if (!shader->CompileStatus) {
316
	 printf("Info log for %s:\n%s\n", argv[optind], shader->InfoLog);
317
	 status = EXIT_FAILURE;
318
	 break;
319
      }
320
   }
321
 
322
   if ((status == EXIT_SUCCESS) && do_link)  {
323
      link_shaders(ctx, whole_program);
324
      status = (whole_program->LinkStatus) ? EXIT_SUCCESS : EXIT_FAILURE;
325
 
326
      if (strlen(whole_program->InfoLog) > 0)
327
	 printf("Info log for linking:\n%s\n", whole_program->InfoLog);
328
   }
329
 
330
   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++)
331
      ralloc_free(whole_program->_LinkedShaders[i]);
332
 
333
   ralloc_free(whole_program);
334
   _mesa_glsl_release_types();
335
   _mesa_glsl_release_functions();
336
 
337
   return status;
338
}