14a49301eSmrg/* 24a49301eSmrg * Copyright 2009 VMware, Inc. 34a49301eSmrg * All Rights Reserved. 44a49301eSmrg * 54a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 64a49301eSmrg * copy of this software and associated documentation files (the "Software"), 74a49301eSmrg * to deal in the Software without restriction, including without limitation 84a49301eSmrg * on the rights to use, copy, modify, merge, publish, distribute, sub 94a49301eSmrg * license, and/or sell copies of the Software, and to permit persons to whom 104a49301eSmrg * the Software is furnished to do so, subject to the following conditions: 114a49301eSmrg * 124a49301eSmrg * The above copyright notice and this permission notice (including the next 134a49301eSmrg * paragraph) shall be included in all copies or substantial portions of the 144a49301eSmrg * Software. 154a49301eSmrg * 164a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 174a49301eSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 184a49301eSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 194a49301eSmrg * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 204a49301eSmrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 214a49301eSmrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 224a49301eSmrg * USE OR OTHER DEALINGS IN THE SOFTWARE. 234a49301eSmrg */ 244a49301eSmrg 254a49301eSmrg#include "u_indices.h" 264a49301eSmrg#include "u_indices_priv.h" 274a49301eSmrg 284a49301eSmrgstatic void translate_memcpy_ushort( const void *in, 29af69d88dSmrg unsigned start, 3001e04c3fSmrg unsigned in_nr, 3101e04c3fSmrg unsigned out_nr, 3201e04c3fSmrg unsigned restart_index, 334a49301eSmrg void *out ) 344a49301eSmrg{ 3501e04c3fSmrg memcpy(out, &((short *)in)[start], out_nr*sizeof(short)); 364a49301eSmrg} 374a49301eSmrg 384a49301eSmrgstatic void translate_memcpy_uint( const void *in, 39af69d88dSmrg unsigned start, 4001e04c3fSmrg unsigned in_nr, 4101e04c3fSmrg unsigned out_nr, 4201e04c3fSmrg unsigned restart_index, 434a49301eSmrg void *out ) 444a49301eSmrg{ 4501e04c3fSmrg memcpy(out, &((int *)in)[start], out_nr*sizeof(int)); 464a49301eSmrg} 477ec681f3Smrg 487ec681f3Smrgstatic void translate_byte_to_ushort( const void *in, 497ec681f3Smrg unsigned start, 507ec681f3Smrg UNUSED unsigned in_nr, 517ec681f3Smrg unsigned out_nr, 527ec681f3Smrg UNUSED unsigned restart_index, 537ec681f3Smrg void *out ) 547ec681f3Smrg{ 557ec681f3Smrg uint8_t *src = (uint8_t *)in + start; 567ec681f3Smrg uint16_t *dst = out; 577ec681f3Smrg while (out_nr--) { 587ec681f3Smrg *dst++ = *src++; 597ec681f3Smrg } 607ec681f3Smrg} 617ec681f3Smrg 627ec681f3Smrgenum pipe_prim_type 637ec681f3Smrgu_index_prim_type_convert(unsigned hw_mask, enum pipe_prim_type prim, bool pv_matches) 647ec681f3Smrg{ 657ec681f3Smrg if ((hw_mask & (1<<prim)) && pv_matches) 667ec681f3Smrg return prim; 677ec681f3Smrg 687ec681f3Smrg switch (prim) { 697ec681f3Smrg case PIPE_PRIM_POINTS: 707ec681f3Smrg return PIPE_PRIM_POINTS; 717ec681f3Smrg case PIPE_PRIM_LINES: 727ec681f3Smrg case PIPE_PRIM_LINE_STRIP: 737ec681f3Smrg case PIPE_PRIM_LINE_LOOP: 747ec681f3Smrg return PIPE_PRIM_LINES; 757ec681f3Smrg case PIPE_PRIM_TRIANGLES: 767ec681f3Smrg case PIPE_PRIM_TRIANGLE_STRIP: 777ec681f3Smrg case PIPE_PRIM_TRIANGLE_FAN: 787ec681f3Smrg case PIPE_PRIM_QUADS: 797ec681f3Smrg case PIPE_PRIM_QUAD_STRIP: 807ec681f3Smrg case PIPE_PRIM_POLYGON: 817ec681f3Smrg return PIPE_PRIM_TRIANGLES; 827ec681f3Smrg case PIPE_PRIM_LINES_ADJACENCY: 837ec681f3Smrg case PIPE_PRIM_LINE_STRIP_ADJACENCY: 847ec681f3Smrg return PIPE_PRIM_LINES_ADJACENCY; 857ec681f3Smrg case PIPE_PRIM_TRIANGLES_ADJACENCY: 867ec681f3Smrg case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: 877ec681f3Smrg return PIPE_PRIM_TRIANGLES_ADJACENCY; 887ec681f3Smrg case PIPE_PRIM_PATCHES: 897ec681f3Smrg return PIPE_PRIM_PATCHES; 907ec681f3Smrg default: 917ec681f3Smrg assert(0); 927ec681f3Smrg break; 937ec681f3Smrg } 947ec681f3Smrg return PIPE_PRIM_POINTS; 957ec681f3Smrg} 964a49301eSmrg 97af69d88dSmrg/** 98af69d88dSmrg * Translate indexes when a driver can't support certain types 99af69d88dSmrg * of drawing. Example include: 100af69d88dSmrg * - Translate 1-byte indexes into 2-byte indexes 101af69d88dSmrg * - Translate PIPE_PRIM_QUADS into PIPE_PRIM_TRIANGLES when the hardware 102af69d88dSmrg * doesn't support the former. 103af69d88dSmrg * - Translate from first provoking vertex to last provoking vertex and 104af69d88dSmrg * vice versa. 105af69d88dSmrg * 10601e04c3fSmrg * Note that this function is used for indexed primitives. 10701e04c3fSmrg * 108af69d88dSmrg * \param hw_mask mask of (1 << PIPE_PRIM_x) flags indicating which types 109af69d88dSmrg * of primitives are supported by the hardware. 110af69d88dSmrg * \param prim incoming PIPE_PRIM_x 111af69d88dSmrg * \param in_index_size bytes per index value (1, 2 or 4) 112af69d88dSmrg * \param nr number of incoming vertices 113af69d88dSmrg * \param in_pv incoming provoking vertex convention (PV_FIRST or PV_LAST) 114af69d88dSmrg * \param out_pv desired provoking vertex convention (PV_FIRST or PV_LAST) 11501e04c3fSmrg * \param prim_restart whether primitive restart is disable or enabled 116af69d88dSmrg * \param out_prim returns new PIPE_PRIM_x we'll translate to 117af69d88dSmrg * \param out_index_size returns bytes per new index value (2 or 4) 118af69d88dSmrg * \param out_nr returns number of new vertices 119af69d88dSmrg * \param out_translate returns the translation function to use by the caller 120af69d88dSmrg */ 12101e04c3fSmrgenum indices_mode 12201e04c3fSmrgu_index_translator(unsigned hw_mask, 12301e04c3fSmrg enum pipe_prim_type prim, 12401e04c3fSmrg unsigned in_index_size, 12501e04c3fSmrg unsigned nr, 12601e04c3fSmrg unsigned in_pv, 12701e04c3fSmrg unsigned out_pv, 12801e04c3fSmrg unsigned prim_restart, 12901e04c3fSmrg enum pipe_prim_type *out_prim, 13001e04c3fSmrg unsigned *out_index_size, 13101e04c3fSmrg unsigned *out_nr, 13201e04c3fSmrg u_translate_func *out_translate) 1334a49301eSmrg{ 1344a49301eSmrg unsigned in_idx; 1354a49301eSmrg unsigned out_idx; 13601e04c3fSmrg enum indices_mode ret = U_TRANSLATE_NORMAL; 1374a49301eSmrg 138af69d88dSmrg assert(in_index_size == 1 || 139af69d88dSmrg in_index_size == 2 || 140af69d88dSmrg in_index_size == 4); 141af69d88dSmrg 1424a49301eSmrg u_index_init(); 1434a49301eSmrg 1444a49301eSmrg in_idx = in_size_idx(in_index_size); 1457ec681f3Smrg *out_index_size = u_index_size_convert(in_index_size); 1464a49301eSmrg out_idx = out_size_idx(*out_index_size); 1474a49301eSmrg 1487ec681f3Smrg if ((hw_mask & (1<<prim)) && 1497ec681f3Smrg in_pv == out_pv) 1504a49301eSmrg { 1514a49301eSmrg if (in_index_size == 4) 1524a49301eSmrg *out_translate = translate_memcpy_uint; 1537ec681f3Smrg else if (in_index_size == 2) 1544a49301eSmrg *out_translate = translate_memcpy_ushort; 1557ec681f3Smrg else 1567ec681f3Smrg *out_translate = translate_byte_to_ushort; 1574a49301eSmrg 1584a49301eSmrg *out_prim = prim; 1594a49301eSmrg *out_nr = nr; 1604a49301eSmrg 1614a49301eSmrg return U_TRANSLATE_MEMCPY; 1624a49301eSmrg } 1637ec681f3Smrg *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim]; 1647ec681f3Smrg *out_prim = u_index_prim_type_convert(hw_mask, prim, in_pv == out_pv); 1657ec681f3Smrg *out_nr = u_index_count_converted_indices(hw_mask, in_pv == out_pv, prim, nr); 16601e04c3fSmrg 1677ec681f3Smrg return ret; 1687ec681f3Smrg} 16901e04c3fSmrg 1707ec681f3Smrgunsigned 1717ec681f3Smrgu_index_count_converted_indices(unsigned hw_mask, bool pv_matches, enum pipe_prim_type prim, unsigned nr) 1727ec681f3Smrg{ 1737ec681f3Smrg if ((hw_mask & (1<<prim)) && pv_matches) 1747ec681f3Smrg return nr; 1757ec681f3Smrg 1767ec681f3Smrg switch (prim) { 1777ec681f3Smrg case PIPE_PRIM_POINTS: 1787ec681f3Smrg case PIPE_PRIM_PATCHES: 1797ec681f3Smrg return nr; 1807ec681f3Smrg case PIPE_PRIM_LINES: 1817ec681f3Smrg return nr; 1827ec681f3Smrg case PIPE_PRIM_LINE_STRIP: 1837ec681f3Smrg return (nr - 1) * 2; 1847ec681f3Smrg case PIPE_PRIM_LINE_LOOP: 1857ec681f3Smrg return nr * 2; 1867ec681f3Smrg case PIPE_PRIM_TRIANGLES: 1877ec681f3Smrg return nr; 1887ec681f3Smrg case PIPE_PRIM_TRIANGLE_STRIP: 1897ec681f3Smrg return (nr - 2) * 3; 1907ec681f3Smrg case PIPE_PRIM_TRIANGLE_FAN: 1917ec681f3Smrg return (nr - 2) * 3; 1927ec681f3Smrg case PIPE_PRIM_QUADS: 1937ec681f3Smrg return (nr / 4) * 6; 1947ec681f3Smrg case PIPE_PRIM_QUAD_STRIP: 1957ec681f3Smrg return (nr - 2) * 3; 1967ec681f3Smrg case PIPE_PRIM_POLYGON: 1977ec681f3Smrg return (nr - 2) * 3; 1987ec681f3Smrg case PIPE_PRIM_LINES_ADJACENCY: 1997ec681f3Smrg return nr; 2007ec681f3Smrg case PIPE_PRIM_LINE_STRIP_ADJACENCY: 2017ec681f3Smrg return (nr - 3) * 4; 2027ec681f3Smrg case PIPE_PRIM_TRIANGLES_ADJACENCY: 2037ec681f3Smrg return nr; 2047ec681f3Smrg case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: 2057ec681f3Smrg return ((nr - 4) / 2) * 6; 2067ec681f3Smrg default: 2077ec681f3Smrg assert(0); 2087ec681f3Smrg break; 2094a49301eSmrg } 2107ec681f3Smrg return nr; 2114a49301eSmrg} 2124a49301eSmrg 2134a49301eSmrg 214af69d88dSmrg/** 215af69d88dSmrg * If a driver does not support a particular gallium primitive type 216af69d88dSmrg * (such as PIPE_PRIM_QUAD_STRIP) this function can be used to help 217af69d88dSmrg * convert the primitive into a simpler type (like PIPE_PRIM_TRIANGLES). 218af69d88dSmrg * 219af69d88dSmrg * The generator functions generates a number of ushort or uint indexes 220af69d88dSmrg * for drawing the new type of primitive. 221af69d88dSmrg * 22201e04c3fSmrg * Note that this function is used for non-indexed primitives. 22301e04c3fSmrg * 224af69d88dSmrg * \param hw_mask a bitmask of (1 << PIPE_PRIM_x) values that indicates 225af69d88dSmrg * kind of primitives are supported by the driver. 226af69d88dSmrg * \param prim the PIPE_PRIM_x that the user wants to draw 227af69d88dSmrg * \param start index of first vertex to draw 228af69d88dSmrg * \param nr number of vertices to draw 229af69d88dSmrg * \param in_pv user's provoking vertex (PV_FIRST/LAST) 230af69d88dSmrg * \param out_pv desired proking vertex for the hardware (PV_FIRST/LAST) 231af69d88dSmrg * \param out_prim returns the new primitive type for the driver 232af69d88dSmrg * \param out_index_size returns OUT_USHORT or OUT_UINT 233af69d88dSmrg * \param out_nr returns new number of vertices to draw 234af69d88dSmrg * \param out_generate returns pointer to the generator function 235af69d88dSmrg */ 23601e04c3fSmrgenum indices_mode 23701e04c3fSmrgu_index_generator(unsigned hw_mask, 23801e04c3fSmrg enum pipe_prim_type prim, 23901e04c3fSmrg unsigned start, 24001e04c3fSmrg unsigned nr, 24101e04c3fSmrg unsigned in_pv, 24201e04c3fSmrg unsigned out_pv, 24301e04c3fSmrg enum pipe_prim_type *out_prim, 24401e04c3fSmrg unsigned *out_index_size, 24501e04c3fSmrg unsigned *out_nr, 24601e04c3fSmrg u_generate_func *out_generate) 2474a49301eSmrg{ 2484a49301eSmrg unsigned out_idx; 2494a49301eSmrg 2504a49301eSmrg u_index_init(); 2514a49301eSmrg 2524a49301eSmrg *out_index_size = ((start + nr) > 0xfffe) ? 4 : 2; 2534a49301eSmrg out_idx = out_size_idx(*out_index_size); 2547ec681f3Smrg *out_prim = u_index_prim_type_convert(hw_mask, prim, in_pv == out_pv); 2557ec681f3Smrg *out_nr = u_index_count_converted_indices(hw_mask, in_pv == out_pv, prim, nr); 2564a49301eSmrg 2574a49301eSmrg if ((hw_mask & (1<<prim)) && 2584a49301eSmrg (in_pv == out_pv)) { 2594a49301eSmrg 2604a49301eSmrg *out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS]; 2614a49301eSmrg return U_GENERATE_LINEAR; 2624a49301eSmrg } 2637ec681f3Smrg *out_generate = generate[out_idx][in_pv][out_pv][prim]; 2647ec681f3Smrg return prim == PIPE_PRIM_LINE_LOOP ? U_GENERATE_ONE_OFF : U_GENERATE_REUSABLE; 2654a49301eSmrg} 266