Squashed commit of the following:
[profile/ivi/mesa.git] / src / gallium / drivers / i965 / brw_pipe_shader.c
1 /*
2  Copyright (C) Intel Corp.  2006.  All Rights Reserved.
3  Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4  develop this 3D driver.
5  
6  Permission is hereby granted, free of charge, to any person obtaining
7  a copy of this software and associated documentation files (the
8  "Software"), to deal in the Software without restriction, including
9  without limitation the rights to use, copy, modify, merge, publish,
10  distribute, sublicense, and/or sell copies of the Software, and to
11  permit persons to whom the Software is furnished to do so, subject to
12  the following conditions:
13  
14  The above copyright notice and this permission notice (including the
15  next paragraph) shall be included in all copies or substantial
16  portions of the Software.
17  
18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  
26  **********************************************************************/
27  /*
28   * Authors:
29   *   Keith Whitwell <keith@tungstengraphics.com>
30   */
31
32 #include "util/u_inlines.h"
33 #include "util/u_memory.h"
34   
35 #include "tgsi/tgsi_parse.h"
36 #include "tgsi/tgsi_scan.h"
37
38 #include "brw_context.h"
39 #include "brw_wm.h"
40
41
42 /**
43  * Determine if the given shader uses complex features such as flow
44  * conditionals, loops, subroutines.
45  */
46 static GLboolean has_flow_control(const struct tgsi_shader_info *info)
47 {
48     return (info->opcode_count[TGSI_OPCODE_ARL] > 0 ||
49             info->opcode_count[TGSI_OPCODE_IF] > 0 ||
50             info->opcode_count[TGSI_OPCODE_ENDIF] > 0 || /* redundant - IF */
51             info->opcode_count[TGSI_OPCODE_CAL] > 0 ||
52             info->opcode_count[TGSI_OPCODE_BRK] > 0 ||   /* redundant - BGNLOOP */
53             info->opcode_count[TGSI_OPCODE_RET] > 0 ||   /* redundant - CAL */
54             info->opcode_count[TGSI_OPCODE_BGNLOOP] > 0);
55 }
56
57
58 static void scan_immediates(const struct tgsi_token *tokens,
59                             const struct tgsi_shader_info *info,
60                             struct brw_immediate_data *imm)
61 {
62    struct tgsi_parse_context parse;
63    boolean done = FALSE;
64
65    imm->nr = 0;
66    imm->data = MALLOC(info->immediate_count * 4 * sizeof(float));
67
68    tgsi_parse_init( &parse, tokens );
69    while (!tgsi_parse_end_of_tokens( &parse ) && !done) {
70       tgsi_parse_token( &parse );
71
72       switch (parse.FullToken.Token.Type) {
73       case TGSI_TOKEN_TYPE_DECLARATION:
74          break;
75
76       case TGSI_TOKEN_TYPE_IMMEDIATE: {
77          static const float id[4] = {0,0,0,1};
78          const float *value = &parse.FullToken.FullImmediate.u[0].Float;
79          unsigned size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1;
80          unsigned i;
81
82          for (i = 0; i < size; i++)
83             imm->data[imm->nr][i] = value[i];
84
85          for (; i < 4; i++)
86             imm->data[imm->nr][i] = id[i];
87          
88          imm->nr++;
89          break;
90       }
91
92       case TGSI_TOKEN_TYPE_INSTRUCTION:
93          done = 1;
94          break;
95       }
96    }
97 }
98
99
100 static void brw_bind_fs_state( struct pipe_context *pipe, void *prog )
101 {
102    struct brw_fragment_shader *fs = (struct brw_fragment_shader *)prog;
103    struct brw_context *brw = brw_context(pipe);
104    
105    if (brw->curr.fragment_shader == fs)
106       return;
107
108    if (brw->curr.fragment_shader == NULL ||
109        fs == NULL ||
110        memcmp(&brw->curr.fragment_shader->signature, &fs->signature,
111               brw_fs_signature_size(&fs->signature)) != 0) {
112       brw->state.dirty.mesa |= PIPE_NEW_FRAGMENT_SIGNATURE;
113    }
114
115    brw->curr.fragment_shader = fs;
116    brw->state.dirty.mesa |= PIPE_NEW_FRAGMENT_SHADER;
117 }
118
119 static void brw_bind_vs_state( struct pipe_context *pipe, void *prog )
120 {
121    struct brw_context *brw = brw_context(pipe);
122
123    brw->curr.vertex_shader = (struct brw_vertex_shader *)prog;
124    brw->state.dirty.mesa |= PIPE_NEW_VERTEX_SHADER;
125 }
126
127
128
129 static void *brw_create_fs_state( struct pipe_context *pipe,
130                                   const struct pipe_shader_state *shader )
131 {
132    struct brw_context *brw = brw_context(pipe);
133    struct brw_fragment_shader *fs;
134    int i;
135
136    fs = CALLOC_STRUCT(brw_fragment_shader);
137    if (fs == NULL)
138       return NULL;
139
140    /* Duplicate tokens, scan shader
141     */
142    fs->id = brw->program_id++;
143    fs->has_flow_control = has_flow_control(&fs->info);
144
145    fs->tokens = tgsi_dup_tokens(shader->tokens);
146    if (fs->tokens == NULL)
147       goto fail;
148
149    tgsi_scan_shader(fs->tokens, &fs->info);
150    scan_immediates(fs->tokens, &fs->info, &fs->immediates);
151
152    fs->signature.nr_inputs = fs->info.num_inputs;
153    for (i = 0; i < fs->info.num_inputs; i++) {
154       fs->signature.input[i].interp = fs->info.input_interpolate[i];
155       fs->signature.input[i].semantic = fs->info.input_semantic_name[i];
156       fs->signature.input[i].semantic_index = fs->info.input_semantic_index[i];
157    }
158
159    for (i = 0; i < fs->info.num_inputs; i++)
160       if (fs->info.input_semantic_name[i] == TGSI_SEMANTIC_POSITION)
161          fs->uses_depth = 1;
162
163    if (fs->info.uses_kill)
164       fs->iz_lookup |= IZ_PS_KILL_ALPHATEST_BIT;
165
166    if (fs->info.writes_z)
167       fs->iz_lookup |= IZ_PS_COMPUTES_DEPTH_BIT;
168
169    return (void *)fs;
170
171 fail:
172    FREE(fs);
173    return NULL;
174 }
175
176
177 static void *brw_create_vs_state( struct pipe_context *pipe,
178                                   const struct pipe_shader_state *shader )
179 {
180    struct brw_context *brw = brw_context(pipe);
181    struct brw_vertex_shader *vs;
182    unsigned i;
183
184    vs = CALLOC_STRUCT(brw_vertex_shader);
185    if (vs == NULL)
186       return NULL;
187
188    /* Duplicate tokens, scan shader
189     */
190    vs->tokens = tgsi_dup_tokens(shader->tokens);
191    if (vs->tokens == NULL)
192       goto fail;
193
194    tgsi_scan_shader(vs->tokens, &vs->info);
195    scan_immediates(vs->tokens, &vs->info, &vs->immediates);
196
197    vs->id = brw->program_id++;
198    vs->has_flow_control = has_flow_control(&vs->info);
199
200    vs->output_hpos = BRW_OUTPUT_NOT_PRESENT;
201    vs->output_color0 = BRW_OUTPUT_NOT_PRESENT;
202    vs->output_color1 = BRW_OUTPUT_NOT_PRESENT;
203    vs->output_bfc0 = BRW_OUTPUT_NOT_PRESENT;
204    vs->output_bfc1 = BRW_OUTPUT_NOT_PRESENT;
205    vs->output_edgeflag = BRW_OUTPUT_NOT_PRESENT;
206
207    for (i = 0; i < vs->info.num_outputs; i++) {
208       int index = vs->info.output_semantic_index[i];
209       switch (vs->info.output_semantic_name[i]) {
210       case TGSI_SEMANTIC_POSITION:
211          vs->output_hpos = i;
212          break;
213       case TGSI_SEMANTIC_COLOR:
214          if (index == 0)
215             vs->output_color0 = i;
216          else
217             vs->output_color1 = i;
218          break;
219       case TGSI_SEMANTIC_BCOLOR:
220          if (index == 0)
221             vs->output_bfc0 = i;
222          else
223             vs->output_bfc1 = i;
224          break;
225       case TGSI_SEMANTIC_EDGEFLAG:
226          vs->output_edgeflag = i;
227          break;
228       }
229    }
230
231    
232    /* Done:
233     */
234    return (void *)vs;
235
236 fail:
237    FREE(vs);
238    return NULL;
239 }
240
241
242 static void brw_delete_fs_state( struct pipe_context *pipe, void *prog )
243 {
244    struct brw_fragment_shader *fs = (struct brw_fragment_shader *)prog;
245
246    bo_reference(&fs->const_buffer, NULL);
247    FREE( (void *)fs->tokens );
248    FREE( fs );
249 }
250
251
252 static void brw_delete_vs_state( struct pipe_context *pipe, void *prog )
253 {
254    struct brw_fragment_shader *vs = (struct brw_fragment_shader *)prog;
255
256    /* Delete draw shader
257     */
258    FREE( (void *)vs->tokens );
259    FREE( vs );
260 }
261
262
263 static void brw_set_constant_buffer(struct pipe_context *pipe,
264                                      uint shader, uint index,
265                                      struct pipe_resource *buf)
266 {
267    struct brw_context *brw = brw_context(pipe);
268
269    assert(index == 0);
270
271    if (shader == PIPE_SHADER_FRAGMENT) {
272       pipe_resource_reference( &brw->curr.fragment_constants,
273                              buf );
274
275       brw->state.dirty.mesa |= PIPE_NEW_FRAGMENT_CONSTANTS;
276    }
277    else {
278       pipe_resource_reference( &brw->curr.vertex_constants,
279                              buf );
280
281       brw->state.dirty.mesa |= PIPE_NEW_VERTEX_CONSTANTS;
282    }
283 }
284
285
286 void brw_pipe_shader_init( struct brw_context *brw )
287 {
288    brw->base.set_constant_buffer = brw_set_constant_buffer;
289
290    brw->base.create_vs_state = brw_create_vs_state;
291    brw->base.bind_vs_state = brw_bind_vs_state;
292    brw->base.delete_vs_state = brw_delete_vs_state;
293
294    brw->base.create_fs_state = brw_create_fs_state;
295    brw->base.bind_fs_state = brw_bind_fs_state;
296    brw->base.delete_fs_state = brw_delete_fs_state;
297 }
298
299 void brw_pipe_shader_cleanup( struct brw_context *brw )
300 {
301    pipe_resource_reference( &brw->curr.fragment_constants, NULL );
302    pipe_resource_reference( &brw->curr.vertex_constants, NULL );
303 }