13464ebd5Sriastradh/*
23464ebd5Sriastradh * Copyright © 2009 Intel Corporation
33464ebd5Sriastradh *
43464ebd5Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a
53464ebd5Sriastradh * copy of this software and associated documentation files (the "Software"),
63464ebd5Sriastradh * to deal in the Software without restriction, including without limitation
73464ebd5Sriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense,
83464ebd5Sriastradh * and/or sell copies of the Software, and to permit persons to whom the
93464ebd5Sriastradh * Software is furnished to do so, subject to the following conditions:
103464ebd5Sriastradh *
113464ebd5Sriastradh * The above copyright notice and this permission notice (including the next
123464ebd5Sriastradh * paragraph) shall be included in all copies or substantial portions of the
133464ebd5Sriastradh * Software.
143464ebd5Sriastradh *
153464ebd5Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
163464ebd5Sriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
173464ebd5Sriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
183464ebd5Sriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
193464ebd5Sriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
203464ebd5Sriastradh * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
213464ebd5Sriastradh * DEALINGS IN THE SOFTWARE.
223464ebd5Sriastradh */
233464ebd5Sriastradh
243464ebd5Sriastradh#include <string.h>
253464ebd5Sriastradh#include "main/mtypes.h"
263464ebd5Sriastradh#include "prog_instruction.h"
273464ebd5Sriastradh#include "program_parser.h"
283464ebd5Sriastradh
293464ebd5Sriastradh
303464ebd5Sriastradh/**
313464ebd5Sriastradh * Extra assembly-level parser routines
323464ebd5Sriastradh *
333464ebd5Sriastradh * \author Ian Romanick <ian.d.romanick@intel.com>
343464ebd5Sriastradh */
353464ebd5Sriastradh
363464ebd5Sriastradhint
373464ebd5Sriastradh_mesa_parse_instruction_suffix(const struct asm_parser_state *state,
383464ebd5Sriastradh			       const char *suffix,
393464ebd5Sriastradh			       struct prog_instruction *inst)
403464ebd5Sriastradh{
4101e04c3fSmrg   inst->Saturate = GL_FALSE;
423464ebd5Sriastradh
4301e04c3fSmrg   /* The only possible suffix element is the saturation selector from
443464ebd5Sriastradh    * ARB_fragment_program.
453464ebd5Sriastradh    */
463464ebd5Sriastradh   if (state->mode == ARB_fragment) {
473464ebd5Sriastradh      if (strcmp(suffix, "_SAT") == 0) {
4801e04c3fSmrg	 inst->Saturate = GL_TRUE;
493464ebd5Sriastradh	 suffix += 4;
503464ebd5Sriastradh      }
513464ebd5Sriastradh   }
523464ebd5Sriastradh
533464ebd5Sriastradh   /* It is an error for all of the suffix string not to be consumed.
543464ebd5Sriastradh    */
553464ebd5Sriastradh   return suffix[0] == '\0';
563464ebd5Sriastradh}
573464ebd5Sriastradh
583464ebd5Sriastradh
593464ebd5Sriastradhint
603464ebd5Sriastradh_mesa_ARBvp_parse_option(struct asm_parser_state *state, const char *option)
613464ebd5Sriastradh{
623464ebd5Sriastradh   if (strcmp(option, "ARB_position_invariant") == 0) {
633464ebd5Sriastradh      state->option.PositionInvariant = 1;
643464ebd5Sriastradh      return 1;
653464ebd5Sriastradh   }
663464ebd5Sriastradh
673464ebd5Sriastradh   return 0;
683464ebd5Sriastradh}
693464ebd5Sriastradh
703464ebd5Sriastradh
713464ebd5Sriastradhint
723464ebd5Sriastradh_mesa_ARBfp_parse_option(struct asm_parser_state *state, const char *option)
733464ebd5Sriastradh{
7401e04c3fSmrg   unsigned fog_option;
7501e04c3fSmrg
763464ebd5Sriastradh   /* All of the options currently supported start with "ARB_".  The code is
773464ebd5Sriastradh    * currently structured with nested if-statements because eventually options
783464ebd5Sriastradh    * that start with "NV_" will be supported.  This structure will result in
793464ebd5Sriastradh    * less churn when those options are added.
803464ebd5Sriastradh    */
813464ebd5Sriastradh   if (strncmp(option, "ARB_", 4) == 0) {
823464ebd5Sriastradh      /* Advance the pointer past the "ARB_" prefix.
833464ebd5Sriastradh       */
843464ebd5Sriastradh      option += 4;
853464ebd5Sriastradh
863464ebd5Sriastradh      if (strncmp(option, "fog_", 4) == 0) {
873464ebd5Sriastradh	 option += 4;
883464ebd5Sriastradh
8901e04c3fSmrg         if (strcmp(option, "exp") == 0) {
9001e04c3fSmrg            fog_option = OPTION_FOG_EXP;
9101e04c3fSmrg         } else if (strcmp(option, "exp2") == 0) {
9201e04c3fSmrg            fog_option = OPTION_FOG_EXP2;
9301e04c3fSmrg         } else if (strcmp(option, "linear") == 0) {
9401e04c3fSmrg            fog_option = OPTION_FOG_LINEAR;
9501e04c3fSmrg         } else {
9601e04c3fSmrg            /* invalid option */
9701e04c3fSmrg            return 0;
9801e04c3fSmrg         }
993464ebd5Sriastradh
10001e04c3fSmrg         if (state->option.Fog == OPTION_NONE) {
10101e04c3fSmrg            state->option.Fog = fog_option;
10201e04c3fSmrg            return 1;
10301e04c3fSmrg         }
10401e04c3fSmrg
10501e04c3fSmrg         /* The ARB_fragment_program specification instructs us to handle
10601e04c3fSmrg          * redundant options in two seemingly contradictory ways:
10701e04c3fSmrg          *
10801e04c3fSmrg          * Section 3.11.4.5.1 says:
10901e04c3fSmrg          * "Only one fog application option may be specified by any given
11001e04c3fSmrg          *  fragment program.  A fragment program that specifies more than one
11101e04c3fSmrg          *  of the program options "ARB_fog_exp", "ARB_fog_exp2", and
11201e04c3fSmrg          *  "ARB_fog_linear", will fail to load."
11301e04c3fSmrg          *
11401e04c3fSmrg          * Issue 27 says:
11501e04c3fSmrg          * "The three mandatory options are ARB_fog_exp, ARB_fog_exp2, and
11601e04c3fSmrg          *  ARB_fog_linear.  As these options are mutually exclusive by
11701e04c3fSmrg          *  nature, specifying more than one is not useful.  If more than one
11801e04c3fSmrg          *  is specified, the last one encountered in the <optionSequence>
11901e04c3fSmrg          *  will be the one to actually modify the execution environment."
12001e04c3fSmrg          *
12101e04c3fSmrg          * We choose to allow programs to specify the same OPTION redundantly,
12201e04c3fSmrg          * but fail to load programs that specify contradictory options.
12301e04c3fSmrg          */
12401e04c3fSmrg         return state->option.Fog == fog_option ? 1 : 0;
1253464ebd5Sriastradh      } else if (strncmp(option, "precision_hint_", 15) == 0) {
1263464ebd5Sriastradh	 option += 15;
1273464ebd5Sriastradh
128af69d88dSmrg         /* The ARB_fragment_program spec, 3.11.4.5.2 says:
129af69d88dSmrg          *
130af69d88dSmrg          * "Only one precision control option may be specified by any given
131af69d88dSmrg          * fragment program.  A fragment program that specifies both the
132af69d88dSmrg          * "ARB_precision_hint_fastest" and "ARB_precision_hint_nicest"
133af69d88dSmrg          * program options will fail to load.
134af69d88dSmrg          */
135af69d88dSmrg
13601e04c3fSmrg         if (strcmp(option, "nicest") == 0 &&
13701e04c3fSmrg             state->option.PrecisionHint != OPTION_FASTEST) {
138af69d88dSmrg            state->option.PrecisionHint = OPTION_NICEST;
139af69d88dSmrg            return 1;
14001e04c3fSmrg         } else if (strcmp(option, "fastest") == 0 &&
14101e04c3fSmrg                    state->option.PrecisionHint != OPTION_NICEST) {
142af69d88dSmrg            state->option.PrecisionHint = OPTION_FASTEST;
143af69d88dSmrg            return 1;
144af69d88dSmrg         }
1453464ebd5Sriastradh
1463464ebd5Sriastradh	 return 0;
1473464ebd5Sriastradh      } else if (strcmp(option, "draw_buffers") == 0) {
1483464ebd5Sriastradh	 /* Don't need to check extension availability because all Mesa-based
1493464ebd5Sriastradh	  * drivers support GL_ARB_draw_buffers.
1503464ebd5Sriastradh	  */
1513464ebd5Sriastradh	 state->option.DrawBuffers = 1;
1523464ebd5Sriastradh	 return 1;
1533464ebd5Sriastradh      } else if (strcmp(option, "fragment_program_shadow") == 0) {
1543464ebd5Sriastradh	 if (state->ctx->Extensions.ARB_fragment_program_shadow) {
1553464ebd5Sriastradh	    state->option.Shadow = 1;
1563464ebd5Sriastradh	    return 1;
1573464ebd5Sriastradh	 }
1583464ebd5Sriastradh      } else if (strncmp(option, "fragment_coord_", 15) == 0) {
1593464ebd5Sriastradh         option += 15;
1603464ebd5Sriastradh         if (state->ctx->Extensions.ARB_fragment_coord_conventions) {
1613464ebd5Sriastradh            if (strcmp(option, "origin_upper_left") == 0) {
1623464ebd5Sriastradh               state->option.OriginUpperLeft = 1;
1633464ebd5Sriastradh               return 1;
1643464ebd5Sriastradh            }
1653464ebd5Sriastradh            else if (strcmp(option, "pixel_center_integer") == 0) {
1663464ebd5Sriastradh               state->option.PixelCenterInteger = 1;
1673464ebd5Sriastradh               return 1;
1683464ebd5Sriastradh            }
1693464ebd5Sriastradh         }
1703464ebd5Sriastradh      }
1713464ebd5Sriastradh   } else if (strncmp(option, "ATI_", 4) == 0) {
1723464ebd5Sriastradh      option += 4;
1733464ebd5Sriastradh
1743464ebd5Sriastradh      if (strcmp(option, "draw_buffers") == 0) {
1753464ebd5Sriastradh	 /* Don't need to check extension availability because all Mesa-based
1763464ebd5Sriastradh	  * drivers support GL_ATI_draw_buffers.
1773464ebd5Sriastradh	  */
1783464ebd5Sriastradh	 state->option.DrawBuffers = 1;
1793464ebd5Sriastradh	 return 1;
1803464ebd5Sriastradh      }
1813464ebd5Sriastradh   }
1823464ebd5Sriastradh
1833464ebd5Sriastradh   return 0;
1843464ebd5Sriastradh}
185