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