svga: s/unsigned/enum pipe_prim_type/ for primitive type variables
[mesa.git] / src / gallium / drivers / svga / svga_pipe_draw.c
1 /**********************************************************
2 * Copyright 2008-2009 VMware, Inc. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 **********************************************************/
25
26
27 #include "util/u_format.h"
28 #include "util/u_inlines.h"
29 #include "util/u_prim.h"
30 #include "util/u_prim_restart.h"
31 #include "util/u_time.h"
32 #include "util/u_upload_mgr.h"
33 #include "indices/u_indices.h"
34
35 #include "svga_hw_reg.h"
36 #include "svga_cmd.h"
37 #include "svga_context.h"
38 #include "svga_screen.h"
39 #include "svga_draw.h"
40 #include "svga_shader.h"
41 #include "svga_state.h"
42 #include "svga_swtnl.h"
43 #include "svga_debug.h"
44 #include "svga_resource_buffer.h"
45
46 static enum pipe_error
47 retry_draw_range_elements( struct svga_context *svga,
48 struct pipe_resource *index_buffer,
49 unsigned index_size,
50 int index_bias,
51 unsigned min_index,
52 unsigned max_index,
53 enum pipe_prim_type prim,
54 unsigned start,
55 unsigned count,
56 unsigned start_instance,
57 unsigned instance_count,
58 boolean do_retry )
59 {
60 enum pipe_error ret = PIPE_OK;
61
62 svga_hwtnl_set_fillmode(svga->hwtnl, svga->curr.rast->hw_fillmode);
63
64 ret = svga_update_state( svga, SVGA_STATE_HW_DRAW );
65 if (ret != PIPE_OK)
66 goto retry;
67
68 /** determine if flatshade is to be used after svga_update_state()
69 * in case the fragment shader is changed.
70 */
71 svga_hwtnl_set_flatshade(svga->hwtnl,
72 svga->curr.rast->templ.flatshade ||
73 svga->state.hw_draw.fs->uses_flat_interp,
74 svga->curr.rast->templ.flatshade_first);
75
76 ret = svga_hwtnl_draw_range_elements( svga->hwtnl,
77 index_buffer, index_size, index_bias,
78 min_index, max_index,
79 prim, start, count,
80 start_instance, instance_count);
81 if (ret != PIPE_OK)
82 goto retry;
83
84 return PIPE_OK;
85
86 retry:
87 svga_context_flush( svga, NULL );
88
89 if (do_retry)
90 {
91 return retry_draw_range_elements( svga,
92 index_buffer, index_size, index_bias,
93 min_index, max_index,
94 prim, start, count,
95 start_instance, instance_count, FALSE );
96 }
97
98 return ret;
99 }
100
101
102 static enum pipe_error
103 retry_draw_arrays( struct svga_context *svga,
104 enum pipe_prim_type prim, unsigned start, unsigned count,
105 unsigned start_instance, unsigned instance_count,
106 boolean do_retry )
107 {
108 enum pipe_error ret;
109
110 svga_hwtnl_set_fillmode(svga->hwtnl, svga->curr.rast->hw_fillmode);
111
112 ret = svga_update_state( svga, SVGA_STATE_HW_DRAW );
113 if (ret != PIPE_OK)
114 goto retry;
115
116 /** determine if flatshade is to be used after svga_update_state()
117 * in case the fragment shader is changed.
118 */
119 svga_hwtnl_set_flatshade(svga->hwtnl,
120 svga->curr.rast->templ.flatshade ||
121 svga->state.hw_draw.fs->uses_flat_interp,
122 svga->curr.rast->templ.flatshade_first);
123
124 ret = svga_hwtnl_draw_arrays(svga->hwtnl, prim, start, count,
125 start_instance, instance_count);
126 if (ret != PIPE_OK)
127 goto retry;
128
129 return PIPE_OK;
130
131 retry:
132 if (ret == PIPE_ERROR_OUT_OF_MEMORY && do_retry)
133 {
134 svga_context_flush( svga, NULL );
135
136 return retry_draw_arrays(svga, prim, start, count,
137 start_instance, instance_count,
138 FALSE );
139 }
140
141 return ret;
142 }
143
144
145 /**
146 * Determine if we need to implement primitive restart with a fallback
147 * path which breaks the original primitive into sub-primitive at the
148 * restart indexes.
149 */
150 static boolean
151 need_fallback_prim_restart(const struct svga_context *svga,
152 const struct pipe_draw_info *info)
153 {
154 if (info->primitive_restart && info->indexed) {
155 if (!svga_have_vgpu10(svga))
156 return TRUE;
157 else if (!svga->state.sw.need_swtnl) {
158 if (svga->curr.ib.index_size == 1)
159 return TRUE; /* no device support for 1-byte indexes */
160 else if (svga->curr.ib.index_size == 2)
161 return info->restart_index != 0xffff;
162 else
163 return info->restart_index != 0xffffffff;
164 }
165 }
166
167 return FALSE;
168 }
169
170
171 static void
172 svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
173 {
174 struct svga_context *svga = svga_context( pipe );
175 unsigned reduced_prim = u_reduced_prim( info->mode );
176 unsigned count = info->count;
177 enum pipe_error ret = 0;
178 boolean needed_swtnl;
179
180 svga->hud.num_draw_calls++; /* for SVGA_QUERY_NUM_DRAW_CALLS */
181
182 if (u_reduced_prim(info->mode) == PIPE_PRIM_TRIANGLES &&
183 svga->curr.rast->templ.cull_face == PIPE_FACE_FRONT_AND_BACK)
184 return;
185
186 /*
187 * Mark currently bound target surfaces as dirty
188 * doesn't really matter if it is done before drawing.
189 *
190 * TODO If we ever normaly return something other then
191 * true we should not mark it as dirty then.
192 */
193 svga_mark_surfaces_dirty(svga_context(pipe));
194
195 if (svga->curr.reduced_prim != reduced_prim) {
196 svga->curr.reduced_prim = reduced_prim;
197 svga->dirty |= SVGA_NEW_REDUCED_PRIMITIVE;
198 }
199
200 if (need_fallback_prim_restart(svga, info)) {
201 enum pipe_error r;
202 r = util_draw_vbo_without_prim_restart(pipe, &svga->curr.ib, info);
203 assert(r == PIPE_OK);
204 (void) r;
205 return;
206 }
207
208 if (!u_trim_pipe_prim( info->mode, &count ))
209 return;
210
211 needed_swtnl = svga->state.sw.need_swtnl;
212
213 svga_update_state_retry( svga, SVGA_STATE_NEED_SWTNL );
214
215 #ifdef DEBUG
216 if (svga->curr.vs->base.id == svga->debug.disable_shader ||
217 svga->curr.fs->base.id == svga->debug.disable_shader)
218 return;
219 #endif
220
221 if (svga->state.sw.need_swtnl) {
222 svga->hud.num_fallbacks++; /* for SVGA_QUERY_NUM_FALLBACKS */
223 if (!needed_swtnl) {
224 /*
225 * We're switching from HW to SW TNL. SW TNL will require mapping all
226 * currently bound vertex buffers, some of which may already be
227 * referenced in the current command buffer as result of previous HW
228 * TNL. So flush now, to prevent the context to flush while a referred
229 * vertex buffer is mapped.
230 */
231
232 svga_context_flush(svga, NULL);
233 }
234
235 /* Avoid leaking the previous hwtnl bias to swtnl */
236 svga_hwtnl_set_index_bias( svga->hwtnl, 0 );
237 ret = svga_swtnl_draw_vbo( svga, info );
238 }
239 else {
240 if (info->indexed && svga->curr.ib.buffer) {
241 unsigned offset;
242
243 assert(svga->curr.ib.offset % svga->curr.ib.index_size == 0);
244 offset = svga->curr.ib.offset / svga->curr.ib.index_size;
245
246 ret = retry_draw_range_elements( svga,
247 svga->curr.ib.buffer,
248 svga->curr.ib.index_size,
249 info->index_bias,
250 info->min_index,
251 info->max_index,
252 info->mode,
253 info->start + offset,
254 count,
255 info->start_instance,
256 info->instance_count,
257 TRUE );
258 }
259 else {
260 ret = retry_draw_arrays(svga, info->mode, info->start, count,
261 info->start_instance, info->instance_count,
262 TRUE);
263 }
264 }
265
266 /* XXX: Silence warnings, do something sensible here? */
267 (void)ret;
268
269 if (SVGA_DEBUG & DEBUG_FLUSH) {
270 svga_hwtnl_flush_retry( svga );
271 svga_context_flush(svga, NULL);
272 }
273 }
274
275
276 void svga_init_draw_functions( struct svga_context *svga )
277 {
278 svga->pipe.draw_vbo = svga_draw_vbo;
279 }