Path: blob/21.2-virgl/src/gallium/auxiliary/indices/u_unfilled_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*/232425/*26* NOTE: This file is not compiled by itself. It's actually #included27* by the generated u_unfilled_gen.c file!28*/2930#include "u_indices.h"31#include "u_indices_priv.h"32#include "util/u_prim.h"333435static void translate_ubyte_ushort( const void *in,36unsigned start,37unsigned in_nr,38unsigned out_nr,39unsigned restart_index,40void *out )41{42const ubyte *in_ub = (const ubyte *)in;43ushort *out_us = (ushort *)out;44unsigned i;45for (i = 0; i < out_nr; i++)46out_us[i] = (ushort) in_ub[i+start];47}4849static void translate_memcpy_ushort( const void *in,50unsigned start,51unsigned in_nr,52unsigned out_nr,53unsigned restart_index,54void *out )55{56memcpy(out, &((short *)in)[start], out_nr*sizeof(short));57}5859static void translate_memcpy_uint( const void *in,60unsigned start,61unsigned in_nr,62unsigned out_nr,63unsigned restart_index,64void *out )65{66memcpy(out, &((int *)in)[start], out_nr*sizeof(int));67}686970static void generate_linear_ushort( unsigned start,71unsigned nr,72void *out )73{74ushort *out_us = (ushort *)out;75unsigned i;76for (i = 0; i < nr; i++)77out_us[i] = (ushort)(i + start);78}7980static void generate_linear_uint( unsigned start,81unsigned nr,82void *out )83{84unsigned *out_ui = (unsigned *)out;85unsigned i;86for (i = 0; i < nr; i++)87out_ui[i] = i + start;88}899091/**92* Given a primitive type and number of vertices, return the number of vertices93* needed to draw the primitive with fill mode = PIPE_POLYGON_MODE_LINE using94* separate lines (PIPE_PRIM_LINES).95*/96static unsigned97nr_lines(enum pipe_prim_type prim, unsigned nr)98{99switch (prim) {100case PIPE_PRIM_TRIANGLES:101return (nr / 3) * 6;102case PIPE_PRIM_TRIANGLE_STRIP:103return (nr - 2) * 6;104case PIPE_PRIM_TRIANGLE_FAN:105return (nr - 2) * 6;106case PIPE_PRIM_QUADS:107return (nr / 4) * 8;108case PIPE_PRIM_QUAD_STRIP:109return (nr - 2) / 2 * 8;110case PIPE_PRIM_POLYGON:111return 2 * nr; /* a line (two verts) for each polygon edge */112/* Note: these cases can't really be handled since drawing lines instead113* of triangles would also require changing the GS. But if there's no GS,114* this should work.115*/116case PIPE_PRIM_TRIANGLES_ADJACENCY:117return (nr / 6) * 6;118case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:119return ((nr - 4) / 2) * 6;120default:121assert(0);122return 0;123}124}125126127enum indices_mode128u_unfilled_translator(enum pipe_prim_type prim,129unsigned in_index_size,130unsigned nr,131unsigned unfilled_mode,132enum pipe_prim_type *out_prim,133unsigned *out_index_size,134unsigned *out_nr,135u_translate_func *out_translate)136{137unsigned in_idx;138unsigned out_idx;139140assert(u_reduced_prim(prim) == PIPE_PRIM_TRIANGLES);141142u_unfilled_init();143144in_idx = in_size_idx(in_index_size);145*out_index_size = (in_index_size == 4) ? 4 : 2;146out_idx = out_size_idx(*out_index_size);147148if (unfilled_mode == PIPE_POLYGON_MODE_POINT) {149*out_prim = PIPE_PRIM_POINTS;150*out_nr = nr;151152switch (in_index_size) {153case 1:154*out_translate = translate_ubyte_ushort;155return U_TRANSLATE_NORMAL;156case 2:157*out_translate = translate_memcpy_uint;158return U_TRANSLATE_MEMCPY;159case 4:160*out_translate = translate_memcpy_ushort;161return U_TRANSLATE_MEMCPY;162default:163*out_translate = translate_memcpy_uint;164*out_nr = 0;165assert(0);166return U_TRANSLATE_ERROR;167}168}169else {170assert(unfilled_mode == PIPE_POLYGON_MODE_LINE);171*out_prim = PIPE_PRIM_LINES;172*out_translate = translate_line[in_idx][out_idx][prim];173*out_nr = nr_lines( prim, nr );174return U_TRANSLATE_NORMAL;175}176}177178179/**180* Utility for converting unfilled polygons into points, lines, triangles.181* Few drivers have direct support for OpenGL's glPolygonMode.182* This function helps with converting triangles into points or lines183* when the front and back fill modes are the same. When there's184* different front/back fill modes, that can be handled with the185* 'draw' module.186*/187enum indices_mode188u_unfilled_generator(enum pipe_prim_type prim,189unsigned start,190unsigned nr,191unsigned unfilled_mode,192enum pipe_prim_type *out_prim,193unsigned *out_index_size,194unsigned *out_nr,195u_generate_func *out_generate)196{197unsigned out_idx;198199assert(u_reduced_prim(prim) == PIPE_PRIM_TRIANGLES);200201u_unfilled_init();202203*out_index_size = ((start + nr) > 0xfffe) ? 4 : 2;204out_idx = out_size_idx(*out_index_size);205206if (unfilled_mode == PIPE_POLYGON_MODE_POINT) {207if (*out_index_size == 4)208*out_generate = generate_linear_uint;209else210*out_generate = generate_linear_ushort;211212*out_prim = PIPE_PRIM_POINTS;213*out_nr = nr;214return U_GENERATE_LINEAR;215}216else {217assert(unfilled_mode == PIPE_POLYGON_MODE_LINE);218*out_prim = PIPE_PRIM_LINES;219*out_generate = generate_line[out_idx][prim];220*out_nr = nr_lines( prim, nr );221222return U_GENERATE_REUSABLE;223}224}225226227