1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2013 Rob Clark <robclark@freedesktop.org> 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci * Authors: 24bf215546Sopenharmony_ci * Rob Clark <robclark@freedesktop.org> 25bf215546Sopenharmony_ci */ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci/** 28bf215546Sopenharmony_ci * This module converts provides a more convenient front-end to u_indices, 29bf215546Sopenharmony_ci * etc, utils to convert primitive types supported not supported by the 30bf215546Sopenharmony_ci * hardware. It handles binding new index buffer state, and restoring 31bf215546Sopenharmony_ci * previous state after. To use, put something like this at the front of 32bf215546Sopenharmony_ci * drivers pipe->draw_vbo(): 33bf215546Sopenharmony_ci * 34bf215546Sopenharmony_ci * // emulate unsupported primitives: 35bf215546Sopenharmony_ci * if (info->mode needs emulating) { 36bf215546Sopenharmony_ci * util_primconvert_save_rasterizer_state(ctx->primconvert, ctx->rasterizer); 37bf215546Sopenharmony_ci * util_primconvert_draw_vbo(ctx->primconvert, info); 38bf215546Sopenharmony_ci * return; 39bf215546Sopenharmony_ci * } 40bf215546Sopenharmony_ci * 41bf215546Sopenharmony_ci */ 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci#include "pipe/p_state.h" 44bf215546Sopenharmony_ci#include "util/u_draw.h" 45bf215546Sopenharmony_ci#include "util/u_inlines.h" 46bf215546Sopenharmony_ci#include "util/u_memory.h" 47bf215546Sopenharmony_ci#include "util/u_prim.h" 48bf215546Sopenharmony_ci#include "util/u_prim_restart.h" 49bf215546Sopenharmony_ci#include "util/u_upload_mgr.h" 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci#include "indices/u_indices.h" 52bf215546Sopenharmony_ci#include "indices/u_primconvert.h" 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_cistruct primconvert_context 55bf215546Sopenharmony_ci{ 56bf215546Sopenharmony_ci struct pipe_context *pipe; 57bf215546Sopenharmony_ci struct primconvert_config cfg; 58bf215546Sopenharmony_ci unsigned api_pv; 59bf215546Sopenharmony_ci}; 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_cistruct primconvert_context * 63bf215546Sopenharmony_ciutil_primconvert_create_config(struct pipe_context *pipe, 64bf215546Sopenharmony_ci struct primconvert_config *cfg) 65bf215546Sopenharmony_ci{ 66bf215546Sopenharmony_ci struct primconvert_context *pc = CALLOC_STRUCT(primconvert_context); 67bf215546Sopenharmony_ci if (!pc) 68bf215546Sopenharmony_ci return NULL; 69bf215546Sopenharmony_ci pc->pipe = pipe; 70bf215546Sopenharmony_ci pc->cfg = *cfg; 71bf215546Sopenharmony_ci return pc; 72bf215546Sopenharmony_ci} 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_cistruct primconvert_context * 75bf215546Sopenharmony_ciutil_primconvert_create(struct pipe_context *pipe, uint32_t primtypes_mask) 76bf215546Sopenharmony_ci{ 77bf215546Sopenharmony_ci struct primconvert_config cfg = { .primtypes_mask = primtypes_mask, .restart_primtypes_mask = primtypes_mask }; 78bf215546Sopenharmony_ci return util_primconvert_create_config(pipe, &cfg); 79bf215546Sopenharmony_ci} 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_civoid 82bf215546Sopenharmony_ciutil_primconvert_destroy(struct primconvert_context *pc) 83bf215546Sopenharmony_ci{ 84bf215546Sopenharmony_ci FREE(pc); 85bf215546Sopenharmony_ci} 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_civoid 88bf215546Sopenharmony_ciutil_primconvert_save_rasterizer_state(struct primconvert_context *pc, 89bf215546Sopenharmony_ci const struct pipe_rasterizer_state 90bf215546Sopenharmony_ci *rast) 91bf215546Sopenharmony_ci{ 92bf215546Sopenharmony_ci util_primconvert_save_flatshade_first(pc, rast->flatshade_first); 93bf215546Sopenharmony_ci} 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_civoid 96bf215546Sopenharmony_ciutil_primconvert_save_flatshade_first(struct primconvert_context *pc, bool flatshade_first) 97bf215546Sopenharmony_ci{ 98bf215546Sopenharmony_ci /* if we actually translated the provoking vertex for the buffer, 99bf215546Sopenharmony_ci * we would actually need to save/restore rasterizer state. As 100bf215546Sopenharmony_ci * it is, we just need to make note of the pv. 101bf215546Sopenharmony_ci */ 102bf215546Sopenharmony_ci pc->api_pv = flatshade_first ? PV_FIRST : PV_LAST; 103bf215546Sopenharmony_ci} 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_cistatic bool 106bf215546Sopenharmony_ciprimconvert_init_draw(struct primconvert_context *pc, 107bf215546Sopenharmony_ci const struct pipe_draw_info *info, 108bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 109bf215546Sopenharmony_ci struct pipe_draw_info *new_info, 110bf215546Sopenharmony_ci struct pipe_draw_start_count_bias *new_draw) 111bf215546Sopenharmony_ci{ 112bf215546Sopenharmony_ci struct pipe_draw_start_count_bias *direct_draws = NULL; 113bf215546Sopenharmony_ci unsigned num_direct_draws = 0; 114bf215546Sopenharmony_ci struct pipe_transfer *src_transfer = NULL; 115bf215546Sopenharmony_ci u_translate_func trans_func, direct_draw_func; 116bf215546Sopenharmony_ci u_generate_func gen_func; 117bf215546Sopenharmony_ci const void *src = NULL; 118bf215546Sopenharmony_ci void *dst; 119bf215546Sopenharmony_ci unsigned ib_offset; 120bf215546Sopenharmony_ci unsigned total_index_count = draws->count; 121bf215546Sopenharmony_ci void *rewrite_buffer = NULL; 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci struct pipe_draw_start_count_bias draw = draws[0]; 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci /* Filter out degenerate primitives, u_upload_alloc() will assert 126bf215546Sopenharmony_ci * on size==0 so just bail: 127bf215546Sopenharmony_ci */ 128bf215546Sopenharmony_ci if (!info->primitive_restart && 129bf215546Sopenharmony_ci !u_trim_pipe_prim(info->mode, (unsigned*)&draw.count)) 130bf215546Sopenharmony_ci return false; 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci util_draw_init_info(new_info); 133bf215546Sopenharmony_ci new_info->index_bounds_valid = info->index_bounds_valid; 134bf215546Sopenharmony_ci new_info->min_index = info->min_index; 135bf215546Sopenharmony_ci new_info->max_index = info->max_index; 136bf215546Sopenharmony_ci new_info->start_instance = info->start_instance; 137bf215546Sopenharmony_ci new_info->instance_count = info->instance_count; 138bf215546Sopenharmony_ci new_info->primitive_restart = info->primitive_restart; 139bf215546Sopenharmony_ci new_info->restart_index = info->restart_index; 140bf215546Sopenharmony_ci if (info->index_size) { 141bf215546Sopenharmony_ci enum pipe_prim_type mode = new_info->mode = u_index_prim_type_convert(pc->cfg.primtypes_mask, info->mode, true); 142bf215546Sopenharmony_ci unsigned index_size = info->index_size; 143bf215546Sopenharmony_ci unsigned offset = draw.start * info->index_size; 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci new_info->index_size = u_index_size_convert(info->index_size); 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci src = info->has_user_indices ? info->index.user : NULL; 148bf215546Sopenharmony_ci if (!src) { 149bf215546Sopenharmony_ci /* Map the index range we're interested in (not the whole buffer) */ 150bf215546Sopenharmony_ci src = pipe_buffer_map_range(pc->pipe, info->index.resource, 151bf215546Sopenharmony_ci offset, 152bf215546Sopenharmony_ci draw.count * info->index_size, 153bf215546Sopenharmony_ci PIPE_MAP_READ, &src_transfer); 154bf215546Sopenharmony_ci offset = 0; 155bf215546Sopenharmony_ci draw.start = 0; 156bf215546Sopenharmony_ci } 157bf215546Sopenharmony_ci const void *restart_src = (const uint8_t *)src + offset; 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci /* if the resulting primitive type is not supported by the driver for primitive restart, 160bf215546Sopenharmony_ci * or if the original primitive type was not supported by the driver, 161bf215546Sopenharmony_ci * the draw needs to be rewritten to not use primitive restart 162bf215546Sopenharmony_ci */ 163bf215546Sopenharmony_ci if (info->primitive_restart && 164bf215546Sopenharmony_ci (!(pc->cfg.restart_primtypes_mask & BITFIELD_BIT(mode)) || 165bf215546Sopenharmony_ci !(pc->cfg.primtypes_mask & BITFIELD_BIT(info->mode)))) { 166bf215546Sopenharmony_ci /* step 1: rewrite draw to not use primitive primitive restart; 167bf215546Sopenharmony_ci * this pre-filters degenerate primitives 168bf215546Sopenharmony_ci */ 169bf215546Sopenharmony_ci direct_draws = util_prim_restart_convert_to_direct(restart_src, info, &draw, &num_direct_draws, 170bf215546Sopenharmony_ci &new_info->min_index, &new_info->max_index, &total_index_count); 171bf215546Sopenharmony_ci new_info->primitive_restart = false; 172bf215546Sopenharmony_ci /* step 2: get a translator function which does nothing but handle any index size conversions 173bf215546Sopenharmony_ci * which may or may not occur (8bit -> 16bit) 174bf215546Sopenharmony_ci */ 175bf215546Sopenharmony_ci u_index_translator(0xffff, 176bf215546Sopenharmony_ci info->mode, index_size, total_index_count, 177bf215546Sopenharmony_ci pc->api_pv, pc->api_pv, 178bf215546Sopenharmony_ci PR_DISABLE, 179bf215546Sopenharmony_ci &mode, &index_size, &new_draw->count, 180bf215546Sopenharmony_ci &direct_draw_func); 181bf215546Sopenharmony_ci /* this should always be a direct translation */ 182bf215546Sopenharmony_ci assert(new_draw->count == total_index_count); 183bf215546Sopenharmony_ci /* step 3: allocate a temp buffer for an intermediate rewrite step 184bf215546Sopenharmony_ci * if no indices were found, this was a single incomplete restart and can be discarded 185bf215546Sopenharmony_ci */ 186bf215546Sopenharmony_ci if (total_index_count) 187bf215546Sopenharmony_ci rewrite_buffer = malloc(index_size * total_index_count); 188bf215546Sopenharmony_ci if (!rewrite_buffer) { 189bf215546Sopenharmony_ci if (src_transfer) 190bf215546Sopenharmony_ci pipe_buffer_unmap(pc->pipe, src_transfer); 191bf215546Sopenharmony_ci return false; 192bf215546Sopenharmony_ci } 193bf215546Sopenharmony_ci } 194bf215546Sopenharmony_ci /* (step 4: get the actual primitive conversion translator function) */ 195bf215546Sopenharmony_ci u_index_translator(pc->cfg.primtypes_mask, 196bf215546Sopenharmony_ci info->mode, index_size, total_index_count, 197bf215546Sopenharmony_ci pc->api_pv, pc->api_pv, 198bf215546Sopenharmony_ci new_info->primitive_restart ? PR_ENABLE : PR_DISABLE, 199bf215546Sopenharmony_ci &mode, &index_size, &new_draw->count, 200bf215546Sopenharmony_ci &trans_func); 201bf215546Sopenharmony_ci assert(new_info->mode == mode); 202bf215546Sopenharmony_ci assert(new_info->index_size == index_size); 203bf215546Sopenharmony_ci } 204bf215546Sopenharmony_ci else { 205bf215546Sopenharmony_ci enum pipe_prim_type mode = 0; 206bf215546Sopenharmony_ci unsigned index_size; 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci u_index_generator(pc->cfg.primtypes_mask, 209bf215546Sopenharmony_ci info->mode, draw.start, draw.count, 210bf215546Sopenharmony_ci pc->api_pv, pc->api_pv, 211bf215546Sopenharmony_ci &mode, &index_size, &new_draw->count, 212bf215546Sopenharmony_ci &gen_func); 213bf215546Sopenharmony_ci new_info->mode = mode; 214bf215546Sopenharmony_ci new_info->index_size = index_size; 215bf215546Sopenharmony_ci } 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci /* (step 5: allocate gpu memory sized for the FINAL index count) */ 218bf215546Sopenharmony_ci u_upload_alloc(pc->pipe->stream_uploader, 0, new_info->index_size * new_draw->count, 4, 219bf215546Sopenharmony_ci &ib_offset, &new_info->index.resource, &dst); 220bf215546Sopenharmony_ci new_draw->start = ib_offset / new_info->index_size; 221bf215546Sopenharmony_ci new_draw->index_bias = info->index_size ? draw.index_bias : 0; 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci if (info->index_size) { 224bf215546Sopenharmony_ci if (num_direct_draws) { 225bf215546Sopenharmony_ci uint8_t *ptr = rewrite_buffer; 226bf215546Sopenharmony_ci uint8_t *dst_ptr = dst; 227bf215546Sopenharmony_ci /* step 6: if rewriting a prim-restart draw to direct draws, 228bf215546Sopenharmony_ci * loop over all the direct draws in order to rewrite them into a single index buffer 229bf215546Sopenharmony_ci * and draw in order to match the original call 230bf215546Sopenharmony_ci */ 231bf215546Sopenharmony_ci for (unsigned i = 0; i < num_direct_draws; i++) { 232bf215546Sopenharmony_ci /* step 6a: get the index count for this draw, once converted */ 233bf215546Sopenharmony_ci unsigned tmp_count = u_index_count_converted_indices(pc->cfg.primtypes_mask, true, info->mode, direct_draws[i].count); 234bf215546Sopenharmony_ci /* step 6b: handle index size conversion using the temp buffer; no change in index count 235bf215546Sopenharmony_ci * TODO: this step can be optimized out if the index size is known to not change 236bf215546Sopenharmony_ci */ 237bf215546Sopenharmony_ci direct_draw_func(src, direct_draws[i].start, direct_draws[i].count, direct_draws[i].count, info->restart_index, ptr); 238bf215546Sopenharmony_ci /* step 6c: handle the primitive type conversion rewriting to the converted index count */ 239bf215546Sopenharmony_ci trans_func(ptr, 0, direct_draws[i].count, tmp_count, info->restart_index, dst_ptr); 240bf215546Sopenharmony_ci /* step 6d: increment the temp buffer and mapped final index buffer pointers */ 241bf215546Sopenharmony_ci ptr += new_info->index_size * direct_draws[i].count; 242bf215546Sopenharmony_ci dst_ptr += new_info->index_size * tmp_count; 243bf215546Sopenharmony_ci } 244bf215546Sopenharmony_ci /* step 7: set the final index count, which is the converted total index count from the original draw rewrite */ 245bf215546Sopenharmony_ci new_draw->count = u_index_count_converted_indices(pc->cfg.primtypes_mask, true, info->mode, total_index_count); 246bf215546Sopenharmony_ci } else 247bf215546Sopenharmony_ci trans_func(src, draw.start, draw.count, new_draw->count, info->restart_index, dst); 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci if (pc->cfg.fixed_prim_restart && new_info->primitive_restart) { 250bf215546Sopenharmony_ci new_info->restart_index = (1ull << (new_info->index_size * 8)) - 1; 251bf215546Sopenharmony_ci if (info->restart_index != new_info->restart_index) 252bf215546Sopenharmony_ci util_translate_prim_restart_data(new_info->index_size, dst, dst, 253bf215546Sopenharmony_ci new_draw->count, 254bf215546Sopenharmony_ci info->restart_index); 255bf215546Sopenharmony_ci } 256bf215546Sopenharmony_ci } 257bf215546Sopenharmony_ci else { 258bf215546Sopenharmony_ci gen_func(draw.start, new_draw->count, dst); 259bf215546Sopenharmony_ci } 260bf215546Sopenharmony_ci new_info->was_line_loop = info->mode == PIPE_PRIM_LINE_LOOP; 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci if (src_transfer) 263bf215546Sopenharmony_ci pipe_buffer_unmap(pc->pipe, src_transfer); 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci u_upload_unmap(pc->pipe->stream_uploader); 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci free(direct_draws); 268bf215546Sopenharmony_ci free(rewrite_buffer); 269bf215546Sopenharmony_ci return true; 270bf215546Sopenharmony_ci} 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_cistatic void 273bf215546Sopenharmony_ciutil_primconvert_draw_single_vbo(struct primconvert_context *pc, 274bf215546Sopenharmony_ci const struct pipe_draw_info *info, 275bf215546Sopenharmony_ci unsigned drawid_offset, 276bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draw) 277bf215546Sopenharmony_ci{ 278bf215546Sopenharmony_ci struct pipe_draw_info new_info; 279bf215546Sopenharmony_ci struct pipe_draw_start_count_bias new_draw; 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci if (!primconvert_init_draw(pc, info, draw, &new_info, &new_draw)) 282bf215546Sopenharmony_ci return; 283bf215546Sopenharmony_ci /* to the translated draw: */ 284bf215546Sopenharmony_ci pc->pipe->draw_vbo(pc->pipe, &new_info, drawid_offset, NULL, &new_draw, 1); 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci pipe_resource_reference(&new_info.index.resource, NULL); 287bf215546Sopenharmony_ci} 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_civoid 290bf215546Sopenharmony_ciutil_primconvert_draw_vbo(struct primconvert_context *pc, 291bf215546Sopenharmony_ci const struct pipe_draw_info *info, 292bf215546Sopenharmony_ci unsigned drawid_offset, 293bf215546Sopenharmony_ci const struct pipe_draw_indirect_info *indirect, 294bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 295bf215546Sopenharmony_ci unsigned num_draws) 296bf215546Sopenharmony_ci{ 297bf215546Sopenharmony_ci if (indirect && indirect->buffer) { 298bf215546Sopenharmony_ci /* this is stupid, but we're already doing a readback, 299bf215546Sopenharmony_ci * so this thing may as well get the rest of the job done 300bf215546Sopenharmony_ci */ 301bf215546Sopenharmony_ci unsigned draw_count = 0; 302bf215546Sopenharmony_ci struct u_indirect_params *new_draws = util_draw_indirect_read(pc->pipe, info, indirect, &draw_count); 303bf215546Sopenharmony_ci if (!new_draws) 304bf215546Sopenharmony_ci goto cleanup; 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci for (unsigned i = 0; i < draw_count; i++) 307bf215546Sopenharmony_ci util_primconvert_draw_single_vbo(pc, &new_draws[i].info, drawid_offset + i, &new_draws[i].draw); 308bf215546Sopenharmony_ci free(new_draws); 309bf215546Sopenharmony_ci } else { 310bf215546Sopenharmony_ci unsigned drawid = drawid_offset; 311bf215546Sopenharmony_ci for (unsigned i = 0; i < num_draws; i++) { 312bf215546Sopenharmony_ci if (draws[i].count && info->instance_count) 313bf215546Sopenharmony_ci util_primconvert_draw_single_vbo(pc, info, drawid, &draws[i]); 314bf215546Sopenharmony_ci if (info->increment_draw_id) 315bf215546Sopenharmony_ci drawid++; 316bf215546Sopenharmony_ci } 317bf215546Sopenharmony_ci } 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_cicleanup: 320bf215546Sopenharmony_ci if (info->take_index_buffer_ownership) { 321bf215546Sopenharmony_ci struct pipe_resource *buffer = info->index.resource; 322bf215546Sopenharmony_ci pipe_resource_reference(&buffer, NULL); 323bf215546Sopenharmony_ci } 324bf215546Sopenharmony_ci} 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_civoid 327bf215546Sopenharmony_ciutil_primconvert_draw_vertex_state(struct primconvert_context *pc, 328bf215546Sopenharmony_ci struct pipe_vertex_state *vstate, 329bf215546Sopenharmony_ci uint32_t partial_velem_mask, 330bf215546Sopenharmony_ci struct pipe_draw_vertex_state_info info, 331bf215546Sopenharmony_ci const struct pipe_draw_start_count_bias *draws, 332bf215546Sopenharmony_ci unsigned num_draws) 333bf215546Sopenharmony_ci{ 334bf215546Sopenharmony_ci struct pipe_draw_info new_info; 335bf215546Sopenharmony_ci struct pipe_draw_start_count_bias new_draw; 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci if (pc->cfg.primtypes_mask & BITFIELD_BIT(info.mode)) { 338bf215546Sopenharmony_ci pc->pipe->draw_vertex_state(pc->pipe, vstate, partial_velem_mask, info, draws, num_draws); 339bf215546Sopenharmony_ci return; 340bf215546Sopenharmony_ci } 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci if (num_draws > 1) { 343bf215546Sopenharmony_ci for (unsigned i = 0; i < num_draws; i++) { 344bf215546Sopenharmony_ci if (draws[i].count) 345bf215546Sopenharmony_ci util_primconvert_draw_vertex_state(pc, vstate, partial_velem_mask, info, &draws[i], 1); 346bf215546Sopenharmony_ci } 347bf215546Sopenharmony_ci return; 348bf215546Sopenharmony_ci } 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci struct pipe_draw_info dinfo = {0}; 351bf215546Sopenharmony_ci dinfo.mode = info.mode; 352bf215546Sopenharmony_ci dinfo.index_size = 4; 353bf215546Sopenharmony_ci dinfo.instance_count = 1; 354bf215546Sopenharmony_ci dinfo.index.resource = vstate->input.indexbuf; 355bf215546Sopenharmony_ci if (!primconvert_init_draw(pc, &dinfo, draws, &new_info, &new_draw)) 356bf215546Sopenharmony_ci return; 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci struct pipe_vertex_state *new_state = pc->pipe->screen->create_vertex_state(pc->pipe->screen, 359bf215546Sopenharmony_ci &vstate->input.vbuffer, 360bf215546Sopenharmony_ci vstate->input.elements, 361bf215546Sopenharmony_ci vstate->input.num_elements, 362bf215546Sopenharmony_ci new_info.index.resource, 363bf215546Sopenharmony_ci vstate->input.full_velem_mask); 364bf215546Sopenharmony_ci if (new_state) { 365bf215546Sopenharmony_ci struct pipe_draw_vertex_state_info new_vinfo; 366bf215546Sopenharmony_ci new_vinfo.mode = new_info.mode; 367bf215546Sopenharmony_ci new_vinfo.take_vertex_state_ownership = true; 368bf215546Sopenharmony_ci /* to the translated draw: */ 369bf215546Sopenharmony_ci pc->pipe->draw_vertex_state(pc->pipe, new_state, partial_velem_mask, new_vinfo, &new_draw, 1); 370bf215546Sopenharmony_ci } 371bf215546Sopenharmony_ci if (info.take_vertex_state_ownership) 372bf215546Sopenharmony_ci pipe_vertex_state_reference(&vstate, NULL); 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci pipe_resource_reference(&new_info.index.resource, NULL); 375bf215546Sopenharmony_ci} 376