1/*
2 * Copyright © 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
24#include <string.h>
25#include "main/mtypes.h"
26#include "prog_instruction.h"
27#include "program_parser.h"
28
29
30/**
31 * Extra assembly-level parser routines
32 *
33 * \author Ian Romanick <ian.d.romanick@intel.com>
34 */
35
36int
37_mesa_parse_instruction_suffix(const struct asm_parser_state *state,
38			       const char *suffix,
39			       struct prog_instruction *inst)
40{
41   inst->Saturate = GL_FALSE;
42
43   /* The only possible suffix element is the saturation selector from
44    * ARB_fragment_program.
45    */
46   if (state->mode == ARB_fragment) {
47      if (strcmp(suffix, "_SAT") == 0) {
48	 inst->Saturate = GL_TRUE;
49	 suffix += 4;
50      }
51   }
52
53   /* It is an error for all of the suffix string not to be consumed.
54    */
55   return suffix[0] == '\0';
56}
57
58
59int
60_mesa_ARBvp_parse_option(struct asm_parser_state *state, const char *option)
61{
62   if (strcmp(option, "ARB_position_invariant") == 0) {
63      state->option.PositionInvariant = 1;
64      return 1;
65   }
66
67   return 0;
68}
69
70
71int
72_mesa_ARBfp_parse_option(struct asm_parser_state *state, const char *option)
73{
74   unsigned fog_option;
75
76   /* All of the options currently supported start with "ARB_".  The code is
77    * currently structured with nested if-statements because eventually options
78    * that start with "NV_" will be supported.  This structure will result in
79    * less churn when those options are added.
80    */
81   if (strncmp(option, "ARB_", 4) == 0) {
82      /* Advance the pointer past the "ARB_" prefix.
83       */
84      option += 4;
85
86      if (strncmp(option, "fog_", 4) == 0) {
87	 option += 4;
88
89         if (strcmp(option, "exp") == 0) {
90            fog_option = OPTION_FOG_EXP;
91         } else if (strcmp(option, "exp2") == 0) {
92            fog_option = OPTION_FOG_EXP2;
93         } else if (strcmp(option, "linear") == 0) {
94            fog_option = OPTION_FOG_LINEAR;
95         } else {
96            /* invalid option */
97            return 0;
98         }
99
100         if (state->option.Fog == OPTION_NONE) {
101            state->option.Fog = fog_option;
102            return 1;
103         }
104
105         /* The ARB_fragment_program specification instructs us to handle
106          * redundant options in two seemingly contradictory ways:
107          *
108          * Section 3.11.4.5.1 says:
109          * "Only one fog application option may be specified by any given
110          *  fragment program.  A fragment program that specifies more than one
111          *  of the program options "ARB_fog_exp", "ARB_fog_exp2", and
112          *  "ARB_fog_linear", will fail to load."
113          *
114          * Issue 27 says:
115          * "The three mandatory options are ARB_fog_exp, ARB_fog_exp2, and
116          *  ARB_fog_linear.  As these options are mutually exclusive by
117          *  nature, specifying more than one is not useful.  If more than one
118          *  is specified, the last one encountered in the <optionSequence>
119          *  will be the one to actually modify the execution environment."
120          *
121          * We choose to allow programs to specify the same OPTION redundantly,
122          * but fail to load programs that specify contradictory options.
123          */
124         return state->option.Fog == fog_option ? 1 : 0;
125      } else if (strncmp(option, "precision_hint_", 15) == 0) {
126	 option += 15;
127
128         /* The ARB_fragment_program spec, 3.11.4.5.2 says:
129          *
130          * "Only one precision control option may be specified by any given
131          * fragment program.  A fragment program that specifies both the
132          * "ARB_precision_hint_fastest" and "ARB_precision_hint_nicest"
133          * program options will fail to load.
134          */
135
136         if (strcmp(option, "nicest") == 0 &&
137             state->option.PrecisionHint != OPTION_FASTEST) {
138            state->option.PrecisionHint = OPTION_NICEST;
139            return 1;
140         } else if (strcmp(option, "fastest") == 0 &&
141                    state->option.PrecisionHint != OPTION_NICEST) {
142            state->option.PrecisionHint = OPTION_FASTEST;
143            return 1;
144         }
145
146	 return 0;
147      } else if (strcmp(option, "draw_buffers") == 0) {
148	 /* Don't need to check extension availability because all Mesa-based
149	  * drivers support GL_ARB_draw_buffers.
150	  */
151	 state->option.DrawBuffers = 1;
152	 return 1;
153      } else if (strcmp(option, "fragment_program_shadow") == 0) {
154	 if (state->ctx->Extensions.ARB_fragment_program_shadow) {
155	    state->option.Shadow = 1;
156	    return 1;
157	 }
158      } else if (strncmp(option, "fragment_coord_", 15) == 0) {
159         option += 15;
160         if (state->ctx->Extensions.ARB_fragment_coord_conventions) {
161            if (strcmp(option, "origin_upper_left") == 0) {
162               state->option.OriginUpperLeft = 1;
163               return 1;
164            }
165            else if (strcmp(option, "pixel_center_integer") == 0) {
166               state->option.PixelCenterInteger = 1;
167               return 1;
168            }
169         }
170      }
171   } else if (strncmp(option, "ATI_", 4) == 0) {
172      option += 4;
173
174      if (strcmp(option, "draw_buffers") == 0) {
175	 /* Don't need to check extension availability because all Mesa-based
176	  * drivers support GL_ATI_draw_buffers.
177	  */
178	 state->option.DrawBuffers = 1;
179	 return 1;
180      }
181   }
182
183   return 0;
184}
185