1848b8605Smrg/* 2848b8605Smrg * Copyright 2009 VMware, Inc. 3848b8605Smrg * All Rights Reserved. 4848b8605Smrg * 5848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6848b8605Smrg * copy of this software and associated documentation files (the "Software"), 7848b8605Smrg * to deal in the Software without restriction, including without limitation 8848b8605Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub 9848b8605Smrg * license, and/or sell copies of the Software, and to permit persons to whom 10848b8605Smrg * the Software is furnished to do so, subject to the following conditions: 11848b8605Smrg * 12848b8605Smrg * The above copyright notice and this permission notice (including the next 13848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the 14848b8605Smrg * Software. 15848b8605Smrg * 16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19848b8605Smrg * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20848b8605Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21848b8605Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22848b8605Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. 23848b8605Smrg */ 24848b8605Smrg 25848b8605Smrg#include "u_indices.h" 26848b8605Smrg#include "u_indices_priv.h" 27848b8605Smrg 28848b8605Smrgstatic void translate_memcpy_ushort( const void *in, 29848b8605Smrg unsigned start, 30b8e80941Smrg unsigned in_nr, 31b8e80941Smrg unsigned out_nr, 32b8e80941Smrg unsigned restart_index, 33848b8605Smrg void *out ) 34848b8605Smrg{ 35b8e80941Smrg memcpy(out, &((short *)in)[start], out_nr*sizeof(short)); 36848b8605Smrg} 37848b8605Smrg 38848b8605Smrgstatic void translate_memcpy_uint( const void *in, 39848b8605Smrg unsigned start, 40b8e80941Smrg unsigned in_nr, 41b8e80941Smrg unsigned out_nr, 42b8e80941Smrg unsigned restart_index, 43848b8605Smrg void *out ) 44848b8605Smrg{ 45b8e80941Smrg memcpy(out, &((int *)in)[start], out_nr*sizeof(int)); 46848b8605Smrg} 47848b8605Smrg 48848b8605Smrg 49848b8605Smrg/** 50848b8605Smrg * Translate indexes when a driver can't support certain types 51848b8605Smrg * of drawing. Example include: 52848b8605Smrg * - Translate 1-byte indexes into 2-byte indexes 53848b8605Smrg * - Translate PIPE_PRIM_QUADS into PIPE_PRIM_TRIANGLES when the hardware 54848b8605Smrg * doesn't support the former. 55848b8605Smrg * - Translate from first provoking vertex to last provoking vertex and 56848b8605Smrg * vice versa. 57848b8605Smrg * 58b8e80941Smrg * Note that this function is used for indexed primitives. 59b8e80941Smrg * 60848b8605Smrg * \param hw_mask mask of (1 << PIPE_PRIM_x) flags indicating which types 61848b8605Smrg * of primitives are supported by the hardware. 62848b8605Smrg * \param prim incoming PIPE_PRIM_x 63848b8605Smrg * \param in_index_size bytes per index value (1, 2 or 4) 64848b8605Smrg * \param nr number of incoming vertices 65848b8605Smrg * \param in_pv incoming provoking vertex convention (PV_FIRST or PV_LAST) 66848b8605Smrg * \param out_pv desired provoking vertex convention (PV_FIRST or PV_LAST) 67b8e80941Smrg * \param prim_restart whether primitive restart is disable or enabled 68848b8605Smrg * \param out_prim returns new PIPE_PRIM_x we'll translate to 69848b8605Smrg * \param out_index_size returns bytes per new index value (2 or 4) 70848b8605Smrg * \param out_nr returns number of new vertices 71848b8605Smrg * \param out_translate returns the translation function to use by the caller 72848b8605Smrg */ 73b8e80941Smrgenum indices_mode 74b8e80941Smrgu_index_translator(unsigned hw_mask, 75b8e80941Smrg enum pipe_prim_type prim, 76b8e80941Smrg unsigned in_index_size, 77b8e80941Smrg unsigned nr, 78b8e80941Smrg unsigned in_pv, 79b8e80941Smrg unsigned out_pv, 80b8e80941Smrg unsigned prim_restart, 81b8e80941Smrg enum pipe_prim_type *out_prim, 82b8e80941Smrg unsigned *out_index_size, 83b8e80941Smrg unsigned *out_nr, 84b8e80941Smrg u_translate_func *out_translate) 85848b8605Smrg{ 86848b8605Smrg unsigned in_idx; 87848b8605Smrg unsigned out_idx; 88b8e80941Smrg enum indices_mode ret = U_TRANSLATE_NORMAL; 89848b8605Smrg 90848b8605Smrg assert(in_index_size == 1 || 91848b8605Smrg in_index_size == 2 || 92848b8605Smrg in_index_size == 4); 93848b8605Smrg 94848b8605Smrg u_index_init(); 95848b8605Smrg 96848b8605Smrg in_idx = in_size_idx(in_index_size); 97848b8605Smrg *out_index_size = (in_index_size == 4) ? 4 : 2; 98848b8605Smrg out_idx = out_size_idx(*out_index_size); 99848b8605Smrg 100848b8605Smrg if ((hw_mask & (1<<prim)) && 101848b8605Smrg in_index_size == *out_index_size && 102848b8605Smrg in_pv == out_pv) 103848b8605Smrg { 104848b8605Smrg /* Index translation not really needed */ 105848b8605Smrg if (in_index_size == 4) 106848b8605Smrg *out_translate = translate_memcpy_uint; 107848b8605Smrg else 108848b8605Smrg *out_translate = translate_memcpy_ushort; 109848b8605Smrg 110848b8605Smrg *out_prim = prim; 111848b8605Smrg *out_nr = nr; 112848b8605Smrg 113848b8605Smrg return U_TRANSLATE_MEMCPY; 114848b8605Smrg } 115848b8605Smrg else { 116b8e80941Smrg *out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim]; 117b8e80941Smrg 118848b8605Smrg switch (prim) { 119848b8605Smrg case PIPE_PRIM_POINTS: 120848b8605Smrg *out_prim = PIPE_PRIM_POINTS; 121848b8605Smrg *out_nr = nr; 122848b8605Smrg break; 123848b8605Smrg 124848b8605Smrg case PIPE_PRIM_LINES: 125848b8605Smrg *out_prim = PIPE_PRIM_LINES; 126848b8605Smrg *out_nr = nr; 127848b8605Smrg break; 128848b8605Smrg 129848b8605Smrg case PIPE_PRIM_LINE_STRIP: 130848b8605Smrg *out_prim = PIPE_PRIM_LINES; 131848b8605Smrg *out_nr = (nr - 1) * 2; 132848b8605Smrg break; 133848b8605Smrg 134848b8605Smrg case PIPE_PRIM_LINE_LOOP: 135848b8605Smrg *out_prim = PIPE_PRIM_LINES; 136848b8605Smrg *out_nr = nr * 2; 137848b8605Smrg break; 138848b8605Smrg 139848b8605Smrg case PIPE_PRIM_TRIANGLES: 140848b8605Smrg *out_prim = PIPE_PRIM_TRIANGLES; 141848b8605Smrg *out_nr = nr; 142848b8605Smrg break; 143848b8605Smrg 144848b8605Smrg case PIPE_PRIM_TRIANGLE_STRIP: 145848b8605Smrg *out_prim = PIPE_PRIM_TRIANGLES; 146848b8605Smrg *out_nr = (nr - 2) * 3; 147848b8605Smrg break; 148848b8605Smrg 149848b8605Smrg case PIPE_PRIM_TRIANGLE_FAN: 150848b8605Smrg *out_prim = PIPE_PRIM_TRIANGLES; 151848b8605Smrg *out_nr = (nr - 2) * 3; 152848b8605Smrg break; 153848b8605Smrg 154848b8605Smrg case PIPE_PRIM_QUADS: 155848b8605Smrg *out_prim = PIPE_PRIM_TRIANGLES; 156848b8605Smrg *out_nr = (nr / 4) * 6; 157848b8605Smrg break; 158848b8605Smrg 159848b8605Smrg case PIPE_PRIM_QUAD_STRIP: 160848b8605Smrg *out_prim = PIPE_PRIM_TRIANGLES; 161848b8605Smrg *out_nr = (nr - 2) * 3; 162848b8605Smrg break; 163848b8605Smrg 164848b8605Smrg case PIPE_PRIM_POLYGON: 165848b8605Smrg *out_prim = PIPE_PRIM_TRIANGLES; 166848b8605Smrg *out_nr = (nr - 2) * 3; 167848b8605Smrg break; 168848b8605Smrg 169b8e80941Smrg case PIPE_PRIM_LINES_ADJACENCY: 170b8e80941Smrg *out_prim = PIPE_PRIM_LINES_ADJACENCY; 171b8e80941Smrg *out_nr = nr; 172b8e80941Smrg break; 173b8e80941Smrg 174b8e80941Smrg case PIPE_PRIM_LINE_STRIP_ADJACENCY: 175b8e80941Smrg *out_prim = PIPE_PRIM_LINES_ADJACENCY; 176b8e80941Smrg *out_nr = (nr - 3) * 4; 177b8e80941Smrg break; 178b8e80941Smrg 179b8e80941Smrg case PIPE_PRIM_TRIANGLES_ADJACENCY: 180b8e80941Smrg *out_prim = PIPE_PRIM_TRIANGLES_ADJACENCY; 181b8e80941Smrg *out_nr = nr; 182b8e80941Smrg break; 183b8e80941Smrg 184b8e80941Smrg case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: 185b8e80941Smrg *out_prim = PIPE_PRIM_TRIANGLES_ADJACENCY; 186b8e80941Smrg *out_nr = ((nr - 4) / 2) * 6; 187b8e80941Smrg break; 188b8e80941Smrg 189848b8605Smrg default: 190848b8605Smrg assert(0); 191848b8605Smrg *out_prim = PIPE_PRIM_POINTS; 192848b8605Smrg *out_nr = nr; 193848b8605Smrg return U_TRANSLATE_ERROR; 194848b8605Smrg } 195848b8605Smrg } 196848b8605Smrg 197848b8605Smrg return ret; 198848b8605Smrg} 199848b8605Smrg 200848b8605Smrg 201848b8605Smrg/** 202848b8605Smrg * If a driver does not support a particular gallium primitive type 203848b8605Smrg * (such as PIPE_PRIM_QUAD_STRIP) this function can be used to help 204848b8605Smrg * convert the primitive into a simpler type (like PIPE_PRIM_TRIANGLES). 205848b8605Smrg * 206848b8605Smrg * The generator functions generates a number of ushort or uint indexes 207848b8605Smrg * for drawing the new type of primitive. 208848b8605Smrg * 209b8e80941Smrg * Note that this function is used for non-indexed primitives. 210b8e80941Smrg * 211848b8605Smrg * \param hw_mask a bitmask of (1 << PIPE_PRIM_x) values that indicates 212848b8605Smrg * kind of primitives are supported by the driver. 213848b8605Smrg * \param prim the PIPE_PRIM_x that the user wants to draw 214848b8605Smrg * \param start index of first vertex to draw 215848b8605Smrg * \param nr number of vertices to draw 216848b8605Smrg * \param in_pv user's provoking vertex (PV_FIRST/LAST) 217848b8605Smrg * \param out_pv desired proking vertex for the hardware (PV_FIRST/LAST) 218848b8605Smrg * \param out_prim returns the new primitive type for the driver 219848b8605Smrg * \param out_index_size returns OUT_USHORT or OUT_UINT 220848b8605Smrg * \param out_nr returns new number of vertices to draw 221848b8605Smrg * \param out_generate returns pointer to the generator function 222848b8605Smrg */ 223b8e80941Smrgenum indices_mode 224b8e80941Smrgu_index_generator(unsigned hw_mask, 225b8e80941Smrg enum pipe_prim_type prim, 226b8e80941Smrg unsigned start, 227b8e80941Smrg unsigned nr, 228b8e80941Smrg unsigned in_pv, 229b8e80941Smrg unsigned out_pv, 230b8e80941Smrg enum pipe_prim_type *out_prim, 231b8e80941Smrg unsigned *out_index_size, 232b8e80941Smrg unsigned *out_nr, 233b8e80941Smrg u_generate_func *out_generate) 234848b8605Smrg{ 235848b8605Smrg unsigned out_idx; 236848b8605Smrg 237848b8605Smrg u_index_init(); 238848b8605Smrg 239848b8605Smrg *out_index_size = ((start + nr) > 0xfffe) ? 4 : 2; 240848b8605Smrg out_idx = out_size_idx(*out_index_size); 241848b8605Smrg 242848b8605Smrg if ((hw_mask & (1<<prim)) && 243848b8605Smrg (in_pv == out_pv)) { 244848b8605Smrg 245848b8605Smrg *out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS]; 246848b8605Smrg *out_prim = prim; 247848b8605Smrg *out_nr = nr; 248848b8605Smrg return U_GENERATE_LINEAR; 249848b8605Smrg } 250848b8605Smrg else { 251b8e80941Smrg *out_generate = generate[out_idx][in_pv][out_pv][prim]; 252b8e80941Smrg 253848b8605Smrg switch (prim) { 254848b8605Smrg case PIPE_PRIM_POINTS: 255848b8605Smrg *out_prim = PIPE_PRIM_POINTS; 256848b8605Smrg *out_nr = nr; 257848b8605Smrg return U_GENERATE_REUSABLE; 258848b8605Smrg 259848b8605Smrg case PIPE_PRIM_LINES: 260848b8605Smrg *out_prim = PIPE_PRIM_LINES; 261848b8605Smrg *out_nr = nr; 262848b8605Smrg return U_GENERATE_REUSABLE; 263848b8605Smrg 264848b8605Smrg case PIPE_PRIM_LINE_STRIP: 265848b8605Smrg *out_prim = PIPE_PRIM_LINES; 266848b8605Smrg *out_nr = (nr - 1) * 2; 267848b8605Smrg return U_GENERATE_REUSABLE; 268848b8605Smrg 269848b8605Smrg case PIPE_PRIM_LINE_LOOP: 270848b8605Smrg *out_prim = PIPE_PRIM_LINES; 271848b8605Smrg *out_nr = nr * 2; 272848b8605Smrg return U_GENERATE_ONE_OFF; 273848b8605Smrg 274848b8605Smrg case PIPE_PRIM_TRIANGLES: 275848b8605Smrg *out_prim = PIPE_PRIM_TRIANGLES; 276848b8605Smrg *out_nr = nr; 277848b8605Smrg return U_GENERATE_REUSABLE; 278848b8605Smrg 279848b8605Smrg case PIPE_PRIM_TRIANGLE_STRIP: 280848b8605Smrg *out_prim = PIPE_PRIM_TRIANGLES; 281848b8605Smrg *out_nr = (nr - 2) * 3; 282848b8605Smrg return U_GENERATE_REUSABLE; 283848b8605Smrg 284848b8605Smrg case PIPE_PRIM_TRIANGLE_FAN: 285848b8605Smrg *out_prim = PIPE_PRIM_TRIANGLES; 286848b8605Smrg *out_nr = (nr - 2) * 3; 287848b8605Smrg return U_GENERATE_REUSABLE; 288848b8605Smrg 289848b8605Smrg case PIPE_PRIM_QUADS: 290848b8605Smrg *out_prim = PIPE_PRIM_TRIANGLES; 291848b8605Smrg *out_nr = (nr / 4) * 6; 292848b8605Smrg return U_GENERATE_REUSABLE; 293848b8605Smrg 294848b8605Smrg case PIPE_PRIM_QUAD_STRIP: 295848b8605Smrg *out_prim = PIPE_PRIM_TRIANGLES; 296848b8605Smrg *out_nr = (nr - 2) * 3; 297848b8605Smrg return U_GENERATE_REUSABLE; 298848b8605Smrg 299848b8605Smrg case PIPE_PRIM_POLYGON: 300848b8605Smrg *out_prim = PIPE_PRIM_TRIANGLES; 301848b8605Smrg *out_nr = (nr - 2) * 3; 302848b8605Smrg return U_GENERATE_REUSABLE; 303848b8605Smrg 304b8e80941Smrg case PIPE_PRIM_LINES_ADJACENCY: 305b8e80941Smrg *out_prim = PIPE_PRIM_LINES_ADJACENCY; 306b8e80941Smrg *out_nr = nr; 307b8e80941Smrg return U_GENERATE_REUSABLE; 308b8e80941Smrg 309b8e80941Smrg case PIPE_PRIM_LINE_STRIP_ADJACENCY: 310b8e80941Smrg *out_prim = PIPE_PRIM_LINES_ADJACENCY; 311b8e80941Smrg *out_nr = (nr - 3) * 4; 312b8e80941Smrg return U_GENERATE_REUSABLE; 313b8e80941Smrg 314b8e80941Smrg case PIPE_PRIM_TRIANGLES_ADJACENCY: 315b8e80941Smrg *out_prim = PIPE_PRIM_TRIANGLES_ADJACENCY; 316b8e80941Smrg *out_nr = nr; 317b8e80941Smrg return U_GENERATE_REUSABLE; 318b8e80941Smrg 319b8e80941Smrg case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: 320b8e80941Smrg *out_prim = PIPE_PRIM_TRIANGLES_ADJACENCY; 321b8e80941Smrg *out_nr = ((nr - 4) / 2) * 6; 322b8e80941Smrg return U_GENERATE_REUSABLE; 323b8e80941Smrg 324848b8605Smrg default: 325848b8605Smrg assert(0); 326848b8605Smrg *out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS]; 327848b8605Smrg *out_prim = PIPE_PRIM_POINTS; 328848b8605Smrg *out_nr = nr; 329848b8605Smrg return U_TRANSLATE_ERROR; 330848b8605Smrg } 331848b8605Smrg } 332848b8605Smrg} 333