svga: add guest statistic gathering interface
[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_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWELEMENTS);
63
64 svga_hwtnl_set_fillmode(svga->hwtnl, svga->curr.rast->hw_fillmode);
65
66 ret = svga_update_state( svga, SVGA_STATE_HW_DRAW );
67 if (ret != PIPE_OK)
68 goto retry;
69
70 /** determine if flatshade is to be used after svga_update_state()
71 * in case the fragment shader is changed.
72 */
73 svga_hwtnl_set_flatshade(svga->hwtnl,
74 svga->curr.rast->templ.flatshade ||
75 svga->state.hw_draw.fs->uses_flat_interp,
76 svga->curr.rast->templ.flatshade_first);
77
78 ret = svga_hwtnl_draw_range_elements( svga->hwtnl,
79 index_buffer, index_size, index_bias,
80 min_index, max_index,
81 prim, start, count,
82 start_instance, instance_count);
83 if (ret != PIPE_OK)
84 goto retry;
85
86 goto done;
87
88 retry:
89 svga_context_flush( svga, NULL );
90
91 if (do_retry)
92 {
93 ret = retry_draw_range_elements(svga,
94 index_buffer, index_size, index_bias,
95 min_index, max_index,
96 prim, start, count,
97 start_instance, instance_count, FALSE);
98 }
99
100 done:
101 SVGA_STATS_TIME_POP(svga_sws(svga));
102 return ret;
103 }
104
105
106 static enum pipe_error
107 retry_draw_arrays( struct svga_context *svga,
108 enum pipe_prim_type prim, unsigned start, unsigned count,
109 unsigned start_instance, unsigned instance_count,
110 boolean do_retry )
111 {
112 enum pipe_error ret;
113
114 SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWARRAYS);
115
116 svga_hwtnl_set_fillmode(svga->hwtnl, svga->curr.rast->hw_fillmode);
117
118 ret = svga_update_state( svga, SVGA_STATE_HW_DRAW );
119 if (ret != PIPE_OK)
120 goto retry;
121
122 /** determine if flatshade is to be used after svga_update_state()
123 * in case the fragment shader is changed.
124 */
125 svga_hwtnl_set_flatshade(svga->hwtnl,
126 svga->curr.rast->templ.flatshade ||
127 svga->state.hw_draw.fs->uses_flat_interp,
128 svga->curr.rast->templ.flatshade_first);
129
130 ret = svga_hwtnl_draw_arrays(svga->hwtnl, prim, start, count,
131 start_instance, instance_count);
132 if (ret != PIPE_OK)
133 goto retry;
134
135 goto done;
136
137 retry:
138 if (ret == PIPE_ERROR_OUT_OF_MEMORY && do_retry)
139 {
140 svga_context_flush( svga, NULL );
141
142 ret = retry_draw_arrays(svga, prim, start, count,
143 start_instance, instance_count,
144 FALSE);
145 }
146
147 done:
148 SVGA_STATS_TIME_POP(svga_sws(svga));
149 return ret;
150 }
151
152
153 /**
154 * Determine if we need to implement primitive restart with a fallback
155 * path which breaks the original primitive into sub-primitive at the
156 * restart indexes.
157 */
158 static boolean
159 need_fallback_prim_restart(const struct svga_context *svga,
160 const struct pipe_draw_info *info)
161 {
162 if (info->primitive_restart && info->indexed) {
163 if (!svga_have_vgpu10(svga))
164 return TRUE;
165 else if (!svga->state.sw.need_swtnl) {
166 if (svga->curr.ib.index_size == 1)
167 return TRUE; /* no device support for 1-byte indexes */
168 else if (svga->curr.ib.index_size == 2)
169 return info->restart_index != 0xffff;
170 else
171 return info->restart_index != 0xffffffff;
172 }
173 }
174
175 return FALSE;
176 }
177
178
179 static void
180 svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
181 {
182 struct svga_context *svga = svga_context( pipe );
183 unsigned reduced_prim = u_reduced_prim( info->mode );
184 unsigned count = info->count;
185 enum pipe_error ret = 0;
186 boolean needed_swtnl;
187
188 SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWVBO);
189
190 svga->hud.num_draw_calls++; /* for SVGA_QUERY_NUM_DRAW_CALLS */
191
192 if (u_reduced_prim(info->mode) == PIPE_PRIM_TRIANGLES &&
193 svga->curr.rast->templ.cull_face == PIPE_FACE_FRONT_AND_BACK)
194 goto done;
195
196 /*
197 * Mark currently bound target surfaces as dirty
198 * doesn't really matter if it is done before drawing.
199 *
200 * TODO If we ever normaly return something other then
201 * true we should not mark it as dirty then.
202 */
203 svga_mark_surfaces_dirty(svga_context(pipe));
204
205 if (svga->curr.reduced_prim != reduced_prim) {
206 svga->curr.reduced_prim = reduced_prim;
207 svga->dirty |= SVGA_NEW_REDUCED_PRIMITIVE;
208 }
209
210 if (need_fallback_prim_restart(svga, info)) {
211 enum pipe_error r;
212 r = util_draw_vbo_without_prim_restart(pipe, &svga->curr.ib, info);
213 assert(r == PIPE_OK);
214 (void) r;
215 goto done;
216 }
217
218 if (!u_trim_pipe_prim( info->mode, &count ))
219 goto done;
220
221 needed_swtnl = svga->state.sw.need_swtnl;
222
223 svga_update_state_retry( svga, SVGA_STATE_NEED_SWTNL );
224
225 #ifdef DEBUG
226 if (svga->curr.vs->base.id == svga->debug.disable_shader ||
227 svga->curr.fs->base.id == svga->debug.disable_shader)
228 goto done;
229 #endif
230
231 if (svga->state.sw.need_swtnl) {
232 svga->hud.num_fallbacks++; /* for SVGA_QUERY_NUM_FALLBACKS */
233 if (!needed_swtnl) {
234 /*
235 * We're switching from HW to SW TNL. SW TNL will require mapping all
236 * currently bound vertex buffers, some of which may already be
237 * referenced in the current command buffer as result of previous HW
238 * TNL. So flush now, to prevent the context to flush while a referred
239 * vertex buffer is mapped.
240 */
241
242 svga_context_flush(svga, NULL);
243 }
244
245 /* Avoid leaking the previous hwtnl bias to swtnl */
246 svga_hwtnl_set_index_bias( svga->hwtnl, 0 );
247 ret = svga_swtnl_draw_vbo( svga, info );
248 }
249 else {
250 if (info->indexed && svga->curr.ib.buffer) {
251 unsigned offset;
252
253 assert(svga->curr.ib.offset % svga->curr.ib.index_size == 0);
254 offset = svga->curr.ib.offset / svga->curr.ib.index_size;
255
256 ret = retry_draw_range_elements( svga,
257 svga->curr.ib.buffer,
258 svga->curr.ib.index_size,
259 info->index_bias,
260 info->min_index,
261 info->max_index,
262 info->mode,
263 info->start + offset,
264 count,
265 info->start_instance,
266 info->instance_count,
267 TRUE );
268 }
269 else {
270 ret = retry_draw_arrays(svga, info->mode, info->start, count,
271 info->start_instance, info->instance_count,
272 TRUE);
273 }
274 }
275
276 /* XXX: Silence warnings, do something sensible here? */
277 (void)ret;
278
279 if (SVGA_DEBUG & DEBUG_FLUSH) {
280 svga_hwtnl_flush_retry( svga );
281 svga_context_flush(svga, NULL);
282 }
283
284 done:
285 SVGA_STATS_TIME_POP(svga_sws(svga));
286 ;
287 }
288
289
290 void svga_init_draw_functions( struct svga_context *svga )
291 {
292 svga->pipe.draw_vbo = svga_draw_vbo;
293 }