1bf215546Sopenharmony_ci/********************************************************** 2bf215546Sopenharmony_ci * Copyright 2008-2009 VMware, Inc. All rights reserved. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person 5bf215546Sopenharmony_ci * obtaining a copy of this software and associated documentation 6bf215546Sopenharmony_ci * files (the "Software"), to deal in the Software without 7bf215546Sopenharmony_ci * restriction, including without limitation the rights to use, copy, 8bf215546Sopenharmony_ci * modify, merge, publish, distribute, sublicense, and/or sell copies 9bf215546Sopenharmony_ci * of the Software, and to permit persons to whom the Software is 10bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be 13bf215546Sopenharmony_ci * included in all copies or substantial portions of the Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16bf215546Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18bf215546Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19bf215546Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20bf215546Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21bf215546Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22bf215546Sopenharmony_ci * SOFTWARE. 23bf215546Sopenharmony_ci * 24bf215546Sopenharmony_ci **********************************************************/ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "util/u_draw.h" 28bf215546Sopenharmony_ci#include "util/format/u_format.h" 29bf215546Sopenharmony_ci#include "util/u_helpers.h" 30bf215546Sopenharmony_ci#include "util/u_inlines.h" 31bf215546Sopenharmony_ci#include "util/u_prim.h" 32bf215546Sopenharmony_ci#include "util/u_prim_restart.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#include "svga_context.h" 35bf215546Sopenharmony_ci#include "svga_draw_private.h" 36bf215546Sopenharmony_ci#include "svga_screen.h" 37bf215546Sopenharmony_ci#include "svga_draw.h" 38bf215546Sopenharmony_ci#include "svga_shader.h" 39bf215546Sopenharmony_ci#include "svga_surface.h" 40bf215546Sopenharmony_ci#include "svga_swtnl.h" 41bf215546Sopenharmony_ci#include "svga_debug.h" 42bf215546Sopenharmony_ci#include "svga_resource_buffer.h" 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_cistatic enum pipe_error 46bf215546Sopenharmony_ciretry_draw_range_elements(struct svga_context *svga, 47bf215546Sopenharmony_ci const struct pipe_draw_info *info, 48bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draw, 49bf215546Sopenharmony_ci unsigned count) 50bf215546Sopenharmony_ci{ 51bf215546Sopenharmony_ci SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWELEMENTS); 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci SVGA_RETRY(svga, svga_hwtnl_draw_range_elements(svga->hwtnl, info, draw, count)); 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci SVGA_STATS_TIME_POP(svga_sws(svga)); 56bf215546Sopenharmony_ci return PIPE_OK; 57bf215546Sopenharmony_ci} 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_cistatic enum pipe_error 61bf215546Sopenharmony_ciretry_draw_arrays( struct svga_context *svga, 62bf215546Sopenharmony_ci enum pipe_prim_type prim, unsigned start, unsigned count, 63bf215546Sopenharmony_ci unsigned start_instance, unsigned instance_count, 64bf215546Sopenharmony_ci ubyte vertices_per_patch) 65bf215546Sopenharmony_ci{ 66bf215546Sopenharmony_ci enum pipe_error ret; 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWARRAYS); 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_ci SVGA_RETRY_OOM(svga, ret, svga_hwtnl_draw_arrays(svga->hwtnl, prim, start, 71bf215546Sopenharmony_ci count, start_instance, 72bf215546Sopenharmony_ci instance_count, 73bf215546Sopenharmony_ci vertices_per_patch)); 74bf215546Sopenharmony_ci SVGA_STATS_TIME_POP(svga_sws(svga)); 75bf215546Sopenharmony_ci return ret; 76bf215546Sopenharmony_ci} 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci/** 80bf215546Sopenharmony_ci * Auto draw (get vertex count from a transform feedback result). 81bf215546Sopenharmony_ci */ 82bf215546Sopenharmony_cistatic enum pipe_error 83bf215546Sopenharmony_ciretry_draw_auto(struct svga_context *svga, 84bf215546Sopenharmony_ci const struct pipe_draw_info *info, 85bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect) 86bf215546Sopenharmony_ci{ 87bf215546Sopenharmony_ci assert(svga_have_sm5(svga)); 88bf215546Sopenharmony_ci assert(indirect->count_from_stream_output); 89bf215546Sopenharmony_ci assert(info->instance_count == 1); 90bf215546Sopenharmony_ci /* SO drawing implies core profile and none of these prim types */ 91bf215546Sopenharmony_ci assert(info->mode != PIPE_PRIM_QUADS && 92bf215546Sopenharmony_ci info->mode != PIPE_PRIM_QUAD_STRIP && 93bf215546Sopenharmony_ci info->mode != PIPE_PRIM_POLYGON); 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci if (info->mode == PIPE_PRIM_LINE_LOOP) { 96bf215546Sopenharmony_ci /* XXX need to do a fallback */ 97bf215546Sopenharmony_ci assert(!"draw auto fallback not supported yet"); 98bf215546Sopenharmony_ci return PIPE_OK; 99bf215546Sopenharmony_ci } 100bf215546Sopenharmony_ci else { 101bf215546Sopenharmony_ci SVGA3dPrimitiveRange range; 102bf215546Sopenharmony_ci unsigned hw_count; 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_ci range.primType = svga_translate_prim(info->mode, 12, &hw_count, 105bf215546Sopenharmony_ci svga->patch_vertices); 106bf215546Sopenharmony_ci range.primitiveCount = 0; 107bf215546Sopenharmony_ci range.indexArray.surfaceId = SVGA3D_INVALID_ID; 108bf215546Sopenharmony_ci range.indexArray.offset = 0; 109bf215546Sopenharmony_ci range.indexArray.stride = 0; 110bf215546Sopenharmony_ci range.indexWidth = 0; 111bf215546Sopenharmony_ci range.indexBias = 0; 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci SVGA_RETRY(svga, svga_hwtnl_prim 114bf215546Sopenharmony_ci (svga->hwtnl, &range, 115bf215546Sopenharmony_ci 0, /* vertex count comes from SO buffer */ 116bf215546Sopenharmony_ci 0, /* don't know min index */ 117bf215546Sopenharmony_ci ~0u, /* don't know max index */ 118bf215546Sopenharmony_ci NULL, /* no index buffer */ 119bf215546Sopenharmony_ci 0, /* start instance */ 120bf215546Sopenharmony_ci 1, /* only 1 instance supported */ 121bf215546Sopenharmony_ci NULL, /* indirect drawing info */ 122bf215546Sopenharmony_ci indirect->count_from_stream_output)); 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci return PIPE_OK; 125bf215546Sopenharmony_ci } 126bf215546Sopenharmony_ci} 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci/** 130bf215546Sopenharmony_ci * Indirect draw (get vertex count, start index, etc. from a buffer object. 131bf215546Sopenharmony_ci */ 132bf215546Sopenharmony_cistatic enum pipe_error 133bf215546Sopenharmony_ciretry_draw_indirect(struct svga_context *svga, 134bf215546Sopenharmony_ci const struct pipe_draw_info *info, 135bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect) 136bf215546Sopenharmony_ci{ 137bf215546Sopenharmony_ci assert(svga_have_sm5(svga)); 138bf215546Sopenharmony_ci assert(indirect && indirect->buffer); 139bf215546Sopenharmony_ci /* indirect drawing implies core profile and none of these prim types */ 140bf215546Sopenharmony_ci assert(info->mode != PIPE_PRIM_QUADS && 141bf215546Sopenharmony_ci info->mode != PIPE_PRIM_QUAD_STRIP && 142bf215546Sopenharmony_ci info->mode != PIPE_PRIM_POLYGON); 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci if (info->mode == PIPE_PRIM_LINE_LOOP) { 145bf215546Sopenharmony_ci /* need to do a fallback */ 146bf215546Sopenharmony_ci util_draw_indirect(&svga->pipe, info, indirect); 147bf215546Sopenharmony_ci return PIPE_OK; 148bf215546Sopenharmony_ci } 149bf215546Sopenharmony_ci else { 150bf215546Sopenharmony_ci SVGA3dPrimitiveRange range; 151bf215546Sopenharmony_ci unsigned hw_count; 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci range.primType = svga_translate_prim(info->mode, 12, &hw_count, 154bf215546Sopenharmony_ci svga->patch_vertices); 155bf215546Sopenharmony_ci range.primitiveCount = 0; /* specified in indirect buffer */ 156bf215546Sopenharmony_ci range.indexArray.surfaceId = SVGA3D_INVALID_ID; 157bf215546Sopenharmony_ci range.indexArray.offset = 0; 158bf215546Sopenharmony_ci range.indexArray.stride = 0; 159bf215546Sopenharmony_ci range.indexWidth = info->index_size; 160bf215546Sopenharmony_ci range.indexBias = 0; /* specified in indirect buffer */ 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci SVGA_RETRY(svga, svga_hwtnl_prim 163bf215546Sopenharmony_ci (svga->hwtnl, &range, 164bf215546Sopenharmony_ci 0, /* vertex count is in indirect buffer */ 165bf215546Sopenharmony_ci 0, /* don't know min index */ 166bf215546Sopenharmony_ci ~0u, /* don't know max index */ 167bf215546Sopenharmony_ci info->index.resource, 168bf215546Sopenharmony_ci info->start_instance, 169bf215546Sopenharmony_ci 0, /* don't know instance count */ 170bf215546Sopenharmony_ci indirect, 171bf215546Sopenharmony_ci NULL)); /* SO vertex count */ 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci return PIPE_OK; 174bf215546Sopenharmony_ci } 175bf215546Sopenharmony_ci} 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci/** 179bf215546Sopenharmony_ci * Determine if we need to implement primitive restart with a fallback 180bf215546Sopenharmony_ci * path which breaks the original primitive into sub-primitive at the 181bf215546Sopenharmony_ci * restart indexes. 182bf215546Sopenharmony_ci */ 183bf215546Sopenharmony_cistatic boolean 184bf215546Sopenharmony_cineed_fallback_prim_restart(const struct svga_context *svga, 185bf215546Sopenharmony_ci const struct pipe_draw_info *info) 186bf215546Sopenharmony_ci{ 187bf215546Sopenharmony_ci if (info->primitive_restart && info->index_size) { 188bf215546Sopenharmony_ci if (!svga_have_vgpu10(svga)) 189bf215546Sopenharmony_ci return TRUE; 190bf215546Sopenharmony_ci else if (!svga->state.sw.need_swtnl) { 191bf215546Sopenharmony_ci if (info->index_size == 1) 192bf215546Sopenharmony_ci return TRUE; /* no device support for 1-byte indexes */ 193bf215546Sopenharmony_ci else if (info->index_size == 2) 194bf215546Sopenharmony_ci return info->restart_index != 0xffff; 195bf215546Sopenharmony_ci else 196bf215546Sopenharmony_ci return info->restart_index != 0xffffffff; 197bf215546Sopenharmony_ci } 198bf215546Sopenharmony_ci } 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci return FALSE; 201bf215546Sopenharmony_ci} 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci/** 205bf215546Sopenharmony_ci * A helper function to return the vertex count from the primitive count 206bf215546Sopenharmony_ci * returned from the stream output statistics query for the specified stream. 207bf215546Sopenharmony_ci */ 208bf215546Sopenharmony_cistatic unsigned 209bf215546Sopenharmony_ciget_vcount_from_stream_output(struct svga_context *svga, 210bf215546Sopenharmony_ci const struct pipe_draw_info *info, 211bf215546Sopenharmony_ci unsigned stream) 212bf215546Sopenharmony_ci{ 213bf215546Sopenharmony_ci unsigned primcount; 214bf215546Sopenharmony_ci primcount = svga_get_primcount_from_stream_output(svga, stream); 215bf215546Sopenharmony_ci return u_vertices_for_prims(info->mode, primcount); 216bf215546Sopenharmony_ci} 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_cistatic void 220bf215546Sopenharmony_cisvga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info, 221bf215546Sopenharmony_ci unsigned drawid_offset, 222bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect, 223bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 224bf215546Sopenharmony_ci unsigned num_draws) 225bf215546Sopenharmony_ci{ 226bf215546Sopenharmony_ci if (num_draws > 1) { 227bf215546Sopenharmony_ci util_draw_multi(pipe, info, drawid_offset, indirect, draws, num_draws); 228bf215546Sopenharmony_ci return; 229bf215546Sopenharmony_ci } 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci if (!indirect && (!draws[0].count || !info->instance_count)) 232bf215546Sopenharmony_ci return; 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci struct svga_context *svga = svga_context(pipe); 235bf215546Sopenharmony_ci enum pipe_prim_type reduced_prim = u_reduced_prim(info->mode); 236bf215546Sopenharmony_ci unsigned count = draws[0].count; 237bf215546Sopenharmony_ci enum pipe_error ret = 0; 238bf215546Sopenharmony_ci boolean needed_swtnl; 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWVBO); 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci svga->hud.num_draw_calls++; /* for SVGA_QUERY_NUM_DRAW_CALLS */ 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci if (u_reduced_prim(info->mode) == PIPE_PRIM_TRIANGLES && 245bf215546Sopenharmony_ci svga->curr.rast->templ.cull_face == PIPE_FACE_FRONT_AND_BACK) 246bf215546Sopenharmony_ci goto done; 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci /* 249bf215546Sopenharmony_ci * Mark currently bound target surfaces as dirty 250bf215546Sopenharmony_ci * doesn't really matter if it is done before drawing. 251bf215546Sopenharmony_ci * 252bf215546Sopenharmony_ci * TODO If we ever normaly return something other then 253bf215546Sopenharmony_ci * true we should not mark it as dirty then. 254bf215546Sopenharmony_ci */ 255bf215546Sopenharmony_ci svga_mark_surfaces_dirty(svga_context(pipe)); 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci if (svga->curr.reduced_prim != reduced_prim) { 258bf215546Sopenharmony_ci svga->curr.reduced_prim = reduced_prim; 259bf215546Sopenharmony_ci svga->dirty |= SVGA_NEW_REDUCED_PRIMITIVE; 260bf215546Sopenharmony_ci } 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci /* We need to adjust the vertexID in the vertex shader since SV_VertexID 263bf215546Sopenharmony_ci * always start from 0 for DrawArrays and does not include baseVertex for 264bf215546Sopenharmony_ci * DrawIndexed. 265bf215546Sopenharmony_ci */ 266bf215546Sopenharmony_ci unsigned index_bias = info->index_size ? draws->index_bias : 0; 267bf215546Sopenharmony_ci if (svga->curr.vertex_id_bias != (draws[0].start + index_bias)) { 268bf215546Sopenharmony_ci svga->curr.vertex_id_bias = draws[0].start + index_bias; 269bf215546Sopenharmony_ci svga->dirty |= SVGA_NEW_VS_CONSTS; 270bf215546Sopenharmony_ci } 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci if (svga->curr.vertices_per_patch != svga->patch_vertices) { 273bf215546Sopenharmony_ci svga->curr.vertices_per_patch = svga->patch_vertices; 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_ci /* If input patch size changes, we need to notifiy the TCS 276bf215546Sopenharmony_ci * code to reevaluate the shader variant since the 277bf215546Sopenharmony_ci * vertices per patch count is a constant in the control 278bf215546Sopenharmony_ci * point count declaration. 279bf215546Sopenharmony_ci */ 280bf215546Sopenharmony_ci if (svga->curr.tcs || svga->curr.tes) 281bf215546Sopenharmony_ci svga->dirty |= SVGA_NEW_TCS_PARAM; 282bf215546Sopenharmony_ci } 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci if (need_fallback_prim_restart(svga, info)) { 285bf215546Sopenharmony_ci enum pipe_error r; 286bf215546Sopenharmony_ci r = util_draw_vbo_without_prim_restart(pipe, info, drawid_offset, indirect, &draws[0]); 287bf215546Sopenharmony_ci assert(r == PIPE_OK); 288bf215546Sopenharmony_ci (void) r; 289bf215546Sopenharmony_ci goto done; 290bf215546Sopenharmony_ci } 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci if (!indirect && !u_trim_pipe_prim(info->mode, &count)) 293bf215546Sopenharmony_ci goto done; 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci needed_swtnl = svga->state.sw.need_swtnl; 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci svga_update_state_retry(svga, SVGA_STATE_NEED_SWTNL); 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci if (svga->state.sw.need_swtnl) { 300bf215546Sopenharmony_ci svga->hud.num_fallbacks++; /* for SVGA_QUERY_NUM_FALLBACKS */ 301bf215546Sopenharmony_ci if (!needed_swtnl) { 302bf215546Sopenharmony_ci /* 303bf215546Sopenharmony_ci * We're switching from HW to SW TNL. SW TNL will require mapping all 304bf215546Sopenharmony_ci * currently bound vertex buffers, some of which may already be 305bf215546Sopenharmony_ci * referenced in the current command buffer as result of previous HW 306bf215546Sopenharmony_ci * TNL. So flush now, to prevent the context to flush while a referred 307bf215546Sopenharmony_ci * vertex buffer is mapped. 308bf215546Sopenharmony_ci */ 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_ci svga_context_flush(svga, NULL); 311bf215546Sopenharmony_ci } 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci /* Avoid leaking the previous hwtnl bias to swtnl */ 314bf215546Sopenharmony_ci svga_hwtnl_set_index_bias(svga->hwtnl, 0); 315bf215546Sopenharmony_ci ret = svga_swtnl_draw_vbo(svga, info, drawid_offset, indirect, &draws[0]); 316bf215546Sopenharmony_ci } 317bf215546Sopenharmony_ci else { 318bf215546Sopenharmony_ci if (!svga_update_state_retry(svga, SVGA_STATE_HW_DRAW)) { 319bf215546Sopenharmony_ci static const char *msg = "State update failed, skipping draw call"; 320bf215546Sopenharmony_ci debug_printf("%s\n", msg); 321bf215546Sopenharmony_ci util_debug_message(&svga->debug.callback, INFO, "%s", msg); 322bf215546Sopenharmony_ci goto done; 323bf215546Sopenharmony_ci } 324bf215546Sopenharmony_ci svga_hwtnl_set_fillmode(svga->hwtnl, svga->curr.rast->hw_fillmode); 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci svga_update_state_retry(svga, SVGA_STATE_HW_DRAW); 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci /** determine if flatshade is to be used after svga_update_state() 329bf215546Sopenharmony_ci * in case the fragment shader is changed. 330bf215546Sopenharmony_ci */ 331bf215546Sopenharmony_ci svga_hwtnl_set_flatshade(svga->hwtnl, 332bf215546Sopenharmony_ci svga->curr.rast->templ.flatshade || 333bf215546Sopenharmony_ci svga_is_using_flat_shading(svga), 334bf215546Sopenharmony_ci svga->curr.rast->templ.flatshade_first); 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_ci if (indirect && indirect->count_from_stream_output) { 337bf215546Sopenharmony_ci unsigned stream = 0; 338bf215546Sopenharmony_ci assert(count == 0); 339bf215546Sopenharmony_ci 340bf215546Sopenharmony_ci /* If the vertex count is from the stream output of a non-zero stream 341bf215546Sopenharmony_ci * or the draw info specifies instancing, we will need a workaround 342bf215546Sopenharmony_ci * since the draw_auto command does not support stream instancing. 343bf215546Sopenharmony_ci * The workaround requires querying the vertex count from the 344bf215546Sopenharmony_ci * stream output statistics query for the specified stream and then 345bf215546Sopenharmony_ci * fallback to the regular draw function. 346bf215546Sopenharmony_ci */ 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_ci /* Check the stream index of the specified stream output target */ 349bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(svga->so_targets); i++) { 350bf215546Sopenharmony_ci if (svga->vcount_so_targets[i] == indirect->count_from_stream_output) { 351bf215546Sopenharmony_ci stream = (svga->vcount_buffer_stream >> (i * 4)) & 0xf; 352bf215546Sopenharmony_ci break; 353bf215546Sopenharmony_ci } 354bf215546Sopenharmony_ci } 355bf215546Sopenharmony_ci if (info->instance_count > 1 || stream > 0) { 356bf215546Sopenharmony_ci count = get_vcount_from_stream_output(svga, info, stream); 357bf215546Sopenharmony_ci } 358bf215546Sopenharmony_ci } 359bf215546Sopenharmony_ci 360bf215546Sopenharmony_ci if (indirect && indirect->count_from_stream_output && count == 0) { 361bf215546Sopenharmony_ci ret = retry_draw_auto(svga, info, indirect); 362bf215546Sopenharmony_ci } 363bf215546Sopenharmony_ci else if (indirect && indirect->buffer) { 364bf215546Sopenharmony_ci ret = retry_draw_indirect(svga, info, indirect); 365bf215546Sopenharmony_ci } 366bf215546Sopenharmony_ci else if (info->index_size) { 367bf215546Sopenharmony_ci ret = retry_draw_range_elements(svga, info, &draws[0], count); 368bf215546Sopenharmony_ci } 369bf215546Sopenharmony_ci else { 370bf215546Sopenharmony_ci ret = retry_draw_arrays(svga, info->mode, draws[0].start, count, 371bf215546Sopenharmony_ci info->start_instance, info->instance_count, 372bf215546Sopenharmony_ci svga->patch_vertices); 373bf215546Sopenharmony_ci } 374bf215546Sopenharmony_ci } 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci /* XXX: Silence warnings, do something sensible here? */ 377bf215546Sopenharmony_ci (void)ret; 378bf215546Sopenharmony_ci 379bf215546Sopenharmony_ci if (SVGA_DEBUG & DEBUG_FLUSH) { 380bf215546Sopenharmony_ci svga_hwtnl_flush_retry(svga); 381bf215546Sopenharmony_ci svga_context_flush(svga, NULL); 382bf215546Sopenharmony_ci } 383bf215546Sopenharmony_ci 384bf215546Sopenharmony_cidone: 385bf215546Sopenharmony_ci SVGA_STATS_TIME_POP(svga_sws(svga)); 386bf215546Sopenharmony_ci} 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci 389bf215546Sopenharmony_civoid 390bf215546Sopenharmony_cisvga_init_draw_functions(struct svga_context *svga) 391bf215546Sopenharmony_ci{ 392bf215546Sopenharmony_ci svga->pipe.draw_vbo = svga_draw_vbo; 393bf215546Sopenharmony_ci} 394