Path: blob/21.2-virgl/src/gallium/auxiliary/indices/u_indices.c
4565 views
/*1* Copyright 2009 VMware, Inc.2* All Rights Reserved.3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the "Software"),6* to deal in the Software without restriction, including without limitation7* on the rights to use, copy, modify, merge, publish, distribute, sub8* license, and/or sell copies of the Software, and to permit persons to whom9* the Software is furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice (including the next12* paragraph) shall be included in all copies or substantial portions of the13* Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL18* VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,19* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR20* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE21* USE OR OTHER DEALINGS IN THE SOFTWARE.22*/2324#include "u_indices.h"25#include "u_indices_priv.h"2627static void translate_memcpy_ushort( const void *in,28unsigned start,29unsigned in_nr,30unsigned out_nr,31unsigned restart_index,32void *out )33{34memcpy(out, &((short *)in)[start], out_nr*sizeof(short));35}3637static void translate_memcpy_uint( const void *in,38unsigned start,39unsigned in_nr,40unsigned out_nr,41unsigned restart_index,42void *out )43{44memcpy(out, &((int *)in)[start], out_nr*sizeof(int));45}4647static void translate_byte_to_ushort( const void *in,48unsigned start,49UNUSED unsigned in_nr,50unsigned out_nr,51UNUSED unsigned restart_index,52void *out )53{54uint8_t *src = (uint8_t *)in + start;55uint16_t *dst = out;56while (out_nr--) {57*dst++ = *src++;58}59}6061enum pipe_prim_type62u_index_prim_type_convert(unsigned hw_mask, enum pipe_prim_type prim, bool pv_matches)63{64if ((hw_mask & (1<<prim)) && pv_matches)65return prim;6667switch (prim) {68case PIPE_PRIM_POINTS:69return PIPE_PRIM_POINTS;70case PIPE_PRIM_LINES:71case PIPE_PRIM_LINE_STRIP:72case PIPE_PRIM_LINE_LOOP:73return PIPE_PRIM_LINES;74case PIPE_PRIM_TRIANGLES:75case PIPE_PRIM_TRIANGLE_STRIP:76case PIPE_PRIM_TRIANGLE_FAN:77case PIPE_PRIM_QUADS:78case PIPE_PRIM_QUAD_STRIP:79case PIPE_PRIM_POLYGON:80return PIPE_PRIM_TRIANGLES;81case PIPE_PRIM_LINES_ADJACENCY:82case PIPE_PRIM_LINE_STRIP_ADJACENCY:83return PIPE_PRIM_LINES_ADJACENCY;84case PIPE_PRIM_TRIANGLES_ADJACENCY:85case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:86return PIPE_PRIM_TRIANGLES_ADJACENCY;87default:88assert(0);89break;90}91return PIPE_PRIM_POINTS;92}9394/**95* Translate indexes when a driver can't support certain types96* of drawing. Example include:97* - Translate 1-byte indexes into 2-byte indexes98* - Translate PIPE_PRIM_QUADS into PIPE_PRIM_TRIANGLES when the hardware99* doesn't support the former.100* - Translate from first provoking vertex to last provoking vertex and101* vice versa.102*103* Note that this function is used for indexed primitives.104*105* \param hw_mask mask of (1 << PIPE_PRIM_x) flags indicating which types106* of primitives are supported by the hardware.107* \param prim incoming PIPE_PRIM_x108* \param in_index_size bytes per index value (1, 2 or 4)109* \param nr number of incoming vertices110* \param in_pv incoming provoking vertex convention (PV_FIRST or PV_LAST)111* \param out_pv desired provoking vertex convention (PV_FIRST or PV_LAST)112* \param prim_restart whether primitive restart is disable or enabled113* \param out_prim returns new PIPE_PRIM_x we'll translate to114* \param out_index_size returns bytes per new index value (2 or 4)115* \param out_nr returns number of new vertices116* \param out_translate returns the translation function to use by the caller117*/118enum indices_mode119u_index_translator(unsigned hw_mask,120enum pipe_prim_type prim,121unsigned in_index_size,122unsigned nr,123unsigned in_pv,124unsigned out_pv,125unsigned prim_restart,126enum pipe_prim_type *out_prim,127unsigned *out_index_size,128unsigned *out_nr,129u_translate_func *out_translate)130{131unsigned in_idx;132unsigned out_idx;133enum indices_mode ret = U_TRANSLATE_NORMAL;134135assert(in_index_size == 1 ||136in_index_size == 2 ||137in_index_size == 4);138139u_index_init();140141in_idx = in_size_idx(in_index_size);142*out_index_size = u_index_size_convert(in_index_size);143out_idx = out_size_idx(*out_index_size);144145if ((hw_mask & (1<<prim)) &&146in_pv == out_pv)147{148if (in_index_size == 4)149*out_translate = translate_memcpy_uint;150else if (in_index_size == 2)151*out_translate = translate_memcpy_ushort;152else153*out_translate = translate_byte_to_ushort;154155*out_prim = prim;156*out_nr = nr;157158return U_TRANSLATE_MEMCPY;159}160*out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim];161*out_prim = u_index_prim_type_convert(hw_mask, prim, in_pv == out_pv);162*out_nr = u_index_count_converted_indices(hw_mask, in_pv == out_pv, prim, nr);163164return ret;165}166167unsigned168u_index_count_converted_indices(unsigned hw_mask, bool pv_matches, enum pipe_prim_type prim, unsigned nr)169{170if ((hw_mask & (1<<prim)) && pv_matches)171return nr;172173switch (prim) {174case PIPE_PRIM_POINTS:175return nr;176case PIPE_PRIM_LINES:177return nr;178case PIPE_PRIM_LINE_STRIP:179return (nr - 1) * 2;180case PIPE_PRIM_LINE_LOOP:181return nr * 2;182case PIPE_PRIM_TRIANGLES:183return nr;184case PIPE_PRIM_TRIANGLE_STRIP:185return (nr - 2) * 3;186case PIPE_PRIM_TRIANGLE_FAN:187return (nr - 2) * 3;188case PIPE_PRIM_QUADS:189return (nr / 4) * 6;190case PIPE_PRIM_QUAD_STRIP:191return (nr - 2) * 3;192case PIPE_PRIM_POLYGON:193return (nr - 2) * 3;194case PIPE_PRIM_LINES_ADJACENCY:195return nr;196case PIPE_PRIM_LINE_STRIP_ADJACENCY:197return (nr - 3) * 4;198case PIPE_PRIM_TRIANGLES_ADJACENCY:199return nr;200case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:201return ((nr - 4) / 2) * 6;202default:203assert(0);204break;205}206return nr;207}208209210/**211* If a driver does not support a particular gallium primitive type212* (such as PIPE_PRIM_QUAD_STRIP) this function can be used to help213* convert the primitive into a simpler type (like PIPE_PRIM_TRIANGLES).214*215* The generator functions generates a number of ushort or uint indexes216* for drawing the new type of primitive.217*218* Note that this function is used for non-indexed primitives.219*220* \param hw_mask a bitmask of (1 << PIPE_PRIM_x) values that indicates221* kind of primitives are supported by the driver.222* \param prim the PIPE_PRIM_x that the user wants to draw223* \param start index of first vertex to draw224* \param nr number of vertices to draw225* \param in_pv user's provoking vertex (PV_FIRST/LAST)226* \param out_pv desired proking vertex for the hardware (PV_FIRST/LAST)227* \param out_prim returns the new primitive type for the driver228* \param out_index_size returns OUT_USHORT or OUT_UINT229* \param out_nr returns new number of vertices to draw230* \param out_generate returns pointer to the generator function231*/232enum indices_mode233u_index_generator(unsigned hw_mask,234enum pipe_prim_type prim,235unsigned start,236unsigned nr,237unsigned in_pv,238unsigned out_pv,239enum pipe_prim_type *out_prim,240unsigned *out_index_size,241unsigned *out_nr,242u_generate_func *out_generate)243{244unsigned out_idx;245246u_index_init();247248*out_index_size = ((start + nr) > 0xfffe) ? 4 : 2;249out_idx = out_size_idx(*out_index_size);250*out_prim = u_index_prim_type_convert(hw_mask, prim, in_pv == out_pv);251*out_nr = u_index_count_converted_indices(hw_mask, in_pv == out_pv, prim, nr);252253if ((hw_mask & (1<<prim)) &&254(in_pv == out_pv)) {255256*out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS];257return U_GENERATE_LINEAR;258}259*out_generate = generate[out_idx][in_pv][out_pv][prim];260return prim == PIPE_PRIM_LINE_LOOP ? U_GENERATE_ONE_OFF : U_GENERATE_REUSABLE;261}262263264