indices: add translate/generate functions for unfilled modes

Most of the time unfilled rendering requires a lot more thought than
just translating triangles to lines or points.  But sometimes, you can
do exactly that, and it can be quite a bit quicker.  Add code to do the
translation.  The caller has to determine whether it's a legal thing
to do in the current state, in particular you'd need:
  - culling disabled
  - offset disabled
  - same front and back fill modes
  - possibly other stuff I can't think of.
This commit is contained in:
Keith Whitwell 2009-03-04 21:35:17 +00:00
parent 59311fb06c
commit 79a05a6b3f
6 changed files with 1622 additions and 1 deletions

View File

@ -4,9 +4,13 @@ include $(TOP)/configs/current
LIBNAME = indices
C_SOURCES = \
u_indices_gen.c
u_indices_gen.c \
u_unfilled_gen.c
include ../../Makefile.template
u_indices_gen.c: u_indices_gen.py
python $< > $@
u_unfilled_gen.c: u_unfilled_gen.py
python $< > $@

View File

@ -7,11 +7,20 @@ env.CodeGenerate(
command = 'python $SCRIPT > $TARGET'
)
env.CodeGenerate(
target = 'u_unfilled_gen.c',
script = 'u_unfilled_gen.py',
source = [],
command = 'python $SCRIPT > $TARGET'
)
indices = env.ConvenienceLibrary(
target = 'indices',
source = [
# 'u_indices.c',
# 'u_unfilled_indices.c',
'u_indices_gen.c',
'u_unfilled_gen.c',
])
auxiliaries.insert(0, indices)

View File

@ -80,4 +80,27 @@ int u_index_generator( unsigned hw_mask,
u_generate_func *out_generate );
void u_unfilled_init( void );
int u_unfilled_translator( unsigned prim,
unsigned in_index_size,
unsigned nr,
unsigned unfilled_mode,
unsigned *out_prim,
unsigned *out_index_size,
unsigned *out_nr,
u_translate_func *out_translate );
int u_unfilled_generator( unsigned prim,
unsigned start,
unsigned nr,
unsigned unfilled_mode,
unsigned *out_prim,
unsigned *out_index_size,
unsigned *out_nr,
u_generate_func *out_generate );
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,247 @@
#!/usr/bin/env python
copyright = '''
/*
* Copyright 2009 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
'''
GENERATE, UBYTE, USHORT, UINT = 'generate', 'ubyte', 'ushort', 'uint'
FIRST, LAST = 'first', 'last'
INTYPES = (GENERATE, UBYTE, USHORT, UINT)
OUTTYPES = (USHORT, UINT)
PRIMS=('tris',
'trifan',
'tristrip',
'quads',
'quadstrip',
'polygon')
LONGPRIMS=('PIPE_PRIM_TRIANGLES',
'PIPE_PRIM_TRIANGLE_FAN',
'PIPE_PRIM_TRIANGLE_STRIP',
'PIPE_PRIM_QUADS',
'PIPE_PRIM_QUAD_STRIP',
'PIPE_PRIM_POLYGON')
longprim = dict(zip(PRIMS, LONGPRIMS))
intype_idx = dict(ubyte='IN_UBYTE', ushort='IN_USHORT', uint='IN_UINT')
outtype_idx = dict(ushort='OUT_USHORT', uint='OUT_UINT')
def prolog():
print '''/* File automatically generated by u_unfilled_gen.py */'''
print copyright
print r'''
/**
* @file
* Functions to translate and generate index lists
*/
#include "indices/u_indices.h"
#include "indices/u_indices_priv.h"
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
static unsigned out_size_idx( unsigned index_size )
{
switch (index_size) {
case 4: return OUT_UINT;
case 2: return OUT_USHORT;
default: assert(0); return OUT_USHORT;
}
}
static unsigned in_size_idx( unsigned index_size )
{
switch (index_size) {
case 4: return IN_UINT;
case 2: return IN_USHORT;
case 1: return IN_UBYTE;
default: assert(0); return IN_UBYTE;
}
}
static u_generate_func generate_line[OUT_COUNT][PRIM_COUNT];
static u_translate_func translate_line[IN_COUNT][OUT_COUNT][PRIM_COUNT];
'''
def vert( intype, outtype, v0 ):
if intype == GENERATE:
return '(' + outtype + ')(' + v0 + ')'
else:
return '(' + outtype + ')in[' + v0 + ']'
def line( intype, outtype, ptr, v0, v1 ):
print ' debug_printf(" line %d %d\\n", (int)' + v0 + ', (int)' + v1 + ');'
print ' (' + ptr + ')[0] = ' + vert( intype, outtype, v0 ) + ';'
print ' (' + ptr + ')[1] = ' + vert( intype, outtype, v1 ) + ';'
# XXX: have the opportunity here to avoid over-drawing shared lines in
# tristrips, fans, etc, by integrating this into the calling functions
# and only emitting each line at most once.
#
def do_tri( intype, outtype, ptr, v0, v1, v2 ):
line( intype, outtype, ptr, v0, v1 )
line( intype, outtype, ptr + '+2', v1, v2 )
line( intype, outtype, ptr + '+4', v2, v0 )
def do_quad( intype, outtype, ptr, v0, v1, v2, v3 ):
line( intype, outtype, ptr, v0, v1 )
line( intype, outtype, ptr + '+2', v1, v2 )
line( intype, outtype, ptr + '+4', v2, v3 )
line( intype, outtype, ptr + '+6', v3, v0 )
def name(intype, outtype, prim):
if intype == GENERATE:
return 'generate_' + prim + '_' + outtype
else:
return 'translate_' + prim + '_' + intype + '2' + outtype
def preamble(intype, outtype, prim):
print 'static void ' + name( intype, outtype, prim ) + '('
if intype != GENERATE:
print ' const void * _in,'
print ' unsigned nr,'
print ' void *_out )'
print '{'
if intype != GENERATE:
print ' const ' + intype + '*in = (const ' + intype + '*)_in;'
print ' ' + outtype + ' *out = (' + outtype + '*)_out;'
print ' unsigned i, j;'
print ' (void)j;'
def postamble():
print '}'
def tris(intype, outtype):
preamble(intype, outtype, prim='tris')
print ' for (j = i = 0; j < nr; j+=6, i+=3) { '
do_tri( intype, outtype, 'out+j', 'i', 'i+1', 'i+2' );
print ' }'
postamble()
def tristrip(intype, outtype):
preamble(intype, outtype, prim='tristrip')
print ' for (j = i = 0; j < nr; j+=6, i++) { '
do_tri( intype, outtype, 'out+j', 'i', 'i+1/*+(i&1)*/', 'i+2/*-(i&1)*/' );
print ' }'
postamble()
def trifan(intype, outtype):
preamble(intype, outtype, prim='trifan')
print ' for (j = i = 0; j < nr; j+=6, i++) { '
do_tri( intype, outtype, 'out+j', '0', 'i+1', 'i+2' );
print ' }'
postamble()
def polygon(intype, outtype):
preamble(intype, outtype, prim='polygon')
print ' for (j = i = 0; j < nr; j+=6, i++) { '
do_tri( intype, outtype, 'out+j', '0', 'i+1', 'i+2' );
print ' }'
postamble()
def quads(intype, outtype):
preamble(intype, outtype, prim='quads')
print ' for (j = i = 0; j < nr; j+=8, i+=4) { '
do_quad( intype, outtype, 'out+j', 'i+0', 'i+1', 'i+2', 'i+3' );
print ' }'
postamble()
def quadstrip(intype, outtype):
preamble(intype, outtype, prim='quadstrip')
print ' for (j = i = 0; j < nr; j+=8, i+=2) { '
do_quad( intype, outtype, 'out+j', 'i+2', 'i+0', 'i+1', 'i+3' );
print ' }'
postamble()
def emit_funcs():
for intype in INTYPES:
for outtype in OUTTYPES:
tris(intype, outtype)
tristrip(intype, outtype)
trifan(intype, outtype)
quads(intype, outtype)
quadstrip(intype, outtype)
polygon(intype, outtype)
def init(intype, outtype, prim):
if intype == GENERATE:
print ('generate_line[' +
outtype_idx[outtype] +
'][' + longprim[prim] +
'] = ' + name( intype, outtype, prim ) + ';')
else:
print ('translate_line[' +
intype_idx[intype] +
'][' + outtype_idx[outtype] +
'][' + longprim[prim] +
'] = ' + name( intype, outtype, prim ) + ';')
def emit_all_inits():
for intype in INTYPES:
for outtype in OUTTYPES:
for prim in PRIMS:
init(intype, outtype, prim)
def emit_init():
print 'void u_unfilled_init( void )'
print '{'
print ' static int firsttime = 1;'
print ' if (!firsttime) return;'
print ' firsttime = 0;'
emit_all_inits()
print '}'
def epilog():
print '#include "indices/u_unfilled_indices.c"'
def main():
prolog()
emit_funcs()
emit_init()
epilog()
if __name__ == '__main__':
main()

View File

@ -0,0 +1,186 @@
/*
* Copyright 2009 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "u_indices.h"
#include "u_indices_priv.h"
static void translate_ubyte_ushort( const void *in,
unsigned nr,
void *out )
{
const ubyte *in_ub = (const ubyte *)in;
ushort *out_us = (ushort *)out;
unsigned i;
for (i = 0; i < nr; i++)
out_us[i] = (ushort) in_ub[i];
}
static void translate_memcpy_ushort( const void *in,
unsigned nr,
void *out )
{
memcpy(out, in, nr*sizeof(short));
}
static void translate_memcpy_uint( const void *in,
unsigned nr,
void *out )
{
memcpy(out, in, nr*sizeof(int));
}
static void generate_linear_ushort( unsigned nr,
void *out )
{
ushort *out_us = (ushort *)out;
unsigned i;
for (i = 0; i < nr; i++)
out_us[i] = (ushort) i;
}
static void generate_linear_uint( unsigned nr,
void *out )
{
unsigned *out_ui = (unsigned *)out;
unsigned i;
for (i = 0; i < nr; i++)
out_ui[i] = i;
}
static unsigned nr_lines( unsigned prim,
unsigned nr )
{
switch (prim) {
case PIPE_PRIM_TRIANGLES:
return (nr / 3) * 6;
case PIPE_PRIM_TRIANGLE_STRIP:
return (nr - 2) * 6;
case PIPE_PRIM_TRIANGLE_FAN:
return (nr - 2) * 6;
case PIPE_PRIM_QUADS:
return (nr / 4) * 8;
case PIPE_PRIM_QUAD_STRIP:
return (nr - 2) / 2 * 8;
case PIPE_PRIM_POLYGON:
return (nr - 2) * 6;
default:
assert(0);
return 0;
}
}
int u_unfilled_translator( unsigned prim,
unsigned in_index_size,
unsigned nr,
unsigned unfilled_mode,
unsigned *out_prim,
unsigned *out_index_size,
unsigned *out_nr,
u_translate_func *out_translate )
{
unsigned in_idx;
unsigned out_idx;
u_unfilled_init();
in_idx = in_size_idx(in_index_size);
*out_index_size = (in_index_size == 4) ? 4 : 2;
out_idx = out_size_idx(*out_index_size);
if (unfilled_mode == PIPE_POLYGON_MODE_POINT)
{
*out_prim = PIPE_PRIM_POINTS;
*out_nr = nr;
switch (in_index_size)
{
case 1:
*out_translate = translate_ubyte_ushort;
return U_TRANSLATE_NORMAL;
case 2:
*out_translate = translate_memcpy_uint;
return U_TRANSLATE_MEMCPY;
case 4:
*out_translate = translate_memcpy_ushort;
return U_TRANSLATE_MEMCPY;
default:
*out_translate = translate_memcpy_uint;
*out_nr = 0;
assert(0);
return U_TRANSLATE_ERROR;
}
}
else {
assert(unfilled_mode == PIPE_POLYGON_MODE_LINE);
*out_prim = PIPE_PRIM_LINES;
*out_translate = translate_line[in_idx][out_idx][prim];
*out_nr = nr_lines( prim, nr );
return U_TRANSLATE_NORMAL;
}
}
int u_unfilled_generator( unsigned prim,
unsigned start,
unsigned nr,
unsigned unfilled_mode,
unsigned *out_prim,
unsigned *out_index_size,
unsigned *out_nr,
u_generate_func *out_generate )
{
unsigned out_idx;
u_unfilled_init();
*out_index_size = ((start + nr) > 0xfffe) ? 4 : 2;
out_idx = out_size_idx(*out_index_size);
if (unfilled_mode == PIPE_POLYGON_MODE_POINT) {
if (*out_index_size == 4)
*out_generate = generate_linear_uint;
else
*out_generate = generate_linear_ushort;
*out_prim = PIPE_PRIM_POINTS;
*out_nr = nr;
return U_GENERATE_LINEAR;
}
else {
assert(unfilled_mode == PIPE_POLYGON_MODE_LINE);
*out_prim = PIPE_PRIM_LINES;
*out_generate = generate_line[out_idx][prim];
*out_nr = nr_lines( prim, nr );
return U_GENERATE_REUSABLE;
}
}