use the new macro
[mesa.git] / src / gallium / auxiliary / draw / draw_pt_fetch_shade_pipeline.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 #include "pipe/p_util.h"
29 #include "draw/draw_context.h"
30 #include "draw/draw_private.h"
31 #include "draw/draw_vbuf.h"
32 #include "draw/draw_vertex.h"
33 #include "draw/draw_pt.h"
34
35 struct fetch_pipeline_middle_end {
36 struct draw_pt_middle_end base;
37 struct draw_context *draw;
38
39 struct {
40 const ubyte *ptr;
41 unsigned pitch;
42 void (*fetch)( const void *from, float *attrib);
43 void (*emit)( const float *attrib, float **out );
44 } fetch[PIPE_MAX_ATTRIBS];
45
46 unsigned nr_fetch;
47 unsigned pipeline_vertex_size;
48 unsigned hw_vertex_size;
49 unsigned prim;
50 };
51
52 #if 0
53 static void emit_R32_FLOAT( const float *attrib,
54 float **out )
55 {
56 (*out)[0] = attrib[0];
57 (*out) += 1;
58 }
59
60 static void emit_R32G32_FLOAT( const float *attrib,
61 float **out )
62 {
63 (*out)[0] = attrib[0];
64 (*out)[1] = attrib[1];
65 (*out) += 2;
66 }
67
68 static void emit_R32G32B32_FLOAT( const float *attrib,
69 float **out )
70 {
71 (*out)[0] = attrib[0];
72 (*out)[1] = attrib[1];
73 (*out)[2] = attrib[2];
74 (*out) += 3;
75 }
76 #endif
77 static void emit_R32G32B32A32_FLOAT( const float *attrib,
78 float **out )
79 {
80 (*out)[0] = attrib[0];
81 (*out)[1] = attrib[1];
82 (*out)[2] = attrib[2];
83 (*out)[3] = attrib[3];
84 (*out) += 4;
85 }
86
87 static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
88 unsigned prim )
89 {
90 struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
91 struct draw_context *draw = fpme->draw;
92 unsigned i, nr = 0;
93 boolean ok;
94 const struct vertex_info *vinfo;
95
96 fpme->prim = prim;
97
98 ok = draw->render->set_primitive(draw->render, prim);
99 if (!ok) {
100 assert(0);
101 return;
102 }
103 /* Must do this after set_primitive() above:
104 */
105 vinfo = draw->render->get_vertex_info(draw->render);
106
107 /* Need to look at vertex shader inputs (we know it is a
108 * passthrough shader, so these define the outputs too). If we
109 * were running a shader, we'd still be looking at the inputs at
110 * this point.
111 */
112 for (i = 0; i < draw->vertex_shader->info.num_inputs; i++) {
113 unsigned buf = draw->vertex_element[i].vertex_buffer_index;
114 enum pipe_format format = draw->vertex_element[i].src_format;
115
116 fpme->fetch[nr].ptr = ((const ubyte *) draw->user.vbuffer[buf] +
117 draw->vertex_buffer[buf].buffer_offset +
118 draw->vertex_element[i].src_offset);
119
120 fpme->fetch[nr].pitch = draw->vertex_buffer[buf].pitch;
121 fpme->fetch[nr].fetch = draw_get_fetch_func( format );
122
123 /* Always do this -- somewhat redundant...
124 */
125 fpme->fetch[nr].emit = emit_R32G32B32A32_FLOAT;
126 nr++;
127 }
128
129 fpme->nr_fetch = nr;
130 //fpme->pipeline_vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float);
131 fpme->pipeline_vertex_size = MAX_VERTEX_ALLOCATION;
132 fpme->hw_vertex_size = vinfo->size * 4;
133 }
134
135
136
137
138 static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
139 const unsigned *fetch_elts,
140 unsigned fetch_count,
141 const ushort *draw_elts,
142 unsigned draw_count )
143 {
144 struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
145 struct draw_context *draw = fpme->draw;
146 struct draw_vertex_shader *shader = draw->vertex_shader;
147 char *pipeline_verts;
148
149 pipeline_verts = MALLOC(fpme->pipeline_vertex_size *
150 fetch_count);
151
152 if (!pipeline_verts) {
153 assert(0);
154 return;
155 }
156
157
158 /* Shade
159 */
160 shader->prepare(shader, draw);
161 if (shader->run(shader, draw, fetch_elts, fetch_count, pipeline_verts,
162 fpme->pipeline_vertex_size)) {
163 /* Run the pipeline */
164 draw_pt_run_pipeline( fpme->draw,
165 fpme->prim,
166 pipeline_verts,
167 fpme->pipeline_vertex_size,
168 fetch_count,
169 draw_elts,
170 draw_count );
171 } else {
172 unsigned i, j;
173 void *hw_verts;
174 float *out;
175
176 /* XXX: need to flush to get prim_vbuf.c to release its allocation??
177 */
178 draw_do_flush( draw, DRAW_FLUSH_BACKEND );
179
180 hw_verts = draw->render->allocate_vertices(draw->render,
181 (ushort)fpme->hw_vertex_size,
182 (ushort)fetch_count);
183 if (!hw_verts) {
184 assert(0);
185 return;
186 }
187
188 out = (float *)hw_verts;
189 for (i = 0; i < fetch_count; i++) {
190 struct vertex_header *header =
191 (struct vertex_header*)(pipeline_verts + (fpme->pipeline_vertex_size * i));
192
193 for (j = 0; j < fpme->nr_fetch; j++) {
194 float *attrib = header->data[j];
195 /*debug_printf("emiting [%f, %f, %f, %f]\n",
196 attrib[0], attrib[1],
197 attrib[2], attrib[3]);*/
198 fpme->fetch[j].emit(attrib, &out);
199 }
200 }
201 /* XXX: Draw arrays path to avoid re-emitting index list again and
202 * again.
203 */
204 draw->render->draw(draw->render,
205 draw_elts,
206 draw_count);
207
208 draw->render->release_vertices(draw->render,
209 hw_verts,
210 fpme->hw_vertex_size,
211 fetch_count);
212 }
213
214
215 FREE(pipeline_verts);
216 }
217
218
219
220 static void fetch_pipeline_finish( struct draw_pt_middle_end *middle )
221 {
222 /* nothing to do */
223 }
224
225 static void fetch_pipeline_destroy( struct draw_pt_middle_end *middle )
226 {
227 FREE(middle);
228 }
229
230
231 struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit( struct draw_context *draw )
232 {
233 struct fetch_pipeline_middle_end *fetch_pipeline = CALLOC_STRUCT( fetch_pipeline_middle_end );
234
235 fetch_pipeline->base.prepare = fetch_pipeline_prepare;
236 fetch_pipeline->base.run = fetch_pipeline_run;
237 fetch_pipeline->base.finish = fetch_pipeline_finish;
238 fetch_pipeline->base.destroy = fetch_pipeline_destroy;
239
240 fetch_pipeline->draw = draw;
241
242 return &fetch_pipeline->base;
243 }