1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2009 VMware, Inc. 3bf215546Sopenharmony_ci * All Rights Reserved. 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include "u_indices.h" 26bf215546Sopenharmony_ci#include "u_indices_priv.h" 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_cistatic void translate_memcpy_ushort( const void *in, 29bf215546Sopenharmony_ci unsigned start, 30bf215546Sopenharmony_ci unsigned in_nr, 31bf215546Sopenharmony_ci unsigned out_nr, 32bf215546Sopenharmony_ci unsigned restart_index, 33bf215546Sopenharmony_ci void *out ) 34bf215546Sopenharmony_ci{ 35bf215546Sopenharmony_ci memcpy(out, &((short *)in)[start], out_nr*sizeof(short)); 36bf215546Sopenharmony_ci} 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_cistatic void translate_memcpy_uint( const void *in, 39bf215546Sopenharmony_ci unsigned start, 40bf215546Sopenharmony_ci unsigned in_nr, 41bf215546Sopenharmony_ci unsigned out_nr, 42bf215546Sopenharmony_ci unsigned restart_index, 43bf215546Sopenharmony_ci void *out ) 44bf215546Sopenharmony_ci{ 45bf215546Sopenharmony_ci memcpy(out, &((int *)in)[start], out_nr*sizeof(int)); 46bf215546Sopenharmony_ci} 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_cistatic void translate_byte_to_ushort( const void *in, 49bf215546Sopenharmony_ci unsigned start, 50bf215546Sopenharmony_ci UNUSED unsigned in_nr, 51bf215546Sopenharmony_ci unsigned out_nr, 52bf215546Sopenharmony_ci UNUSED unsigned restart_index, 53bf215546Sopenharmony_ci void *out ) 54bf215546Sopenharmony_ci{ 55bf215546Sopenharmony_ci uint8_t *src = (uint8_t *)in + start; 56bf215546Sopenharmony_ci uint16_t *dst = out; 57bf215546Sopenharmony_ci while (out_nr--) { 58bf215546Sopenharmony_ci *dst++ = *src++; 59bf215546Sopenharmony_ci } 60bf215546Sopenharmony_ci} 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_cienum pipe_prim_type 63bf215546Sopenharmony_ciu_index_prim_type_convert(unsigned hw_mask, enum pipe_prim_type prim, bool pv_matches) 64bf215546Sopenharmony_ci{ 65bf215546Sopenharmony_ci if ((hw_mask & (1<<prim)) && pv_matches) 66bf215546Sopenharmony_ci return prim; 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci switch (prim) { 69bf215546Sopenharmony_ci case PIPE_PRIM_POINTS: 70bf215546Sopenharmony_ci return PIPE_PRIM_POINTS; 71bf215546Sopenharmony_ci case PIPE_PRIM_LINES: 72bf215546Sopenharmony_ci case PIPE_PRIM_LINE_STRIP: 73bf215546Sopenharmony_ci case PIPE_PRIM_LINE_LOOP: 74bf215546Sopenharmony_ci return PIPE_PRIM_LINES; 75bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLES: 76bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLE_STRIP: 77bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLE_FAN: 78bf215546Sopenharmony_ci case PIPE_PRIM_QUADS: 79bf215546Sopenharmony_ci case PIPE_PRIM_QUAD_STRIP: 80bf215546Sopenharmony_ci case PIPE_PRIM_POLYGON: 81bf215546Sopenharmony_ci return PIPE_PRIM_TRIANGLES; 82bf215546Sopenharmony_ci case PIPE_PRIM_LINES_ADJACENCY: 83bf215546Sopenharmony_ci case PIPE_PRIM_LINE_STRIP_ADJACENCY: 84bf215546Sopenharmony_ci return PIPE_PRIM_LINES_ADJACENCY; 85bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLES_ADJACENCY: 86bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: 87bf215546Sopenharmony_ci return PIPE_PRIM_TRIANGLES_ADJACENCY; 88bf215546Sopenharmony_ci case PIPE_PRIM_PATCHES: 89bf215546Sopenharmony_ci return PIPE_PRIM_PATCHES; 90bf215546Sopenharmony_ci default: 91bf215546Sopenharmony_ci assert(0); 92bf215546Sopenharmony_ci break; 93bf215546Sopenharmony_ci } 94bf215546Sopenharmony_ci return PIPE_PRIM_POINTS; 95bf215546Sopenharmony_ci} 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci/** 98bf215546Sopenharmony_ci * Translate indexes when a driver can't support certain types 99bf215546Sopenharmony_ci * of drawing. Example include: 100bf215546Sopenharmony_ci * - Translate 1-byte indexes into 2-byte indexes 101bf215546Sopenharmony_ci * - Translate PIPE_PRIM_QUADS into PIPE_PRIM_TRIANGLES when the hardware 102bf215546Sopenharmony_ci * doesn't support the former. 103bf215546Sopenharmony_ci * - Translate from first provoking vertex to last provoking vertex and 104bf215546Sopenharmony_ci * vice versa. 105bf215546Sopenharmony_ci * 106bf215546Sopenharmony_ci * Note that this function is used for indexed primitives. 107bf215546Sopenharmony_ci * 108bf215546Sopenharmony_ci * \param hw_mask mask of (1 << PIPE_PRIM_x) flags indicating which types 109bf215546Sopenharmony_ci * of primitives are supported by the hardware. 110bf215546Sopenharmony_ci * \param prim incoming PIPE_PRIM_x 111bf215546Sopenharmony_ci * \param in_index_size bytes per index value (1, 2 or 4) 112bf215546Sopenharmony_ci * \param nr number of incoming vertices 113bf215546Sopenharmony_ci * \param in_pv incoming provoking vertex convention (PV_FIRST or PV_LAST) 114bf215546Sopenharmony_ci * \param out_pv desired provoking vertex convention (PV_FIRST or PV_LAST) 115bf215546Sopenharmony_ci * \param prim_restart whether primitive restart is disable or enabled 116bf215546Sopenharmony_ci * \param out_prim returns new PIPE_PRIM_x we'll translate to 117bf215546Sopenharmony_ci * \param out_index_size returns bytes per new index value (2 or 4) 118bf215546Sopenharmony_ci * \param out_nr returns number of new vertices 119bf215546Sopenharmony_ci * \param out_translate returns the translation function to use by the caller 120bf215546Sopenharmony_ci */ 121bf215546Sopenharmony_cienum indices_mode 122bf215546Sopenharmony_ciu_index_translator(unsigned hw_mask, 123bf215546Sopenharmony_ci enum pipe_prim_type prim, 124bf215546Sopenharmony_ci unsigned in_index_size, 125bf215546Sopenharmony_ci unsigned nr, 126bf215546Sopenharmony_ci unsigned in_pv, 127bf215546Sopenharmony_ci unsigned out_pv, 128bf215546Sopenharmony_ci unsigned prim_restart, 129bf215546Sopenharmony_ci enum pipe_prim_type *out_prim, 130bf215546Sopenharmony_ci unsigned *out_index_size, 131bf215546Sopenharmony_ci unsigned *out_nr, 132bf215546Sopenharmony_ci u_translate_func *out_translate) 133bf215546Sopenharmony_ci{ 134bf215546Sopenharmony_ci unsigned in_idx; 135bf215546Sopenharmony_ci unsigned out_idx; 136bf215546Sopenharmony_ci enum indices_mode ret = U_TRANSLATE_NORMAL; 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci assert(in_index_size == 1 || 139bf215546Sopenharmony_ci in_index_size == 2 || 140bf215546Sopenharmony_ci in_index_size == 4); 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci u_index_init(); 143bf215546Sopenharmony_ci 144bf215546Sopenharmony_ci in_idx = in_size_idx(in_index_size); 145bf215546Sopenharmony_ci *out_index_size = u_index_size_convert(in_index_size); 146bf215546Sopenharmony_ci out_idx = out_size_idx(*out_index_size); 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci if ((hw_mask & (1<<prim)) && 149bf215546Sopenharmony_ci in_pv == out_pv) 150bf215546Sopenharmony_ci { 151bf215546Sopenharmony_ci if (in_index_size == 4) 152bf215546Sopenharmony_ci *out_translate = translate_memcpy_uint; 153bf215546Sopenharmony_ci else if (in_index_size == 2) 154bf215546Sopenharmony_ci *out_translate = translate_memcpy_ushort; 155bf215546Sopenharmony_ci else 156bf215546Sopenharmony_ci *out_translate = translate_byte_to_ushort; 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci *out_prim = prim; 159bf215546Sopenharmony_ci *out_nr = nr; 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci return U_TRANSLATE_MEMCPY; 162bf215546Sopenharmony_ci } 163bf215546Sopenharmony_ci *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim]; 164bf215546Sopenharmony_ci *out_prim = u_index_prim_type_convert(hw_mask, prim, in_pv == out_pv); 165bf215546Sopenharmony_ci *out_nr = u_index_count_converted_indices(hw_mask, in_pv == out_pv, prim, nr); 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci return ret; 168bf215546Sopenharmony_ci} 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ciunsigned 171bf215546Sopenharmony_ciu_index_count_converted_indices(unsigned hw_mask, bool pv_matches, enum pipe_prim_type prim, unsigned nr) 172bf215546Sopenharmony_ci{ 173bf215546Sopenharmony_ci if ((hw_mask & (1<<prim)) && pv_matches) 174bf215546Sopenharmony_ci return nr; 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci switch (prim) { 177bf215546Sopenharmony_ci case PIPE_PRIM_POINTS: 178bf215546Sopenharmony_ci case PIPE_PRIM_PATCHES: 179bf215546Sopenharmony_ci return nr; 180bf215546Sopenharmony_ci case PIPE_PRIM_LINES: 181bf215546Sopenharmony_ci return nr; 182bf215546Sopenharmony_ci case PIPE_PRIM_LINE_STRIP: 183bf215546Sopenharmony_ci return (nr - 1) * 2; 184bf215546Sopenharmony_ci case PIPE_PRIM_LINE_LOOP: 185bf215546Sopenharmony_ci return nr * 2; 186bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLES: 187bf215546Sopenharmony_ci return nr; 188bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLE_STRIP: 189bf215546Sopenharmony_ci return (nr - 2) * 3; 190bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLE_FAN: 191bf215546Sopenharmony_ci return (nr - 2) * 3; 192bf215546Sopenharmony_ci case PIPE_PRIM_QUADS: 193bf215546Sopenharmony_ci return (nr / 4) * 6; 194bf215546Sopenharmony_ci case PIPE_PRIM_QUAD_STRIP: 195bf215546Sopenharmony_ci return (nr - 2) * 3; 196bf215546Sopenharmony_ci case PIPE_PRIM_POLYGON: 197bf215546Sopenharmony_ci return (nr - 2) * 3; 198bf215546Sopenharmony_ci case PIPE_PRIM_LINES_ADJACENCY: 199bf215546Sopenharmony_ci return nr; 200bf215546Sopenharmony_ci case PIPE_PRIM_LINE_STRIP_ADJACENCY: 201bf215546Sopenharmony_ci return (nr - 3) * 4; 202bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLES_ADJACENCY: 203bf215546Sopenharmony_ci return nr; 204bf215546Sopenharmony_ci case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: 205bf215546Sopenharmony_ci return ((nr - 4) / 2) * 6; 206bf215546Sopenharmony_ci default: 207bf215546Sopenharmony_ci assert(0); 208bf215546Sopenharmony_ci break; 209bf215546Sopenharmony_ci } 210bf215546Sopenharmony_ci return nr; 211bf215546Sopenharmony_ci} 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci/** 215bf215546Sopenharmony_ci * If a driver does not support a particular gallium primitive type 216bf215546Sopenharmony_ci * (such as PIPE_PRIM_QUAD_STRIP) this function can be used to help 217bf215546Sopenharmony_ci * convert the primitive into a simpler type (like PIPE_PRIM_TRIANGLES). 218bf215546Sopenharmony_ci * 219bf215546Sopenharmony_ci * The generator functions generates a number of ushort or uint indexes 220bf215546Sopenharmony_ci * for drawing the new type of primitive. 221bf215546Sopenharmony_ci * 222bf215546Sopenharmony_ci * Note that this function is used for non-indexed primitives. 223bf215546Sopenharmony_ci * 224bf215546Sopenharmony_ci * \param hw_mask a bitmask of (1 << PIPE_PRIM_x) values that indicates 225bf215546Sopenharmony_ci * kind of primitives are supported by the driver. 226bf215546Sopenharmony_ci * \param prim the PIPE_PRIM_x that the user wants to draw 227bf215546Sopenharmony_ci * \param start index of first vertex to draw 228bf215546Sopenharmony_ci * \param nr number of vertices to draw 229bf215546Sopenharmony_ci * \param in_pv user's provoking vertex (PV_FIRST/LAST) 230bf215546Sopenharmony_ci * \param out_pv desired proking vertex for the hardware (PV_FIRST/LAST) 231bf215546Sopenharmony_ci * \param out_prim returns the new primitive type for the driver 232bf215546Sopenharmony_ci * \param out_index_size returns OUT_USHORT or OUT_UINT 233bf215546Sopenharmony_ci * \param out_nr returns new number of vertices to draw 234bf215546Sopenharmony_ci * \param out_generate returns pointer to the generator function 235bf215546Sopenharmony_ci */ 236bf215546Sopenharmony_cienum indices_mode 237bf215546Sopenharmony_ciu_index_generator(unsigned hw_mask, 238bf215546Sopenharmony_ci enum pipe_prim_type prim, 239bf215546Sopenharmony_ci unsigned start, 240bf215546Sopenharmony_ci unsigned nr, 241bf215546Sopenharmony_ci unsigned in_pv, 242bf215546Sopenharmony_ci unsigned out_pv, 243bf215546Sopenharmony_ci enum pipe_prim_type *out_prim, 244bf215546Sopenharmony_ci unsigned *out_index_size, 245bf215546Sopenharmony_ci unsigned *out_nr, 246bf215546Sopenharmony_ci u_generate_func *out_generate) 247bf215546Sopenharmony_ci{ 248bf215546Sopenharmony_ci unsigned out_idx; 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci u_index_init(); 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci *out_index_size = ((start + nr) > 0xfffe) ? 4 : 2; 253bf215546Sopenharmony_ci out_idx = out_size_idx(*out_index_size); 254bf215546Sopenharmony_ci *out_prim = u_index_prim_type_convert(hw_mask, prim, in_pv == out_pv); 255bf215546Sopenharmony_ci *out_nr = u_index_count_converted_indices(hw_mask, in_pv == out_pv, prim, nr); 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci if ((hw_mask & (1<<prim)) && 258bf215546Sopenharmony_ci (in_pv == out_pv)) { 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci *out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS]; 261bf215546Sopenharmony_ci return U_GENERATE_LINEAR; 262bf215546Sopenharmony_ci } 263bf215546Sopenharmony_ci *out_generate = generate[out_idx][in_pv][out_pv][prim]; 264bf215546Sopenharmony_ci return prim == PIPE_PRIM_LINE_LOOP ? U_GENERATE_ONE_OFF : U_GENERATE_REUSABLE; 265bf215546Sopenharmony_ci} 266