stand-alone GLSL compiler
authorBrian <brian@nostromo.localnet.net>
Sat, 17 Feb 2007 16:15:39 +0000 (09:15 -0700)
committerBrian <brian@nostromo.localnet.net>
Sat, 17 Feb 2007 16:15:39 +0000 (09:15 -0700)
src/mesa/drivers/glslcompiler/Makefile [new file with mode: 0644]
src/mesa/drivers/glslcompiler/glslcompiler [new file with mode: 0755]
src/mesa/drivers/glslcompiler/glslcompiler.c [new file with mode: 0644]

diff --git a/src/mesa/drivers/glslcompiler/Makefile b/src/mesa/drivers/glslcompiler/Makefile
new file mode 100644 (file)
index 0000000..858457d
--- /dev/null
@@ -0,0 +1,44 @@
+# Makefile for stand-alone GL-SL compiler
+
+TOP = ../../../..
+
+include $(TOP)/configs/current
+
+
+PROGRAM = glslcompiler
+
+OBJECTS = \
+       glslcompiler.o \
+       ../../glapi/glapi.o \
+       ../../glapi/glthread.o \
+       ../../main/dispatch.o \
+       ../common/driverfuncs.o \
+       ../../libmesa.a
+
+INCLUDES = \
+       -I$(TOP)/include \
+       -I$(TOP)/include/GL/internal \
+       -I$(TOP)/src/mesa \
+       -I$(TOP)/src/mesa/main \
+       -I$(TOP)/src/mesa/glapi \
+       -I$(TOP)/src/mesa/math \
+       -I$(TOP)/src/mesa/transform \
+       -I$(TOP)/src/mesa/shader \
+       -I$(TOP)/src/mesa/swrast \
+       -I$(TOP)/src/mesa/swrast_setup \
+
+
+default: $(PROGRAM)
+       $(INSTALL) $(PROGRAM) $(TOP)/bin
+
+
+glslcompiler: $(OBJECTS)
+       $(CC) $(OBJECTS) -lm -lpthread -o $@
+
+
+glslcompiler.o: glslcompiler.c
+       $(CC) -c $(CFLAGS) $(INCLUDES) glslcompiler.c -o $@
+
+
+clean:
+       rm -f *.o *~ $(PROGRAM)
diff --git a/src/mesa/drivers/glslcompiler/glslcompiler b/src/mesa/drivers/glslcompiler/glslcompiler
new file mode 100755 (executable)
index 0000000..a9d15e8
Binary files /dev/null and b/src/mesa/drivers/glslcompiler/glslcompiler differ
diff --git a/src/mesa/drivers/glslcompiler/glslcompiler.c b/src/mesa/drivers/glslcompiler/glslcompiler.c
new file mode 100644 (file)
index 0000000..a27f749
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5.3
+ *
+ * Copyright (C) 1999-2007  Brian Paul, Tungsten Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \mainpage
+ *
+ * Stand-alone Shading Language compiler.  
+ * Basically, a command-line program which accepts GLSL shaders and emits
+ * vertex/fragment programs (GPU instructions).
+ *
+ * This file is basically just a Mesa device driver but instead of building
+ * a shared library we build an executable.
+ *
+ * We can emit programs in three different formats:
+ *  1. ARB-style (GL_ARB_vertex/fragment_program)
+ *  2. NV-style (GL_NV_vertex/fragment_program)
+ *  3. debug-style (a slightly more sophisticated, internal format)
+ *
+ * Note that the ARB and NV program languages can't express all the
+ * features that might be used by a fragment program (examples being
+ * uniform and varying vars).  So, the ARB/NV programs that are
+ * emitted aren't always legal programs in those languages.
+ */
+
+
+#include "imports.h"
+#include "context.h"
+#include "extensions.h"
+#include "framebuffer.h"
+#include "shaders.h"
+#include "shader/shader_api.h"
+#include "shader/prog_print.h"
+#include "drivers/common/driverfuncs.h"
+#include "array_cache/acache.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+#include "swrast/swrast.h"
+#include "swrast/s_context.h"
+#include "swrast/s_triangle.h"
+#include "swrast_setup/swrast_setup.h"
+
+
+static const char *Prog = "glslcompiler";
+
+
+struct options {
+   GLboolean LineNumbers;
+   gl_prog_print_mode Mode;
+   const char *VertFile;
+   const char *FragFile;
+   const char *OutputFile;
+};
+
+static struct options Options;
+
+
+/**
+ * GLSL compiler driver context. (kind of an artificial thing for now)
+ */
+struct compiler_context
+{
+   GLcontext MesaContext;
+   int foo;
+};
+
+typedef struct compiler_context CompilerContext;
+
+
+
+static void
+UpdateState(GLcontext *ctx, GLuint new_state)
+{
+   /* easy - just propogate */
+   _swrast_InvalidateState( ctx, new_state );
+   _swsetup_InvalidateState( ctx, new_state );
+   _ac_InvalidateState( ctx, new_state );
+   _tnl_InvalidateState( ctx, new_state );
+}
+
+
+
+static GLboolean
+CreateContext(void)
+{
+   struct dd_function_table ddFuncs;
+   GLvisual *vis;
+   GLframebuffer *buf;
+   GLcontext *ctx;
+   CompilerContext *cc;
+
+   vis = _mesa_create_visual(GL_TRUE, GL_FALSE, GL_FALSE, /* RGB */
+                             8, 8, 8, 8,  /* color */
+                             0, 0, 0,  /* z, stencil */
+                             0, 0, 0, 0, 1);  /* accum */
+   buf = _mesa_create_framebuffer(vis);
+
+   cc = _mesa_calloc(sizeof(*cc));
+   if (!vis || !buf || !cc) {
+      if (vis)
+         _mesa_destroy_visual(vis);
+      if (buf)
+         _mesa_destroy_framebuffer(buf);
+      return GL_FALSE;
+   }
+
+   _mesa_init_driver_functions(&ddFuncs);
+   ddFuncs.GetString = NULL;/*get_string;*/
+   ddFuncs.UpdateState = UpdateState;
+   ddFuncs.GetBufferSize = NULL;
+
+   ctx = &cc->MesaContext;
+   _mesa_initialize_context(ctx, vis, NULL, &ddFuncs, cc);
+   _mesa_enable_sw_extensions(ctx);
+
+   if (!_swrast_CreateContext( ctx ) ||
+       !_ac_CreateContext( ctx ) ||
+       !_tnl_CreateContext( ctx ) ||
+       !_swsetup_CreateContext( ctx )) {
+      _mesa_destroy_visual(vis);
+      _mesa_free_context_data(ctx);
+      _mesa_free(cc);
+      return GL_FALSE;
+   }
+   TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline;
+   _swsetup_Wakeup( ctx );
+
+   _mesa_make_current(ctx, buf, buf);
+
+   return GL_TRUE;
+}
+
+
+static void
+LoadAndCompileShader(GLuint shader, const char *text)
+{
+   GLint stat;
+   _mesa_ShaderSourceARB(shader, 1, (const GLchar **) &text, NULL);
+   _mesa_CompileShaderARB(shader);
+   _mesa_GetShaderiv(shader, GL_COMPILE_STATUS, &stat);
+   if (!stat) {
+      GLchar log[1000];
+      GLsizei len;
+      _mesa_GetShaderInfoLog(shader, 1000, &len, log);
+      fprintf(stderr, "%s: problem compiling shader: %s\n", Prog, log);
+      exit(1);
+   }
+   else {
+      printf("Shader compiled OK\n");
+   }
+}
+
+
+/**
+ * Read a shader from a file.
+ */
+static void
+ReadShader(GLuint shader, const char *filename)
+{
+   const int max = 100*1000;
+   int n;
+   char *buffer = (char*) malloc(max);
+   FILE *f = fopen(filename, "r");
+   if (!f) {
+      fprintf(stderr, "%s: Unable to open shader file %s\n", Prog, filename);
+      exit(1);
+   }
+
+   n = fread(buffer, 1, max, f);
+   /*
+   printf("%s: read %d bytes from shader file %s\n", Prog, n, filename);
+   */
+   if (n > 0) {
+      buffer[n] = 0;
+      LoadAndCompileShader(shader, buffer);
+   }
+
+   fclose(f);
+   free(buffer);
+}
+
+
+#if 0
+static void
+CheckLink(GLuint prog)
+{
+   GLint stat;
+   _mesa_GetProgramiv(prog, GL_LINK_STATUS, &stat);
+   if (!stat) {
+      GLchar log[1000];
+      GLsizei len;
+      _mesa_GetProgramInfoLog(prog, 1000, &len, log);
+      fprintf(stderr, "%s: Linker error:\n%s\n", Prog, log);
+   }
+   else {
+      fprintf(stderr, "%s: Link success!\n", Prog);
+   }
+}
+#endif
+
+
+static void
+PrintShaderInstructions(GLuint shader, FILE *f)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
+   GLuint i;
+
+   for (i = 0; i < sh->NumPrograms; i++) {
+      struct gl_program *prog = sh->Programs[i];
+      _mesa_print_program_opt(prog, Options.Mode, Options.LineNumbers);
+   }
+}
+
+
+static GLuint
+CompileShader(const char *filename, GLenum type)
+{
+   GLuint shader;
+
+   assert(type == GL_FRAGMENT_SHADER ||
+          type == GL_VERTEX_SHADER);
+
+   shader = _mesa_CreateShader(type);
+   ReadShader(shader, filename);
+
+   return shader;
+}
+
+
+static void
+Usage(void)
+{
+   printf("Mesa GLSL stand-alone compiler\n");
+   printf("Usage:\n");
+   printf("  --vs FILE          vertex shader input filename\n");
+   printf("  --fs FILE          fragment shader input filename\n");
+   printf("  --arb              emit ARB-style instructions (the default)\n");
+   printf("  --nv               emit NV-style instructions\n");
+   printf("  --debug            emit debug-style instructions\n");
+   printf("  --number, -n       emit line numbers\n");
+   printf("  --output, -o FILE  output filename\n");
+   printf("  --help             display this information\n");
+}
+
+
+static void
+ParseOptions(int argc, char *argv[])
+{
+   int i;
+
+   Options.LineNumbers = GL_FALSE;
+   Options.Mode = PROG_PRINT_ARB;
+   Options.VertFile = NULL;
+   Options.FragFile = NULL;
+   Options.OutputFile = NULL;
+
+   for (i = 1; i < argc; i++) {
+      if (strcmp(argv[i], "--vs") == 0) {
+         Options.VertFile = argv[i + 1];
+         i++;
+      }
+      else if (strcmp(argv[i], "--fs") == 0) {
+         Options.FragFile = argv[i + 1];
+         i++;
+      }
+      else if (strcmp(argv[i], "--arb") == 0) {
+         Options.Mode = PROG_PRINT_ARB;
+      }
+      else if (strcmp(argv[i], "--nv") == 0) {
+         Options.Mode = PROG_PRINT_NV;
+      }
+      else if (strcmp(argv[i], "--debug") == 0) {
+         Options.Mode = PROG_PRINT_DEBUG;
+      }
+      else if (strcmp(argv[i], "--number") == 0 ||
+               strcmp(argv[i], "-n") == 0) {
+         Options.LineNumbers = GL_TRUE;
+      }
+      else if (strcmp(argv[i], "--output") == 0 ||
+               strcmp(argv[i], "-o") == 0) {
+         Options.OutputFile = argv[i + 1];
+         i++;
+      }
+      else if (strcmp(argv[i], "--help") == 0) {
+         Usage();
+         exit(0);
+      }
+      else {
+         printf("Unknown option: %s\n", argv[i]);
+         Usage();
+         exit(1);
+      }
+   }
+}
+
+
+int
+main(int argc, char *argv[])
+{
+   GLuint shader = 0;
+
+   if (!CreateContext()) {
+      fprintf(stderr, "%s: Failed to create compiler context\n", Prog);
+      exit(1);
+   }
+
+   ParseOptions(argc, argv);
+
+   if (Options.VertFile) {
+      shader = CompileShader(Options.VertFile, GL_VERTEX_SHADER);
+   }
+   else if (Options.FragFile) {
+      shader = CompileShader(Options.FragFile, GL_FRAGMENT_SHADER);
+   }
+
+   if (shader) {
+      if (Options.OutputFile) {
+         fclose(stdout);
+         /*stdout =*/ freopen(Options.OutputFile, "w", stdout);
+      }
+      if (stdout) {
+         PrintShaderInstructions(shader, stdout);
+      }
+      if (Options.OutputFile) {
+         fclose(stdout);
+      }
+   }
+
+   return 0;
+}