draw: create specialized vs varients incorporating fetch & emit
[mesa.git] / src / gallium / auxiliary / draw / draw_vs_varient.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * 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, sub license, 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 portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Keith Whitwell <keith@tungstengraphics.com>
31 */
32
33 #include "pipe/p_util.h"
34 #include "draw/draw_context.h"
35 #include "draw/draw_private.h"
36 #include "draw/draw_vbuf.h"
37 #include "draw/draw_vertex.h"
38 #include "draw/draw_vs.h"
39 #include "translate/translate.h"
40 #include "translate/translate_cache.h"
41
42 /* A first pass at incorporating vertex fetch/emit functionality into
43 */
44 struct draw_vs_varient_generic {
45 struct draw_vs_varient base;
46
47
48
49 struct draw_vertex_shader *shader;
50 struct draw_context *draw;
51
52 /* Basic plan is to run these two translate functions before/after
53 * the vertex shader's existing run_linear() routine to simulate
54 * the inclusion of this functionality into the shader...
55 *
56 * Next will look at actually including it.
57 */
58 struct translate *fetch;
59 struct translate *emit;
60
61 const float (*constants)[4];
62 };
63
64
65
66
67 static void vsvg_set_constants( struct draw_vs_varient *varient,
68 const float (*constants)[4] )
69 {
70 struct draw_vs_varient_generic *vsvg = (struct draw_vs_varient_generic *)varient;
71
72 vsvg->constants = constants;
73 }
74
75
76 static void vsvg_set_input( struct draw_vs_varient *varient,
77 unsigned buffer,
78 const void *ptr,
79 unsigned stride )
80 {
81 struct draw_vs_varient_generic *vsvg = (struct draw_vs_varient_generic *)varient;
82
83 vsvg->fetch->set_buffer(vsvg->fetch,
84 buffer,
85 ptr,
86 stride);
87 }
88
89
90 static void vsvg_run_elts( struct draw_vs_varient *varient,
91 const unsigned *elts,
92 unsigned count,
93 void *output_buffer)
94 {
95 struct draw_vs_varient_generic *vsvg = (struct draw_vs_varient_generic *)varient;
96
97 /* Want to do this in small batches for cache locality?
98 */
99
100 vsvg->fetch->run_elts( vsvg->fetch,
101 elts,
102 count,
103 output_buffer );
104
105 //if (!vsvg->base.vs->is_passthrough)
106 {
107 vsvg->base.vs->run_linear( vsvg->base.vs,
108 output_buffer,
109 output_buffer,
110 vsvg->constants,
111 count,
112 vsvg->base.key.output_stride,
113 vsvg->base.key.output_stride);
114
115 //if (!vsvg->already_in_emit_format)
116
117 vsvg->emit->set_buffer( vsvg->emit,
118 0,
119 output_buffer,
120 vsvg->base.key.output_stride );
121
122
123 vsvg->emit->run( vsvg->emit,
124 0, count,
125 output_buffer );
126 }
127 }
128
129
130 static void vsvg_run_linear( struct draw_vs_varient *varient,
131 unsigned start,
132 unsigned count,
133 void *output_buffer )
134 {
135 struct draw_vs_varient_generic *vsvg = (struct draw_vs_varient_generic *)varient;
136
137 //debug_printf("%s %d %d\n", __FUNCTION__, start, count);
138
139
140 vsvg->fetch->run( vsvg->fetch,
141 start,
142 count,
143 output_buffer );
144
145 //if (!vsvg->base.vs->is_passthrough)
146 {
147 vsvg->base.vs->run_linear( vsvg->base.vs,
148 output_buffer,
149 output_buffer,
150 vsvg->constants,
151 count,
152 vsvg->base.key.output_stride,
153 vsvg->base.key.output_stride);
154
155 //if (!vsvg->already_in_emit_format)
156 vsvg->emit->set_buffer( vsvg->emit,
157 0,
158 output_buffer,
159 vsvg->base.key.output_stride );
160
161
162 vsvg->emit->run( vsvg->emit,
163 0, count,
164 output_buffer );
165 }
166 }
167
168
169
170 static void vsvg_destroy( struct draw_vs_varient *varient )
171 {
172 FREE(varient);
173 }
174
175
176 struct draw_vs_varient *draw_vs_varient_generic( struct draw_vertex_shader *vs,
177 const struct draw_vs_varient_key *key )
178 {
179 unsigned i;
180 struct translate_key fetch, emit;
181
182 struct draw_vs_varient_generic *vsvg = CALLOC_STRUCT( draw_vs_varient_generic );
183 if (vsvg == NULL)
184 return NULL;
185
186 vsvg->base.key = *key;
187 vsvg->base.vs = vs;
188 vsvg->base.set_input = vsvg_set_input;
189 vsvg->base.set_constants = vsvg_set_constants;
190 vsvg->base.run_elts = vsvg_run_elts;
191 vsvg->base.run_linear = vsvg_run_linear;
192 vsvg->base.destroy = vsvg_destroy;
193
194
195
196 /* OK, have to build a new one:
197 */
198 fetch.nr_elements = vs->info.num_inputs;
199 fetch.output_stride = 0;
200 for (i = 0; i < vs->info.num_inputs; i++) {
201 fetch.element[i].input_format = key->element[i].in.format;
202 fetch.element[i].input_buffer = key->element[i].in.buffer;
203 fetch.element[i].input_offset = key->element[i].in.offset;
204 fetch.element[i].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
205 fetch.element[i].output_offset = fetch.output_stride;
206 fetch.output_stride += 4 * sizeof(float);
207 }
208
209
210 emit.nr_elements = vs->info.num_outputs;
211 emit.output_stride = key->output_stride;
212 for (i = 0; i < vs->info.num_outputs; i++) {
213 emit.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
214 emit.element[i].input_buffer = 0;
215 emit.element[i].input_offset = i * 4 * sizeof(float);
216 emit.element[i].output_format = key->element[i].out.format;
217 emit.element[i].output_offset = key->element[i].out.offset;
218 }
219
220 vsvg->fetch = draw_vs_get_fetch( vs->draw, &fetch );
221 vsvg->emit = draw_vs_get_emit( vs->draw, &emit );
222
223 return &vsvg->base;
224 }
225
226
227
228
229