svga: remove user-space vertex/index buffer code
[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_time.h"
31 #include "indices/u_indices.h"
32
33 #include "svga_hw_reg.h"
34 #include "svga_cmd.h"
35 #include "svga_context.h"
36 #include "svga_screen.h"
37 #include "svga_draw.h"
38 #include "svga_state.h"
39 #include "svga_swtnl.h"
40 #include "svga_debug.h"
41 #include "svga_resource_buffer.h"
42
43
44 static enum pipe_error
45 retry_draw_range_elements( struct svga_context *svga,
46 struct pipe_resource *index_buffer,
47 unsigned index_size,
48 int index_bias,
49 unsigned min_index,
50 unsigned max_index,
51 unsigned prim,
52 unsigned start,
53 unsigned count,
54 unsigned instance_count,
55 boolean do_retry )
56 {
57 enum pipe_error ret = PIPE_OK;
58
59 svga_hwtnl_set_unfilled( svga->hwtnl,
60 svga->curr.rast->hw_unfilled );
61
62 svga_hwtnl_set_flatshade( svga->hwtnl,
63 svga->curr.rast->templ.flatshade,
64 svga->curr.rast->templ.flatshade_first );
65
66 ret = svga_update_state( svga, SVGA_STATE_HW_DRAW );
67 if (ret != PIPE_OK)
68 goto retry;
69
70 ret = svga_hwtnl_draw_range_elements( svga->hwtnl,
71 index_buffer, index_size, index_bias,
72 min_index, max_index,
73 prim, start, count );
74 if (ret != PIPE_OK)
75 goto retry;
76
77 return PIPE_OK;
78
79 retry:
80 svga_context_flush( svga, NULL );
81
82 if (do_retry)
83 {
84 return retry_draw_range_elements( svga,
85 index_buffer, index_size, index_bias,
86 min_index, max_index,
87 prim, start, count,
88 instance_count, FALSE );
89 }
90
91 return ret;
92 }
93
94
95 static enum pipe_error
96 retry_draw_arrays( struct svga_context *svga,
97 unsigned prim,
98 unsigned start,
99 unsigned count,
100 unsigned instance_count,
101 boolean do_retry )
102 {
103 enum pipe_error ret;
104
105 svga_hwtnl_set_unfilled( svga->hwtnl,
106 svga->curr.rast->hw_unfilled );
107
108 svga_hwtnl_set_flatshade( svga->hwtnl,
109 svga->curr.rast->templ.flatshade,
110 svga->curr.rast->templ.flatshade_first );
111
112 ret = svga_update_state( svga, SVGA_STATE_HW_DRAW );
113 if (ret != PIPE_OK)
114 goto retry;
115
116 ret = svga_hwtnl_draw_arrays( svga->hwtnl, prim,
117 start, count );
118 if (ret != PIPE_OK)
119 goto retry;
120
121 return PIPE_OK;
122
123 retry:
124 if (ret == PIPE_ERROR_OUT_OF_MEMORY && do_retry)
125 {
126 svga_context_flush( svga, NULL );
127
128 return retry_draw_arrays( svga,
129 prim,
130 start,
131 count,
132 instance_count,
133 FALSE );
134 }
135
136 return ret;
137 }
138
139
140 static void
141 svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
142 {
143 struct svga_context *svga = svga_context( pipe );
144 unsigned reduced_prim = u_reduced_prim( info->mode );
145 unsigned count = info->count;
146 enum pipe_error ret = 0;
147 boolean needed_swtnl;
148
149 svga->num_draw_calls++; /* for SVGA_QUERY_DRAW_CALLS */
150
151 if (!u_trim_pipe_prim( info->mode, &count ))
152 return;
153
154 /*
155 * Mark currently bound target surfaces as dirty
156 * doesn't really matter if it is done before drawing.
157 *
158 * TODO If we ever normaly return something other then
159 * true we should not mark it as dirty then.
160 */
161 svga_mark_surfaces_dirty(svga_context(pipe));
162
163 if (svga->curr.reduced_prim != reduced_prim) {
164 svga->curr.reduced_prim = reduced_prim;
165 svga->dirty |= SVGA_NEW_REDUCED_PRIMITIVE;
166 }
167
168 needed_swtnl = svga->state.sw.need_swtnl;
169
170 svga_update_state_retry( svga, SVGA_STATE_NEED_SWTNL );
171
172 #ifdef DEBUG
173 if (svga->curr.vs->base.id == svga->debug.disable_shader ||
174 svga->curr.fs->base.id == svga->debug.disable_shader)
175 return;
176 #endif
177
178 if (svga->state.sw.need_swtnl) {
179 svga->num_fallbacks++; /* for SVGA_QUERY_FALLBACKS */
180 if (!needed_swtnl) {
181 /*
182 * We're switching from HW to SW TNL. SW TNL will require mapping all
183 * currently bound vertex buffers, some of which may already be
184 * referenced in the current command buffer as result of previous HW
185 * TNL. So flush now, to prevent the context to flush while a referred
186 * vertex buffer is mapped.
187 */
188
189 svga_context_flush(svga, NULL);
190 }
191
192 /* Avoid leaking the previous hwtnl bias to swtnl */
193 svga_hwtnl_set_index_bias( svga->hwtnl, 0 );
194 ret = svga_swtnl_draw_vbo( svga, info );
195 }
196 else {
197 if (info->indexed && svga->curr.ib.buffer) {
198 unsigned offset;
199
200 assert(svga->curr.ib.offset % svga->curr.ib.index_size == 0);
201 offset = svga->curr.ib.offset / svga->curr.ib.index_size;
202
203 ret = retry_draw_range_elements( svga,
204 svga->curr.ib.buffer,
205 svga->curr.ib.index_size,
206 info->index_bias,
207 info->min_index,
208 info->max_index,
209 info->mode,
210 info->start + offset,
211 info->count,
212 info->instance_count,
213 TRUE );
214 }
215 else {
216 ret = retry_draw_arrays( svga,
217 info->mode,
218 info->start,
219 info->count,
220 info->instance_count,
221 TRUE );
222 }
223 }
224
225 /* XXX: Silence warnings, do something sensible here? */
226 (void)ret;
227
228 if (SVGA_DEBUG & DEBUG_FLUSH) {
229 svga_hwtnl_flush_retry( svga );
230 svga_context_flush(svga, NULL);
231 }
232 }
233
234
235 void svga_init_draw_functions( struct svga_context *svga )
236 {
237 svga->pipe.draw_vbo = svga_draw_vbo;
238 }