+++ /dev/null
-/*
- * Mesa 3-D graphics library
- * Version: 6.5
- *
- * Copyright (C) 1999-2005 Brian Paul 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.
- */
-
-#define DEBUG_FP 0
-
-/**
- * \file arbfragparse.c
- * ARB_fragment_program parser.
- * \author Karl Rasche
- */
-
-#include "glheader.h"
-#include "imports.h"
-#include "program.h"
-#include "arbprogparse.h"
-#include "arbfragparse.h"
-
-
-void
-_mesa_parse_arb_fragment_program(GLcontext * ctx, GLenum target,
- const GLubyte * str, GLsizei len,
- struct fragment_program *program)
-{
- GLuint i;
- struct arb_program ap;
- struct prog_instruction *newInstructions;
- (void) target;
-
- /* set the program target before parsing */
- ap.Base.Target = GL_FRAGMENT_PROGRAM_ARB;
-
- if (!_mesa_parse_arb_program(ctx, str, len, &ap)) {
- /* Error in the program. Just return. */
- return;
- }
-
- /* Copy the relevant contents of the arb_program struct into the
- * fragment_program struct.
- */
- /* copy instruction buffer */
- newInstructions = (struct prog_instruction *)
- _mesa_malloc(ap.Base.NumInstructions * sizeof(struct prog_instruction));
- if (!newInstructions) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
- return;
- }
- _mesa_memcpy(newInstructions, ap.FPInstructions,
- ap.Base.NumInstructions * sizeof(struct prog_instruction));
- if (program->Base.Instructions)
- _mesa_free(program->Base.Instructions);
- program->Base.Instructions = newInstructions;
- program->Base.String = ap.Base.String;
- program->Base.NumInstructions = ap.Base.NumInstructions;
- program->Base.NumTemporaries = ap.Base.NumTemporaries;
- program->Base.NumParameters = ap.Base.NumParameters;
- program->Base.NumAttributes = ap.Base.NumAttributes;
- program->Base.NumAddressRegs = ap.Base.NumAddressRegs;
- program->NumAluInstructions = ap.NumAluInstructions;
- program->NumTexInstructions = ap.NumTexInstructions;
- program->NumTexIndirections = ap.NumTexIndirections;
- program->Base.InputsRead = ap.Base.InputsRead;
- program->Base.OutputsWritten = ap.Base.OutputsWritten;
- for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
- program->TexturesUsed[i] = ap.TexturesUsed[i];
-
- if (program->Base.Parameters) {
- /* free previous program's parameters */
- _mesa_free_parameter_list(program->Base.Parameters);
- }
- program->Base.Parameters = ap.Base.Parameters;
- program->FogOption = ap.FogOption;
-
-#if DEBUG_FP
- _mesa_print_program(&program.Base);
-#endif
-}
#include "arbprogparse.h"
#include "grammar_mesa.h"
#include "program.h"
-#include "get.h"
+#include "context.h"
+#include "mtypes.h"
+#include "program_instruction.h"
+
+
+#define MAX_INSTRUCTIONS 256
+
+
+/**
+ * This is basically a union of the vertex_program and fragment_program
+ * structs that we can use to parse the program into
+ *
+ * XXX we can probably get rid of this entirely someday.
+ */
+struct arb_program
+{
+ struct program Base;
+
+ GLuint Position; /* Just used for error reporting while parsing */
+ GLuint MajorVersion;
+ GLuint MinorVersion;
+
+ /* ARB_vertex_progmra options */
+ GLboolean HintPositionInvariant;
+
+ /* ARB_fragment_progmra options */
+ GLenum PrecisionOption; /* GL_DONT_CARE, GL_NICEST or GL_FASTEST */
+ GLenum FogOption; /* GL_NONE, GL_LINEAR, GL_EXP or GL_EXP2 */
+
+ /* ARB_fragment_program specifics */
+ GLbitfield TexturesUsed[MAX_TEXTURE_IMAGE_UNITS];
+ GLuint NumAluInstructions;
+ GLuint NumTexInstructions;
+ GLuint NumTexIndirections;
+
+ GLboolean UsesKill;
+};
+
#ifndef __extension__
#if !defined(__GNUC__) || (__GNUC__ < 2) || \
* \return 1 on error, 0 on success
*/
static GLint
-parse_arb_program(GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
+parse_instructions(GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
struct arb_program *Program)
{
const GLuint maxInst = (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB)
/* parse the current instruction */
if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
err = parse_fp_instruction (ctx, &inst, vc_head, Program,
- &Program->FPInstructions[Program->Base.NumInstructions]);
+ &Program->Base.Instructions[Program->Base.NumInstructions]);
}
else {
err = parse_vp_instruction (ctx, &inst, vc_head, Program,
- &Program->VPInstructions[Program->Base.NumInstructions]);
+ &Program->Base.Instructions[Program->Base.NumInstructions]);
}
/* increment instuction count */
}
/* Finally, tag on an OPCODE_END instruction */
- if (Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) {
- const GLuint numInst = Program->Base.NumInstructions;
- _mesa_init_instruction(Program->FPInstructions + numInst);
- Program->FPInstructions[numInst].Opcode = OPCODE_END;
- /* YYY Wrong Position in program, whatever, at least not random -> crash
- Program->Position = parse_position (&inst);
- */
- Program->FPInstructions[numInst].StringPos = Program->Position;
- }
- else {
+ {
const GLuint numInst = Program->Base.NumInstructions;
- _mesa_init_instruction(Program->VPInstructions + numInst);
- Program->VPInstructions[numInst].Opcode = OPCODE_END;
+ _mesa_init_instruction(Program->Base.Instructions + numInst);
+ Program->Base.Instructions[numInst].Opcode = OPCODE_END;
/* YYY Wrong Position in program, whatever, at least not random -> crash
Program->Position = parse_position (&inst);
*/
- Program->VPInstructions[numInst].StringPos = Program->Position;
+ Program->Base.Instructions[numInst].StringPos = Program->Position;
}
Program->Base.NumInstructions++;
;
-static int set_reg8 (GLcontext *ctx, grammar id, const byte *name, byte value)
+/**
+ * Set a grammar parameter.
+ * \param name the grammar parameter
+ * \param value the new parameter value
+ * \return 0 if OK, 1 if error
+ */
+static int
+set_reg8 (GLcontext *ctx, grammar id, const char *name, GLubyte value)
{
char error_msg[300];
GLint error_pos;
- if (grammar_set_reg8 (id, name, value))
+ if (grammar_set_reg8 (id, (const byte *) name, value))
return 0;
grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
return 1;
}
-static int extension_is_supported (const GLubyte *ext)
-{
- const GLubyte *extensions = _mesa_GetString(GL_EXTENSIONS);
- const GLubyte *end = extensions + _mesa_strlen ((const char *) extensions);
- const GLint ext_len = (GLint)_mesa_strlen ((const char *) ext);
- while (extensions < end)
- {
- const GLubyte *name_end = (const GLubyte *) _mesa_strstr ((const char *) extensions, " ");
- if (name_end == NULL)
- name_end = end;
- if (name_end - extensions == ext_len && _mesa_strncmp ((const char *) ext,
- (const char *) extensions, ext_len) == 0)
- return 1;
- extensions = name_end + 1;
- }
-
- return 0;
+/**
+ * Enable support for the given language option in the parser.
+ * \return 1 if OK, 0 if error
+ */
+static int
+enable_ext(GLcontext *ctx, grammar id, const char *name)
+{
+ return !set_reg8(ctx, id, name, 1);
}
-static int enable_ext (GLcontext *ctx, grammar id, const byte *name, const byte *extname)
+
+/**
+ * Enable parser extensions based on which OpenGL extensions are supported
+ * by this rendering context.
+ *
+ * \return GL_TRUE if OK, GL_FALSE if error.
+ */
+static GLboolean
+enable_parser_extensions(GLcontext *ctx, grammar id)
{
- if (extension_is_supported (extname))
- if (set_reg8 (ctx, id, name, 0x01))
- return 1;
- return 0;
+#if 0
+ /* These are not supported at this time */
+ if ((ctx->Extensions.ARB_vertex_blend ||
+ ctx->Extensions.EXT_vertex_weighting)
+ && !enable_ext(ctx, id, "point_parameters"))
+ return GL_FALSE;
+ if (ctx->Extensions.ARB_matrix_palette
+ && !enable_ext(ctx, id, "matrix_palette"))
+ return GL_FALSE;
+ if (ctx->Extensions.ARB_fragment_program_shadow
+ && !enable_ext(ctx, id, "fragment_program_shadow"))
+ return GL_FALSE;
+#endif
+ if (ctx->Extensions.EXT_point_parameters
+ && !enable_ext(ctx, id, "point_parameters"))
+ return GL_FALSE;
+ if (ctx->Extensions.EXT_secondary_color
+ && !enable_ext(ctx, id, "secondary_color"))
+ return GL_FALSE;
+ if (ctx->Extensions.EXT_fog_coord
+ && !enable_ext(ctx, id, "fog_coord"))
+ return GL_FALSE;
+ if (ctx->Extensions.NV_texture_rectangle
+ && !enable_ext(ctx, id, "texture_rectangle"))
+ return GL_FALSE;
+ if (ctx->Extensions.ARB_draw_buffers
+ && !enable_ext(ctx, id, "draw_buffers"))
+ return GL_FALSE;
+
+ return GL_TRUE;
}
+
/**
* This kicks everything off.
*
* \param program - The arb_program struct to return all the parsed info in
* \return GL_TRUE on sucess, GL_FALSE on error
*/
-GLboolean
-_mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len,
- struct arb_program * program)
+static GLboolean
+_mesa_parse_arb_program(GLcontext *ctx, GLenum target,
+ const GLubyte *str, GLsizei len,
+ struct arb_program *program)
{
GLint a, err, error_pos;
char error_msg[300];
GLubyte *strz = NULL;
static int arbprogram_syn_is_ok = 0; /* XXX temporary */
+ /* set the program target before parsing */
+ program->Base.Target = target;
+
/* Reset error state */
_mesa_set_program_error(ctx, -1, NULL);
-#if DEBUG_PARSING
- fprintf (stderr, "Loading grammar text!\n");
-#endif
-
- /* check if the arb_grammar_text (arbprogram.syn) is syntactically correct */
+ /* check if arb_grammar_text (arbprogram.syn) is syntactically correct */
if (!arbprogram_syn_is_ok) {
+ /* One-time initialization of parsing system */
grammar grammar_syn_id;
- GLint err;
GLuint parsed_len;
- byte *parsed;
grammar_syn_id = grammar_load_from_text ((byte *) core_grammar_text);
if (grammar_syn_id == 0) {
grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
+ /* XXX this is not a GL error - it's an implementation bug! - FIX */
_mesa_set_program_error (ctx, error_pos, error_msg);
_mesa_error (ctx, GL_INVALID_OPERATION,
- "Error loading grammar rule set");
+ "glProgramStringARB(Error loading grammar rule set)");
return GL_FALSE;
}
- err = grammar_check (grammar_syn_id, (byte *) arb_grammar_text, &parsed, &parsed_len);
+ err = !grammar_check(grammar_syn_id, (byte *) arb_grammar_text,
+ &parsed, &parsed_len);
/* NOTE: we can't destroy grammar_syn_id right here because
* grammar_destroy() can reset the last error
*/
- if (err == 0) {
+ if (err) {
+ /* XXX this is not a GL error - it's an implementation bug! - FIX */
grammar_get_last_error ((byte *) error_msg, 300, &error_pos);
_mesa_set_program_error (ctx, error_pos, error_msg);
- _mesa_error (ctx, GL_INVALID_OPERATION, "Error loading grammar rule set");
-
+ _mesa_error (ctx, GL_INVALID_OPERATION,
+ "glProgramString(Error loading grammar rule set");
grammar_destroy (grammar_syn_id);
return GL_FALSE;
}
/* create the grammar object */
arbprogram_syn_id = grammar_load_from_text ((byte *) arb_grammar_text);
if (arbprogram_syn_id == 0) {
+ /* XXX this is not a GL error - it's an implementation bug! - FIX */
grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
_mesa_set_program_error (ctx, error_pos, error_msg);
_mesa_error (ctx, GL_INVALID_OPERATION,
- "Error loading grammer rule set");
+ "glProgramString(Error loading grammer rule set)");
return GL_FALSE;
}
return GL_FALSE;
}
- /* Enable all active extensions */
- if (enable_ext (ctx, arbprogram_syn_id,
- (byte *) "vertex_blend", (byte *) "GL_ARB_vertex_blend") ||
- enable_ext (ctx, arbprogram_syn_id,
- (byte *) "vertex_blend", (byte *) "GL_EXT_vertex_weighting") ||
- enable_ext (ctx, arbprogram_syn_id,
- (byte *) "matrix_palette", (byte *) "GL_ARB_matrix_palette") ||
- enable_ext (ctx, arbprogram_syn_id,
- (byte *) "point_parameters", (byte *) "GL_ARB_point_parameters") ||
- enable_ext (ctx, arbprogram_syn_id,
- (byte *) "point_parameters", (byte *) "GL_EXT_point_parameters") ||
- enable_ext (ctx, arbprogram_syn_id,
- (byte *) "secondary_color", (byte *) "GL_EXT_secondary_color") ||
- enable_ext (ctx, arbprogram_syn_id,
- (byte *) "fog_coord", (byte *) "GL_EXT_fog_coord") ||
- enable_ext (ctx, arbprogram_syn_id,
- (byte *) "texture_rectangle", (byte *) "GL_ARB_texture_rectangle") ||
- enable_ext (ctx, arbprogram_syn_id,
- (byte *) "texture_rectangle", (byte *) "GL_EXT_texture_rectangle") ||
- enable_ext (ctx, arbprogram_syn_id,
- (byte *) "texture_rectangle", (byte *) "GL_NV_texture_rectangle") ||
- enable_ext (ctx, arbprogram_syn_id,
- (byte *) "fragment_program_shadow", (byte *) "GL_ARB_fragment_program_shadow") ||
- enable_ext (ctx, arbprogram_syn_id,
- (byte *) "draw_buffers", (byte *) "GL_ARB_draw_buffers")) {
- grammar_destroy (arbprogram_syn_id);
+ if (!enable_parser_extensions(ctx, arbprogram_syn_id)) {
+ grammar_destroy(arbprogram_syn_id);
return GL_FALSE;
}
/* check for NULL character occurences */
{
- int i;
- for (i = 0; i < len; i++)
+ GLint i;
+ for (i = 0; i < len; i++) {
if (str[i] == '\0') {
_mesa_set_program_error (ctx, i, "invalid character");
- _mesa_error (ctx, GL_INVALID_OPERATION, "Lexical Error");
-
+ _mesa_error (ctx, GL_INVALID_OPERATION,
+ "glProgramStringARB(illegal character)");
grammar_destroy (arbprogram_syn_id);
return GL_FALSE;
}
+ }
}
/* copy the program string to a null-terminated string */
strz = (GLubyte *) _mesa_malloc (len + 1);
if (!strz) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glprogramStringARB");
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
+ grammar_destroy (arbprogram_syn_id);
return GL_FALSE;
}
_mesa_memcpy (strz, str, len);
strz[len] = '\0';
-#if DEBUG_PARSING
- fprintf (stderr, "Checking Grammar!\n");
-#endif
/* do a fast check on program string - initial production buffer is 4K */
- err = grammar_fast_check (arbprogram_syn_id, strz, &parsed, &parsed_len, 0x1000);
+ err = !grammar_fast_check(arbprogram_syn_id, strz,
+ &parsed, &parsed_len, 0x1000);
/* Syntax parse error */
- if (err == 0) {
- _mesa_free (strz);
+ if (err) {
+ _mesa_free(strz);
grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
_mesa_set_program_error (ctx, error_pos, error_msg);
- _mesa_error (ctx, GL_INVALID_OPERATION, "glprogramStringARB(syntax error)");
+ _mesa_error (ctx, GL_INVALID_OPERATION,
+ "glProgramStringARB(syntax error)");
/* useful for debugging */
#if DEBUG_PARSING
return GL_FALSE;
}
-#if DEBUG_PARSING
- fprintf (stderr, "Destroying grammer dict [parse retval: %d]\n", err);
-#endif
grammar_destroy (arbprogram_syn_id);
+ /*
+ * Program string is syntactically correct at this point
+ * Parse the tokenized version of the program now, generating
+ * vertex/fragment program instructions.
+ */
+
/* Initialize the arb_program struct */
program->Base.String = strz;
+ program->Base.Instructions = (struct prog_instruction *)
+ _mesa_malloc(MAX_INSTRUCTIONS * sizeof(struct prog_instruction));
program->Base.NumInstructions =
program->Base.NumTemporaries =
program->Base.NumParameters =
program->NumAluInstructions =
program->NumTexInstructions =
program->NumTexIndirections = 0;
-
program->UsesKill = 0;
vc_head = NULL;
else {
/* ignore program target */
inst++;
-
- err = parse_arb_program (ctx, inst, &vc_head, program);
-#if DEBUG_PARSING
- fprintf (stderr, "Symantic analysis returns %d [1 is bad!]\n", err);
-#endif
+ err = parse_instructions(ctx, inst, &vc_head, program);
}
/*debug_variables(ctx, vc_head, program); */
var_cache_destroy (&vc_head);
_mesa_free (parsed);
-#if DEBUG_PARSING
- fprintf (stderr, "_mesa_parse_arb_program() done\n");
-#endif
+ /* Reallocate the instruction array from size [MAX_INSTRUCTIONS]
+ * to size [ap.Base.NumInstructions].
+ */
+ program->Base.Instructions = (struct prog_instruction *)
+ _mesa_realloc(program->Base.Instructions,
+ MAX_INSTRUCTIONS * sizeof(struct prog_instruction),/*orig*/
+ program->Base.NumInstructions * sizeof(struct prog_instruction));
+
return !err;
}
+
+
+
+void
+_mesa_parse_arb_fragment_program(GLcontext* ctx, GLenum target,
+ const GLvoid *str, GLsizei len,
+ struct fragment_program *program)
+{
+ struct arb_program ap;
+ GLuint i;
+
+ ASSERT(target == GL_FRAGMENT_PROGRAM_ARB);
+ if (!_mesa_parse_arb_program(ctx, target, str, len, &ap)) {
+ /* Error in the program. Just return. */
+ return;
+ }
+
+ /* Copy the relevant contents of the arb_program struct into the
+ * fragment_program struct.
+ */
+ program->Base.String = ap.Base.String;
+ program->Base.NumInstructions = ap.Base.NumInstructions;
+ program->Base.NumTemporaries = ap.Base.NumTemporaries;
+ program->Base.NumParameters = ap.Base.NumParameters;
+ program->Base.NumAttributes = ap.Base.NumAttributes;
+ program->Base.NumAddressRegs = ap.Base.NumAddressRegs;
+ program->NumAluInstructions = ap.NumAluInstructions;
+ program->NumTexInstructions = ap.NumTexInstructions;
+ program->NumTexIndirections = ap.NumTexIndirections;
+ program->Base.InputsRead = ap.Base.InputsRead;
+ program->Base.OutputsWritten = ap.Base.OutputsWritten;
+ for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
+ program->TexturesUsed[i] = ap.TexturesUsed[i];
+ program->FogOption = ap.FogOption;
+
+ if (program->Base.Instructions)
+ _mesa_free(program->Base.Instructions);
+ program->Base.Instructions = ap.Base.Instructions;
+
+ if (program->Base.Parameters)
+ _mesa_free_parameter_list(program->Base.Parameters);
+ program->Base.Parameters = ap.Base.Parameters;
+
+#if DEBUG_FP
+ _mesa_print_program(&program.Base);
+#endif
+}
+
+
+
+/**
+ * Parse the vertex program string. If success, update the given
+ * vertex_program object with the new program. Else, leave the vertex_program
+ * object unchanged.
+ */
+void
+_mesa_parse_arb_vertex_program(GLcontext *ctx, GLenum target,
+ const GLvoid *str, GLsizei len,
+ struct vertex_program *program)
+{
+ struct arb_program ap;
+
+ ASSERT(target == GL_VERTEX_PROGRAM_ARB);
+
+ if (!_mesa_parse_arb_program(ctx, target, str, len, &ap)) {
+ /* Error in the program. Just return. */
+ return;
+ }
+
+ /* Copy the relevant contents of the arb_program struct into the
+ * vertex_program struct.
+ */
+ program->Base.String = ap.Base.String;
+ program->Base.NumInstructions = ap.Base.NumInstructions;
+ program->Base.NumTemporaries = ap.Base.NumTemporaries;
+ program->Base.NumParameters = ap.Base.NumParameters;
+ program->Base.NumAttributes = ap.Base.NumAttributes;
+ program->Base.NumAddressRegs = ap.Base.NumAddressRegs;
+ program->Base.InputsRead = ap.Base.InputsRead;
+ program->Base.OutputsWritten = ap.Base.OutputsWritten;
+ program->IsPositionInvariant = ap.HintPositionInvariant;
+
+ if (program->Base.Instructions)
+ _mesa_free(program->Base.Instructions);
+ program->Base.Instructions = ap.Base.Instructions;
+
+ if (program->Base.Parameters)
+ _mesa_free_parameter_list(program->Base.Parameters);
+ program->Base.Parameters = ap.Base.Parameters;
+
+#if DEBUG_VP
+ _mesa_print_program(&program->Base);
+#endif
+}