• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "util/u_memory.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  
49  void
draw_pt_emit_prepare(struct pt_emit * emit,unsigned prim,unsigned * max_vertices)50  draw_pt_emit_prepare(struct pt_emit *emit,
51                       unsigned prim,
52                       unsigned *max_vertices)
53  {
54     struct draw_context *draw = emit->draw;
55     const struct vertex_info *vinfo;
56     unsigned dst_offset;
57     struct translate_key hw_key;
58     unsigned i;
59  
60     /* XXX: need to flush to get prim_vbuf.c to release its allocation??
61      */
62     draw_do_flush( draw, DRAW_FLUSH_BACKEND );
63  
64     /* XXX: may need to defensively reset this later on as clipping can
65      * clobber this state in the render backend.
66      */
67     emit->prim = prim;
68  
69     draw->render->set_primitive(draw->render, emit->prim);
70  
71     /* Must do this after set_primitive() above:
72      */
73     emit->vinfo = vinfo = draw->render->get_vertex_info(draw->render);
74  
75     /* Translate from pipeline vertices to hw vertices.
76      */
77     dst_offset = 0;
78     for (i = 0; i < vinfo->num_attribs; i++) {
79        unsigned emit_sz = 0;
80        unsigned src_buffer = 0;
81        unsigned output_format;
82        unsigned src_offset = (vinfo->attrib[i].src_index * 4 * sizeof(float) );
83  
84        output_format = draw_translate_vinfo_format(vinfo->attrib[i].emit);
85        emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit);
86  
87        /* doesn't handle EMIT_OMIT */
88        assert(emit_sz != 0);
89  
90        if (vinfo->attrib[i].emit == EMIT_1F_PSIZE) {
91  	 src_buffer = 1;
92  	 src_offset = 0;
93        }
94  
95        hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
96        hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
97        hw_key.element[i].input_buffer = src_buffer;
98        hw_key.element[i].input_offset = src_offset;
99        hw_key.element[i].instance_divisor = 0;
100        hw_key.element[i].output_format = output_format;
101        hw_key.element[i].output_offset = dst_offset;
102  
103        dst_offset += emit_sz;
104     }
105  
106     hw_key.nr_elements = vinfo->num_attribs;
107     hw_key.output_stride = vinfo->size * 4;
108  
109     if (!emit->translate ||
110         translate_key_compare(&emit->translate->key, &hw_key) != 0) {
111        translate_key_sanitize(&hw_key);
112        emit->translate = translate_cache_find(emit->cache, &hw_key);
113     }
114  
115     *max_vertices = (draw->render->max_vertex_buffer_bytes /
116                      (vinfo->size * 4));
117  }
118  
119  
120  void
draw_pt_emit(struct pt_emit * emit,const struct draw_vertex_info * vert_info,const struct draw_prim_info * prim_info)121  draw_pt_emit(struct pt_emit *emit,
122               const struct draw_vertex_info *vert_info,
123               const struct draw_prim_info *prim_info)
124  {
125     const float (*vertex_data)[4] = (const float (*)[4])vert_info->verts->data;
126     unsigned vertex_count = vert_info->count;
127     unsigned stride = vert_info->stride;
128     const ushort *elts = prim_info->elts;
129     struct draw_context *draw = emit->draw;
130     struct translate *translate = emit->translate;
131     struct vbuf_render *render = draw->render;
132     unsigned start, i;
133     void *hw_verts;
134  
135     /* XXX: need to flush to get prim_vbuf.c to release its allocation??
136      */
137     draw_do_flush( draw, DRAW_FLUSH_BACKEND );
138  
139     if (vertex_count == 0)
140        return;
141  
142     /* XXX: and work out some way to coordinate the render primitive
143      * between vbuf.c and here...
144      */
145     draw->render->set_primitive(draw->render, emit->prim);
146  
147     render->allocate_vertices(render,
148                               (ushort)translate->key.output_stride,
149                               (ushort)vertex_count);
150  
151     hw_verts = render->map_vertices( render );
152     if (!hw_verts) {
153        debug_warn_once("map of vertex buffer failed (out of memory?)");
154        return;
155     }
156  
157     translate->set_buffer(translate,
158  			 0,
159  			 vertex_data,
160  			 stride,
161  			 ~0);
162  
163     translate->set_buffer(translate,
164  			 1,
165  			 &draw->rasterizer->point_size,
166  			 0,
167  			 ~0);
168  
169     /* fetch/translate vertex attribs to fill hw_verts[] */
170     translate->run(translate,
171  		  0,
172  		  vertex_count,
173                    draw->instance_id,
174  		  hw_verts );
175  
176     render->unmap_vertices(render, 0, vertex_count - 1);
177  
178     for (start = i = 0;
179          i < prim_info->primitive_count;
180          start += prim_info->primitive_lengths[i], i++)
181     {
182        render->draw_elements(render,
183                              elts + start,
184                              prim_info->primitive_lengths[i]);
185     }
186  
187     render->release_vertices(render);
188  }
189  
190  
191  void
draw_pt_emit_linear(struct pt_emit * emit,const struct draw_vertex_info * vert_info,const struct draw_prim_info * prim_info)192  draw_pt_emit_linear(struct pt_emit *emit,
193                      const struct draw_vertex_info *vert_info,
194                      const struct draw_prim_info *prim_info)
195  {
196     const float (*vertex_data)[4] = (const float (*)[4])vert_info->verts->data;
197     unsigned stride = vert_info->stride;
198     unsigned count = vert_info->count;
199     struct draw_context *draw = emit->draw;
200     struct translate *translate = emit->translate;
201     struct vbuf_render *render = draw->render;
202     void *hw_verts;
203     unsigned start, i;
204  
205  #if 0
206     debug_printf("Linear emit\n");
207  #endif
208     /* XXX: need to flush to get prim_vbuf.c to release its allocation??
209      */
210     draw_do_flush( draw, DRAW_FLUSH_BACKEND );
211  
212     /* XXX: and work out some way to coordinate the render primitive
213      * between vbuf.c and here...
214      */
215     draw->render->set_primitive(draw->render, emit->prim);
216  
217     if (!render->allocate_vertices(render,
218                                    (ushort)translate->key.output_stride,
219                                    (ushort)count))
220        goto fail;
221  
222     hw_verts = render->map_vertices( render );
223     if (!hw_verts)
224        goto fail;
225  
226     translate->set_buffer(translate, 0,
227  			 vertex_data, stride, count - 1);
228  
229     translate->set_buffer(translate, 1,
230  			 &draw->rasterizer->point_size,
231  			 0, ~0);
232  
233     translate->run(translate,
234                    0,
235                    count,
236                    draw->instance_id,
237                    hw_verts);
238  
239     if (0) {
240        unsigned i;
241        for (i = 0; i < count; i++) {
242           debug_printf("\n\n%s vertex %d:\n", __FUNCTION__, i);
243           draw_dump_emitted_vertex( emit->vinfo,
244                                     (const uint8_t *)hw_verts +
245                                     translate->key.output_stride * i );
246        }
247     }
248  
249     render->unmap_vertices( render, 0, count - 1 );
250  
251     for (start = i = 0;
252          i < prim_info->primitive_count;
253          start += prim_info->primitive_lengths[i], i++)
254     {
255        render->draw_arrays(render,
256                            start,
257                            prim_info->primitive_lengths[i]);
258     }
259  
260     render->release_vertices(render);
261  
262     return;
263  
264  fail:
265     debug_warn_once("allocate or map of vertex buffer failed (out of memory?)");
266     return;
267  }
268  
269  
270  struct pt_emit *
draw_pt_emit_create(struct draw_context * draw)271  draw_pt_emit_create(struct draw_context *draw)
272  {
273     struct pt_emit *emit = CALLOC_STRUCT(pt_emit);
274     if (!emit)
275        return NULL;
276  
277     emit->draw = draw;
278     emit->cache = translate_cache_create();
279     if (!emit->cache) {
280        FREE(emit);
281        return NULL;
282     }
283  
284     return emit;
285  }
286  
287  
288  void
draw_pt_emit_destroy(struct pt_emit * emit)289  draw_pt_emit_destroy(struct pt_emit *emit)
290  {
291     if (emit->cache)
292        translate_cache_destroy(emit->cache);
293  
294     FREE(emit);
295  }
296