Merge branch 'gallium-vertex-linear' into gallium-0.1
[mesa.git] / src / gallium / auxiliary / draw / draw_pt_emit.c
1 /**************************************************************************
2 *
3 * Copyright 2008 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 #include "translate/translate.h"
35 #include "translate/translate_cache.h"
36
37 struct pt_emit {
38 struct draw_context *draw;
39
40 struct translate *translate;
41
42 struct translate_cache *cache;
43 unsigned prim;
44
45 const struct vertex_info *vinfo;
46 };
47
48 void draw_pt_emit_prepare( struct pt_emit *emit,
49 unsigned prim )
50 {
51 struct draw_context *draw = emit->draw;
52 const struct vertex_info *vinfo;
53 unsigned dst_offset;
54 struct translate_key hw_key;
55 unsigned i;
56 boolean ok;
57
58 /* XXX: need to flush to get prim_vbuf.c to release its allocation??
59 */
60 draw_do_flush( draw, DRAW_FLUSH_BACKEND );
61
62
63 /* XXX: may need to defensively reset this later on as clipping can
64 * clobber this state in the render backend.
65 */
66 emit->prim = prim;
67
68 ok = draw->render->set_primitive(draw->render, emit->prim);
69 if (!ok) {
70 assert(0);
71 return;
72 }
73
74 /* Must do this after set_primitive() above:
75 */
76 emit->vinfo = vinfo = draw->render->get_vertex_info(draw->render);
77
78
79 /* Translate from pipeline vertices to hw vertices.
80 */
81 dst_offset = 0;
82 for (i = 0; i < vinfo->num_attribs; i++) {
83 unsigned emit_sz = 0;
84 unsigned src_buffer = 0;
85 unsigned output_format;
86 unsigned src_offset = (vinfo->src_index[i] * 4 * sizeof(float) );
87
88
89
90 switch (vinfo->emit[i]) {
91 case EMIT_4F:
92 output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
93 emit_sz = 4 * sizeof(float);
94 break;
95 case EMIT_3F:
96 output_format = PIPE_FORMAT_R32G32B32_FLOAT;
97 emit_sz = 3 * sizeof(float);
98 break;
99 case EMIT_2F:
100 output_format = PIPE_FORMAT_R32G32_FLOAT;
101 emit_sz = 2 * sizeof(float);
102 break;
103 case EMIT_1F:
104 output_format = PIPE_FORMAT_R32_FLOAT;
105 emit_sz = 1 * sizeof(float);
106 break;
107 case EMIT_1F_PSIZE:
108 output_format = PIPE_FORMAT_R32_FLOAT;
109 emit_sz = 1 * sizeof(float);
110 src_buffer = 1;
111 src_offset = 0;
112 break;
113 case EMIT_4UB:
114 output_format = PIPE_FORMAT_B8G8R8A8_UNORM;
115 emit_sz = 4 * sizeof(ubyte);
116 break;
117 default:
118 assert(0);
119 output_format = PIPE_FORMAT_NONE;
120 emit_sz = 0;
121 break;
122 }
123
124 hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
125 hw_key.element[i].input_buffer = src_buffer;
126 hw_key.element[i].input_offset = src_offset;
127 hw_key.element[i].output_format = output_format;
128 hw_key.element[i].output_offset = dst_offset;
129
130 dst_offset += emit_sz;
131 }
132
133 hw_key.nr_elements = vinfo->num_attribs;
134 hw_key.output_stride = vinfo->size * 4;
135
136 if (!emit->translate ||
137 translate_key_compare(&emit->translate->key, &hw_key) != 0)
138 {
139 translate_key_sanitize(&hw_key);
140 emit->translate = translate_cache_find(emit->cache, &hw_key);
141 }
142 }
143
144
145 void draw_pt_emit( struct pt_emit *emit,
146 const float (*vertex_data)[4],
147 unsigned vertex_count,
148 unsigned stride,
149 const ushort *elts,
150 unsigned count )
151 {
152 struct draw_context *draw = emit->draw;
153 struct translate *translate = emit->translate;
154 struct vbuf_render *render = draw->render;
155 void *hw_verts;
156
157 /* XXX: need to flush to get prim_vbuf.c to release its allocation??
158 */
159 draw_do_flush( draw, DRAW_FLUSH_BACKEND );
160
161 /* XXX: and work out some way to coordinate the render primitive
162 * between vbuf.c and here...
163 */
164 if (!draw->render->set_primitive(draw->render, emit->prim)) {
165 assert(0);
166 return;
167 }
168
169 hw_verts = render->allocate_vertices(render,
170 (ushort)translate->key.output_stride,
171 (ushort)vertex_count);
172 if (!hw_verts) {
173 assert(0);
174 return;
175 }
176
177 translate->set_buffer(translate,
178 0,
179 vertex_data,
180 stride );
181
182 translate->set_buffer(translate,
183 1,
184 &draw->rasterizer->point_size,
185 0);
186
187 translate->run( translate,
188 0,
189 vertex_count,
190 hw_verts );
191
192 render->draw(render,
193 elts,
194 count);
195
196 render->release_vertices(render,
197 hw_verts,
198 translate->key.output_stride,
199 vertex_count);
200 }
201
202
203 void draw_pt_emit_linear(struct pt_emit *emit,
204 const float (*vertex_data)[4],
205 unsigned vertex_count,
206 unsigned stride,
207 unsigned start,
208 unsigned count)
209 {
210 struct draw_context *draw = emit->draw;
211 struct translate *translate = emit->translate;
212 struct vbuf_render *render = draw->render;
213 void *hw_verts;
214
215 #if 0
216 debug_printf("Linear emit\n");
217 #endif
218 /* XXX: need to flush to get prim_vbuf.c to release its allocation??
219 */
220 draw_do_flush( draw, DRAW_FLUSH_BACKEND );
221
222 /* XXX: and work out some way to coordinate the render primitive
223 * between vbuf.c and here...
224 */
225 if (!draw->render->set_primitive(draw->render, emit->prim)) {
226 assert(0);
227 return;
228 }
229
230 hw_verts = render->allocate_vertices(render,
231 (ushort)translate->key.output_stride,
232 (ushort)count);
233 if (!hw_verts) {
234 assert(0);
235 return;
236 }
237
238 translate->set_buffer(translate, 0,
239 vertex_data, stride);
240
241 translate->set_buffer(translate, 1,
242 &draw->rasterizer->point_size,
243 0);
244
245 translate->run(translate,
246 0,
247 vertex_count,
248 hw_verts);
249
250 if (0) {
251 unsigned i;
252 for (i = 0; i < vertex_count; i++) {
253 debug_printf("\n\n%s vertex %d:\n", __FUNCTION__, i);
254 draw_dump_emitted_vertex( emit->vinfo,
255 (const uint8_t *)hw_verts +
256 translate->key.output_stride * i );
257 }
258 }
259
260
261 render->draw_arrays(render, start, count);
262
263 render->release_vertices(render,
264 hw_verts,
265 translate->key.output_stride,
266 vertex_count);
267 }
268
269 struct pt_emit *draw_pt_emit_create( struct draw_context *draw )
270 {
271 struct pt_emit *emit = CALLOC_STRUCT(pt_emit);
272 if (!emit)
273 return NULL;
274
275 emit->draw = draw;
276 emit->cache = translate_cache_create();
277 if (!emit->cache) {
278 FREE(emit);
279 return NULL;
280 }
281
282 return emit;
283 }
284
285 void draw_pt_emit_destroy( struct pt_emit *emit )
286 {
287 if (emit->cache)
288 translate_cache_destroy(emit->cache);
289
290 FREE(emit);
291 }