draw: add passthrough path to the pipeline
[mesa.git] / src / gallium / auxiliary / draw / draw_pt.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_pt.h"
37
38
39 /* XXX: Shouldn't those two functions below use the '>' operator???
40 */
41
42 static boolean too_many_verts( struct draw_context *draw,
43 unsigned verts )
44 {
45 return verts < 1024;
46 }
47
48 static boolean too_many_elts( struct draw_context *draw,
49 unsigned elts )
50 {
51 return elts < (16 * 1024);
52 }
53
54
55 boolean
56 draw_pt_arrays(struct draw_context *draw,
57 unsigned prim,
58 unsigned start,
59 unsigned count)
60 {
61 const boolean pipeline = draw_need_pipeline(draw, prim);
62 const boolean cliptest = !draw->rasterizer->bypass_clipping;
63 const boolean shading = !draw->rasterizer->bypass_vs;
64 struct draw_pt_front_end *frontend = NULL;
65 struct draw_pt_middle_end *middle = NULL;
66
67
68 /* Overall we do:
69 * - frontend -- prepare fetch_elts, draw_elts - eg vcache
70 * - middle -- fetch, shade, cliptest, viewport
71 * - pipeline -- the prim pipeline: clipping, wide lines, etc
72 * - backend -- the vbuf_render provided by the driver.
73 */
74
75
76 if (!cliptest && !pipeline && !shading) {
77 /* This is the 'passthrough' path:
78 */
79 /* Fetch user verts, emit hw verts:
80 */
81 middle = draw->pt.middle.fetch_emit;
82 }
83 else if (!cliptest && !shading) {
84 /* This is the 'passthrough' path targetting the pipeline backend.
85 */
86 /* Fetch user verts, emit pipeline verts, run pipeline:
87 */
88 middle = draw->pt.middle.fetch_pipeline;
89 }
90 #if 0
91 else if (!cliptest && !pipeline) {
92 /* Fetch user verts, run vertex shader, emit hw verts:
93 */
94 middle = draw->pt.middle.fetch_shade_emit;
95 }
96 else if (!pipeline) {
97 /* Even though !pipeline, we have to run it to get clipping. We
98 * do know that the pipeline is just the clipping operation, but
99 * that probably doesn't help much.
100 *
101 * This is going to be the most important path for a lot of
102 * swtnl cards.
103 */
104 /* Fetch user verts,
105 * run vertex shader,
106 * cliptest and viewport trasform
107 * if no clipped vertices,
108 * emit hw verts
109 * else
110 * run pipline
111 */
112 middle = draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit;
113 }
114 else if (!cliptest) {
115 /* Fetch user verts, run vertex shader, run pipeline:
116 */
117 middle = draw->pt.middle.fetch_shade_pipeline;
118 }
119 else {
120 /* This is what we're currently always doing:
121 */
122 /* Fetch user verts, run vertex shader, cliptest, run pipeline:
123 */
124 middle = draw->pt.middle.fetch_shade_cliptest_pipeline;
125 }
126 #else
127 else {
128 return FALSE;
129 }
130 #endif
131
132
133 /* If !pipeline, need to make sure we respect the driver's limited
134 * capabilites to receive blocks of vertex data and elements.
135 */
136 #if 0
137 if (!pipeline) {
138 unsigned vertex_mode = passthrough;
139 unsigned nr_verts = count_vertices( draw, start, count );
140 unsigned hw_prim = prim;
141
142 if (is_elts(draw)) {
143 frontend = draw->pt.front.vcache;
144 hw_prim = reduced_prim(prim);
145 }
146
147 if (too_many_verts(nr_verts)) {
148 /* if (is_verts(draw) && can_split(prim)) {
149 draw = draw_arrays_split;
150 }
151 else */ {
152 frontend = draw->pt.front.vcache;
153 hw_prim = reduced_prim(prim);
154 }
155 }
156
157 if (too_many_elts(count)) {
158
159 /* if (is_elts(draw) && can_split(prim)) {
160 draw = draw_elts_split;
161 }
162 else */ {
163 frontend = draw->pt.front.vcache;
164 hw_prim = reduced_prim(prim);
165 }
166 }
167
168 if (!good_prim(hw_prim)) {
169 draw = draw->pt.front.vcache;
170 }
171 }
172 #else
173 frontend = draw->pt.front.vcache;
174 #endif
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 frontend->prepare( frontend, prim, middle );
181
182 frontend->run( frontend,
183 draw_pt_elt_func( draw ),
184 draw_pt_elt_ptr( draw, start ),
185 count );
186
187 frontend->finish( frontend );
188
189 return TRUE;
190 }
191
192
193 boolean draw_pt_init( struct draw_context *draw )
194 {
195 draw->pt.middle.fetch_emit = draw_pt_fetch_emit( draw );
196 if (!draw->pt.middle.fetch_emit)
197 return FALSE;
198
199 draw->pt.middle.fetch_pipeline = draw_pt_fetch_pipeline( draw );
200 if (!draw->pt.middle.fetch_pipeline)
201 return FALSE;
202
203 draw->pt.front.vcache = draw_pt_vcache( draw );
204 if (!draw->pt.front.vcache)
205 return FALSE;
206
207 return TRUE;
208 }
209
210
211 void draw_pt_destroy( struct draw_context *draw )
212 {
213 if (draw->pt.middle.fetch_emit) {
214 draw->pt.middle.fetch_emit->destroy( draw->pt.middle.fetch_emit );
215 draw->pt.middle.fetch_emit = NULL;
216 }
217
218 if (draw->pt.middle.fetch_pipeline) {
219 draw->pt.middle.fetch_pipeline->destroy( draw->pt.middle.fetch_pipeline );
220 draw->pt.middle.fetch_pipeline = NULL;
221 }
222
223 if (draw->pt.front.vcache) {
224 draw->pt.front.vcache->destroy( draw->pt.front.vcache );
225 draw->pt.front.vcache = NULL;
226 }
227 }