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