move util/indices to core util
these are useful tools to have outside of gallium Reviewed-by: Jesse Natalie <jenatali@microsoft.com> Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Acked-by: Marek Olšák <marek.olsak@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13741>
This commit is contained in:
committed by
Marge Bot
parent
88e4d3809c
commit
97ba2f2fd4
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* 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_memcpy_ushort( const void *in,
|
||||
unsigned start,
|
||||
unsigned in_nr,
|
||||
unsigned out_nr,
|
||||
unsigned restart_index,
|
||||
void *out )
|
||||
{
|
||||
memcpy(out, &((short *)in)[start], out_nr*sizeof(short));
|
||||
}
|
||||
|
||||
static void translate_memcpy_uint( const void *in,
|
||||
unsigned start,
|
||||
unsigned in_nr,
|
||||
unsigned out_nr,
|
||||
unsigned restart_index,
|
||||
void *out )
|
||||
{
|
||||
memcpy(out, &((int *)in)[start], out_nr*sizeof(int));
|
||||
}
|
||||
|
||||
static void translate_byte_to_ushort( const void *in,
|
||||
unsigned start,
|
||||
UNUSED unsigned in_nr,
|
||||
unsigned out_nr,
|
||||
UNUSED unsigned restart_index,
|
||||
void *out )
|
||||
{
|
||||
uint8_t *src = (uint8_t *)in + start;
|
||||
uint16_t *dst = out;
|
||||
while (out_nr--) {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
|
||||
enum pipe_prim_type
|
||||
u_index_prim_type_convert(unsigned hw_mask, enum pipe_prim_type prim, bool pv_matches)
|
||||
{
|
||||
if ((hw_mask & (1<<prim)) && pv_matches)
|
||||
return prim;
|
||||
|
||||
switch (prim) {
|
||||
case PIPE_PRIM_POINTS:
|
||||
return PIPE_PRIM_POINTS;
|
||||
case PIPE_PRIM_LINES:
|
||||
case PIPE_PRIM_LINE_STRIP:
|
||||
case PIPE_PRIM_LINE_LOOP:
|
||||
return PIPE_PRIM_LINES;
|
||||
case PIPE_PRIM_TRIANGLES:
|
||||
case PIPE_PRIM_TRIANGLE_STRIP:
|
||||
case PIPE_PRIM_TRIANGLE_FAN:
|
||||
case PIPE_PRIM_QUADS:
|
||||
case PIPE_PRIM_QUAD_STRIP:
|
||||
case PIPE_PRIM_POLYGON:
|
||||
return PIPE_PRIM_TRIANGLES;
|
||||
case PIPE_PRIM_LINES_ADJACENCY:
|
||||
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
|
||||
return PIPE_PRIM_LINES_ADJACENCY;
|
||||
case PIPE_PRIM_TRIANGLES_ADJACENCY:
|
||||
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
|
||||
return PIPE_PRIM_TRIANGLES_ADJACENCY;
|
||||
case PIPE_PRIM_PATCHES:
|
||||
return PIPE_PRIM_PATCHES;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
return PIPE_PRIM_POINTS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate indexes when a driver can't support certain types
|
||||
* of drawing. Example include:
|
||||
* - Translate 1-byte indexes into 2-byte indexes
|
||||
* - Translate PIPE_PRIM_QUADS into PIPE_PRIM_TRIANGLES when the hardware
|
||||
* doesn't support the former.
|
||||
* - Translate from first provoking vertex to last provoking vertex and
|
||||
* vice versa.
|
||||
*
|
||||
* Note that this function is used for indexed primitives.
|
||||
*
|
||||
* \param hw_mask mask of (1 << PIPE_PRIM_x) flags indicating which types
|
||||
* of primitives are supported by the hardware.
|
||||
* \param prim incoming PIPE_PRIM_x
|
||||
* \param in_index_size bytes per index value (1, 2 or 4)
|
||||
* \param nr number of incoming vertices
|
||||
* \param in_pv incoming provoking vertex convention (PV_FIRST or PV_LAST)
|
||||
* \param out_pv desired provoking vertex convention (PV_FIRST or PV_LAST)
|
||||
* \param prim_restart whether primitive restart is disable or enabled
|
||||
* \param out_prim returns new PIPE_PRIM_x we'll translate to
|
||||
* \param out_index_size returns bytes per new index value (2 or 4)
|
||||
* \param out_nr returns number of new vertices
|
||||
* \param out_translate returns the translation function to use by the caller
|
||||
*/
|
||||
enum indices_mode
|
||||
u_index_translator(unsigned hw_mask,
|
||||
enum pipe_prim_type prim,
|
||||
unsigned in_index_size,
|
||||
unsigned nr,
|
||||
unsigned in_pv,
|
||||
unsigned out_pv,
|
||||
unsigned prim_restart,
|
||||
enum pipe_prim_type *out_prim,
|
||||
unsigned *out_index_size,
|
||||
unsigned *out_nr,
|
||||
u_translate_func *out_translate)
|
||||
{
|
||||
unsigned in_idx;
|
||||
unsigned out_idx;
|
||||
enum indices_mode ret = U_TRANSLATE_NORMAL;
|
||||
|
||||
assert(in_index_size == 1 ||
|
||||
in_index_size == 2 ||
|
||||
in_index_size == 4);
|
||||
|
||||
u_index_init();
|
||||
|
||||
in_idx = in_size_idx(in_index_size);
|
||||
*out_index_size = u_index_size_convert(in_index_size);
|
||||
out_idx = out_size_idx(*out_index_size);
|
||||
|
||||
if ((hw_mask & (1<<prim)) &&
|
||||
in_pv == out_pv)
|
||||
{
|
||||
if (in_index_size == 4)
|
||||
*out_translate = translate_memcpy_uint;
|
||||
else if (in_index_size == 2)
|
||||
*out_translate = translate_memcpy_ushort;
|
||||
else
|
||||
*out_translate = translate_byte_to_ushort;
|
||||
|
||||
*out_prim = prim;
|
||||
*out_nr = nr;
|
||||
|
||||
return U_TRANSLATE_MEMCPY;
|
||||
}
|
||||
*out_translate = translate[in_idx][out_idx][in_pv][out_pv][prim_restart][prim];
|
||||
*out_prim = u_index_prim_type_convert(hw_mask, prim, in_pv == out_pv);
|
||||
*out_nr = u_index_count_converted_indices(hw_mask, in_pv == out_pv, prim, nr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned
|
||||
u_index_count_converted_indices(unsigned hw_mask, bool pv_matches, enum pipe_prim_type prim, unsigned nr)
|
||||
{
|
||||
if ((hw_mask & (1<<prim)) && pv_matches)
|
||||
return nr;
|
||||
|
||||
switch (prim) {
|
||||
case PIPE_PRIM_POINTS:
|
||||
case PIPE_PRIM_PATCHES:
|
||||
return nr;
|
||||
case PIPE_PRIM_LINES:
|
||||
return nr;
|
||||
case PIPE_PRIM_LINE_STRIP:
|
||||
return (nr - 1) * 2;
|
||||
case PIPE_PRIM_LINE_LOOP:
|
||||
return nr * 2;
|
||||
case PIPE_PRIM_TRIANGLES:
|
||||
return nr;
|
||||
case PIPE_PRIM_TRIANGLE_STRIP:
|
||||
return (nr - 2) * 3;
|
||||
case PIPE_PRIM_TRIANGLE_FAN:
|
||||
return (nr - 2) * 3;
|
||||
case PIPE_PRIM_QUADS:
|
||||
return (nr / 4) * 6;
|
||||
case PIPE_PRIM_QUAD_STRIP:
|
||||
return (nr - 2) * 3;
|
||||
case PIPE_PRIM_POLYGON:
|
||||
return (nr - 2) * 3;
|
||||
case PIPE_PRIM_LINES_ADJACENCY:
|
||||
return nr;
|
||||
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
|
||||
return (nr - 3) * 4;
|
||||
case PIPE_PRIM_TRIANGLES_ADJACENCY:
|
||||
return nr;
|
||||
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
|
||||
return ((nr - 4) / 2) * 6;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
return nr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If a driver does not support a particular gallium primitive type
|
||||
* (such as PIPE_PRIM_QUAD_STRIP) this function can be used to help
|
||||
* convert the primitive into a simpler type (like PIPE_PRIM_TRIANGLES).
|
||||
*
|
||||
* The generator functions generates a number of ushort or uint indexes
|
||||
* for drawing the new type of primitive.
|
||||
*
|
||||
* Note that this function is used for non-indexed primitives.
|
||||
*
|
||||
* \param hw_mask a bitmask of (1 << PIPE_PRIM_x) values that indicates
|
||||
* kind of primitives are supported by the driver.
|
||||
* \param prim the PIPE_PRIM_x that the user wants to draw
|
||||
* \param start index of first vertex to draw
|
||||
* \param nr number of vertices to draw
|
||||
* \param in_pv user's provoking vertex (PV_FIRST/LAST)
|
||||
* \param out_pv desired proking vertex for the hardware (PV_FIRST/LAST)
|
||||
* \param out_prim returns the new primitive type for the driver
|
||||
* \param out_index_size returns OUT_USHORT or OUT_UINT
|
||||
* \param out_nr returns new number of vertices to draw
|
||||
* \param out_generate returns pointer to the generator function
|
||||
*/
|
||||
enum indices_mode
|
||||
u_index_generator(unsigned hw_mask,
|
||||
enum pipe_prim_type prim,
|
||||
unsigned start,
|
||||
unsigned nr,
|
||||
unsigned in_pv,
|
||||
unsigned out_pv,
|
||||
enum pipe_prim_type *out_prim,
|
||||
unsigned *out_index_size,
|
||||
unsigned *out_nr,
|
||||
u_generate_func *out_generate)
|
||||
{
|
||||
unsigned out_idx;
|
||||
|
||||
u_index_init();
|
||||
|
||||
*out_index_size = ((start + nr) > 0xfffe) ? 4 : 2;
|
||||
out_idx = out_size_idx(*out_index_size);
|
||||
*out_prim = u_index_prim_type_convert(hw_mask, prim, in_pv == out_pv);
|
||||
*out_nr = u_index_count_converted_indices(hw_mask, in_pv == out_pv, prim, nr);
|
||||
|
||||
if ((hw_mask & (1<<prim)) &&
|
||||
(in_pv == out_pv)) {
|
||||
|
||||
*out_generate = generate[out_idx][in_pv][out_pv][PIPE_PRIM_POINTS];
|
||||
return U_GENERATE_LINEAR;
|
||||
}
|
||||
*out_generate = generate[out_idx][in_pv][out_pv][prim];
|
||||
return prim == PIPE_PRIM_LINE_LOOP ? U_GENERATE_ONE_OFF : U_GENERATE_REUSABLE;
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef U_INDICES_H
|
||||
#define U_INDICES_H
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "pipe/p_defines.h"
|
||||
|
||||
/* First/last provoking vertex */
|
||||
#define PV_FIRST 0
|
||||
#define PV_LAST 1
|
||||
#define PV_COUNT 2
|
||||
|
||||
/* primitive restart disable/enable flags */
|
||||
#define PR_DISABLE 0
|
||||
#define PR_ENABLE 1
|
||||
#define PR_COUNT 2
|
||||
|
||||
|
||||
/**
|
||||
* Index translator function (for glDrawElements() case)
|
||||
*
|
||||
* \param in the input index buffer
|
||||
* \param start the index of the first vertex (pipe_draw_info::start)
|
||||
* \param nr the number of vertices (pipe_draw_info::count)
|
||||
* \param out output buffer big enough for nr vertices (of
|
||||
* @out_index_size bytes each)
|
||||
*/
|
||||
typedef void (*u_translate_func)( const void *in,
|
||||
unsigned start,
|
||||
unsigned in_nr,
|
||||
unsigned out_nr,
|
||||
unsigned restart_index,
|
||||
void *out );
|
||||
|
||||
/**
|
||||
* Index generator function (for glDrawArrays() case)
|
||||
*
|
||||
* \param start the index of the first vertex (pipe_draw_info::start)
|
||||
* \param nr the number of vertices (pipe_draw_info::count)
|
||||
* \param out output buffer big enough for nr vertices (of
|
||||
* @out_index_size bytes each)
|
||||
*/
|
||||
typedef void (*u_generate_func)( unsigned start,
|
||||
unsigned nr,
|
||||
void *out );
|
||||
|
||||
|
||||
/* Return codes describe the translate/generate operation. Caller may
|
||||
* be able to reuse translated indices under some circumstances.
|
||||
*/
|
||||
enum indices_mode {
|
||||
U_TRANSLATE_ERROR = -1,
|
||||
U_TRANSLATE_NORMAL = 1,
|
||||
U_TRANSLATE_MEMCPY = 2,
|
||||
U_GENERATE_LINEAR = 3,
|
||||
U_GENERATE_REUSABLE= 4,
|
||||
U_GENERATE_ONE_OFF = 5,
|
||||
};
|
||||
|
||||
void u_index_init( void );
|
||||
|
||||
/* returns the primitive type resulting from index translation */
|
||||
enum pipe_prim_type
|
||||
u_index_prim_type_convert(unsigned hw_mask, enum pipe_prim_type prim, bool pv_matches);
|
||||
|
||||
static inline unsigned
|
||||
u_index_size_convert(unsigned index_size)
|
||||
{
|
||||
return (index_size == 4) ? 4 : 2;
|
||||
}
|
||||
|
||||
unsigned
|
||||
u_index_count_converted_indices(unsigned hw_mask, bool pv_matches, enum pipe_prim_type prim, unsigned nr);
|
||||
|
||||
/**
|
||||
* For indexed drawing, this function determines what kind of primitive
|
||||
* transformation is needed (if any) for handling:
|
||||
* - unsupported primitive types (such as PIPE_PRIM_POLYGON)
|
||||
* - changing the provoking vertex
|
||||
* - primitive restart
|
||||
* - index size (1 byte, 2 byte or 4 byte indexes)
|
||||
*/
|
||||
enum indices_mode
|
||||
u_index_translator(unsigned hw_mask,
|
||||
enum pipe_prim_type prim,
|
||||
unsigned in_index_size,
|
||||
unsigned nr,
|
||||
unsigned in_pv, /* API */
|
||||
unsigned out_pv, /* hardware */
|
||||
unsigned prim_restart,
|
||||
enum pipe_prim_type *out_prim,
|
||||
unsigned *out_index_size,
|
||||
unsigned *out_nr,
|
||||
u_translate_func *out_translate);
|
||||
|
||||
|
||||
/**
|
||||
* For non-indexed drawing, this function determines what kind of primitive
|
||||
* transformation is needed (see above).
|
||||
*
|
||||
* Note that even when generating it is necessary to know what the
|
||||
* API's PV is, as the indices generated will depend on whether it is
|
||||
* the same as hardware or not, and in the case of triangle strips,
|
||||
* whether it is first or last.
|
||||
*/
|
||||
enum indices_mode
|
||||
u_index_generator(unsigned hw_mask,
|
||||
enum pipe_prim_type prim,
|
||||
unsigned start,
|
||||
unsigned nr,
|
||||
unsigned in_pv, /* API */
|
||||
unsigned out_pv, /* hardware */
|
||||
enum pipe_prim_type *out_prim,
|
||||
unsigned *out_index_size,
|
||||
unsigned *out_nr,
|
||||
u_generate_func *out_generate);
|
||||
|
||||
|
||||
void u_unfilled_init( void );
|
||||
|
||||
/**
|
||||
* If the driver can't handle "unfilled" primitives (i.e. drawing triangle
|
||||
* primitives as 3 lines or 3 points) this function can be used to translate
|
||||
* an indexed primitive into a new indexed primitive to draw as lines or
|
||||
* points.
|
||||
*/
|
||||
enum indices_mode
|
||||
u_unfilled_translator(enum pipe_prim_type prim,
|
||||
unsigned in_index_size,
|
||||
unsigned nr,
|
||||
unsigned unfilled_mode,
|
||||
enum pipe_prim_type *out_prim,
|
||||
unsigned *out_index_size,
|
||||
unsigned *out_nr,
|
||||
u_translate_func *out_translate);
|
||||
|
||||
/**
|
||||
* As above, but for non-indexed (array) primitives.
|
||||
*/
|
||||
enum indices_mode
|
||||
u_unfilled_generator(enum pipe_prim_type prim,
|
||||
unsigned start,
|
||||
unsigned nr,
|
||||
unsigned unfilled_mode,
|
||||
enum pipe_prim_type *out_prim,
|
||||
unsigned *out_index_size,
|
||||
unsigned *out_nr,
|
||||
u_generate_func *out_generate);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,462 @@
|
||||
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'
|
||||
PRDISABLE, PRENABLE = 'prdisable', 'prenable'
|
||||
|
||||
INTYPES = (GENERATE, UBYTE, USHORT, UINT)
|
||||
OUTTYPES = (USHORT, UINT)
|
||||
PVS=(FIRST, LAST)
|
||||
PRS=(PRDISABLE, PRENABLE)
|
||||
PRIMS=('points',
|
||||
'lines',
|
||||
'linestrip',
|
||||
'lineloop',
|
||||
'tris',
|
||||
'trifan',
|
||||
'tristrip',
|
||||
'quads',
|
||||
'quadstrip',
|
||||
'polygon',
|
||||
'linesadj',
|
||||
'linestripadj',
|
||||
'trisadj',
|
||||
'tristripadj')
|
||||
|
||||
LONGPRIMS=('PIPE_PRIM_POINTS',
|
||||
'PIPE_PRIM_LINES',
|
||||
'PIPE_PRIM_LINE_STRIP',
|
||||
'PIPE_PRIM_LINE_LOOP',
|
||||
'PIPE_PRIM_TRIANGLES',
|
||||
'PIPE_PRIM_TRIANGLE_FAN',
|
||||
'PIPE_PRIM_TRIANGLE_STRIP',
|
||||
'PIPE_PRIM_QUADS',
|
||||
'PIPE_PRIM_QUAD_STRIP',
|
||||
'PIPE_PRIM_POLYGON',
|
||||
'PIPE_PRIM_LINES_ADJACENCY',
|
||||
'PIPE_PRIM_LINE_STRIP_ADJACENCY',
|
||||
'PIPE_PRIM_TRIANGLES_ADJACENCY',
|
||||
'PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY')
|
||||
|
||||
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')
|
||||
pv_idx = dict(first='PV_FIRST', last='PV_LAST')
|
||||
pr_idx = dict(prdisable='PR_DISABLE', prenable='PR_ENABLE')
|
||||
|
||||
def prolog():
|
||||
print('''/* File automatically generated by u_indices_gen.py */''')
|
||||
print(copyright)
|
||||
print(r'''
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Functions to translate and generate index lists
|
||||
*/
|
||||
|
||||
#include "indices/u_indices_priv.h"
|
||||
#include "util/u_debug.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_translate_func translate[IN_COUNT][OUT_COUNT][PV_COUNT][PV_COUNT][PR_COUNT][PRIM_COUNT];
|
||||
static u_generate_func generate[OUT_COUNT][PV_COUNT][PV_COUNT][PRIM_COUNT];
|
||||
|
||||
|
||||
''')
|
||||
|
||||
def vert( intype, outtype, v0 ):
|
||||
if intype == GENERATE:
|
||||
return '(' + outtype + ')(' + v0 + ')'
|
||||
else:
|
||||
return '(' + outtype + ')in[' + v0 + ']'
|
||||
|
||||
def point( intype, outtype, ptr, v0 ):
|
||||
print(' (' + ptr + ')[0] = ' + vert( intype, outtype, v0 ) + ';')
|
||||
|
||||
def line( intype, outtype, ptr, v0, v1 ):
|
||||
print(' (' + ptr + ')[0] = ' + vert( intype, outtype, v0 ) + ';')
|
||||
print(' (' + ptr + ')[1] = ' + vert( intype, outtype, v1 ) + ';')
|
||||
|
||||
def tri( intype, outtype, ptr, v0, v1, v2 ):
|
||||
print(' (' + ptr + ')[0] = ' + vert( intype, outtype, v0 ) + ';')
|
||||
print(' (' + ptr + ')[1] = ' + vert( intype, outtype, v1 ) + ';')
|
||||
print(' (' + ptr + ')[2] = ' + vert( intype, outtype, v2 ) + ';')
|
||||
|
||||
def lineadj( intype, outtype, ptr, v0, v1, v2, v3 ):
|
||||
print(' (' + ptr + ')[0] = ' + vert( intype, outtype, v0 ) + ';')
|
||||
print(' (' + ptr + ')[1] = ' + vert( intype, outtype, v1 ) + ';')
|
||||
print(' (' + ptr + ')[2] = ' + vert( intype, outtype, v2 ) + ';')
|
||||
print(' (' + ptr + ')[3] = ' + vert( intype, outtype, v3 ) + ';')
|
||||
|
||||
def triadj( intype, outtype, ptr, v0, v1, v2, v3, v4, v5 ):
|
||||
print(' (' + ptr + ')[0] = ' + vert( intype, outtype, v0 ) + ';')
|
||||
print(' (' + ptr + ')[1] = ' + vert( intype, outtype, v1 ) + ';')
|
||||
print(' (' + ptr + ')[2] = ' + vert( intype, outtype, v2 ) + ';')
|
||||
print(' (' + ptr + ')[3] = ' + vert( intype, outtype, v3 ) + ';')
|
||||
print(' (' + ptr + ')[4] = ' + vert( intype, outtype, v4 ) + ';')
|
||||
print(' (' + ptr + ')[5] = ' + vert( intype, outtype, v5 ) + ';')
|
||||
|
||||
def do_point( intype, outtype, ptr, v0 ):
|
||||
point( intype, outtype, ptr, v0 )
|
||||
|
||||
def do_line( intype, outtype, ptr, v0, v1, inpv, outpv ):
|
||||
if inpv == outpv:
|
||||
line( intype, outtype, ptr, v0, v1 )
|
||||
else:
|
||||
line( intype, outtype, ptr, v1, v0 )
|
||||
|
||||
def do_tri( intype, outtype, ptr, v0, v1, v2, inpv, outpv ):
|
||||
if inpv == outpv:
|
||||
tri( intype, outtype, ptr, v0, v1, v2 )
|
||||
else:
|
||||
if inpv == FIRST:
|
||||
tri( intype, outtype, ptr, v1, v2, v0 )
|
||||
else:
|
||||
tri( intype, outtype, ptr, v2, v0, v1 )
|
||||
|
||||
def do_quad( intype, outtype, ptr, v0, v1, v2, v3, inpv, outpv ):
|
||||
if inpv == LAST:
|
||||
do_tri( intype, outtype, ptr+'+0', v0, v1, v3, inpv, outpv );
|
||||
do_tri( intype, outtype, ptr+'+3', v1, v2, v3, inpv, outpv );
|
||||
else:
|
||||
do_tri( intype, outtype, ptr+'+0', v0, v1, v2, inpv, outpv );
|
||||
do_tri( intype, outtype, ptr+'+3', v0, v2, v3, inpv, outpv );
|
||||
|
||||
def do_lineadj( intype, outtype, ptr, v0, v1, v2, v3, inpv, outpv ):
|
||||
if inpv == outpv:
|
||||
lineadj( intype, outtype, ptr, v0, v1, v2, v3 )
|
||||
else:
|
||||
lineadj( intype, outtype, ptr, v3, v2, v1, v0 )
|
||||
|
||||
def do_triadj( intype, outtype, ptr, v0, v1, v2, v3, v4, v5, inpv, outpv ):
|
||||
if inpv == outpv:
|
||||
triadj( intype, outtype, ptr, v0, v1, v2, v3, v4, v5 )
|
||||
else:
|
||||
triadj( intype, outtype, ptr, v4, v5, v0, v1, v2, v3 )
|
||||
|
||||
def name(intype, outtype, inpv, outpv, pr, prim):
|
||||
if intype == GENERATE:
|
||||
return 'generate_' + prim + '_' + outtype + '_' + inpv + '2' + outpv
|
||||
else:
|
||||
return 'translate_' + prim + '_' + intype + '2' + outtype + '_' + inpv + '2' + outpv + '_' + pr
|
||||
|
||||
def preamble(intype, outtype, inpv, outpv, pr, prim):
|
||||
print('static void ' + name( intype, outtype, inpv, outpv, pr, prim ) + '(')
|
||||
if intype != GENERATE:
|
||||
print(' const void * restrict _in,')
|
||||
print(' unsigned start,')
|
||||
if intype != GENERATE:
|
||||
print(' unsigned in_nr,')
|
||||
print(' unsigned out_nr,')
|
||||
if intype != GENERATE:
|
||||
print(' unsigned restart_index,')
|
||||
print(' void * restrict _out )')
|
||||
print('{')
|
||||
if intype != GENERATE:
|
||||
print(' const ' + intype + '* restrict in = (const ' + intype + '* restrict)_in;')
|
||||
print(' ' + outtype + ' * restrict out = (' + outtype + '* restrict)_out;')
|
||||
print(' unsigned i, j;')
|
||||
print(' (void)j;')
|
||||
|
||||
def postamble():
|
||||
print('}')
|
||||
|
||||
def prim_restart(in_verts, out_verts, out_prims, close_func = None):
|
||||
print('restart:')
|
||||
print(' if (i + ' + str(in_verts) + ' > in_nr) {')
|
||||
for i in range(out_prims):
|
||||
for j in range(out_verts):
|
||||
print(' (out+j+' + str(out_verts * i) + ')[' + str(j) + '] = restart_index;')
|
||||
print(' continue;')
|
||||
print(' }')
|
||||
for i in range(in_verts):
|
||||
print(' if (in[i + ' + str(i) + '] == restart_index) {')
|
||||
print(' i += ' + str(i + 1) + ';')
|
||||
|
||||
if close_func is not None:
|
||||
close_func(i)
|
||||
|
||||
print(' goto restart;')
|
||||
print(' }')
|
||||
|
||||
def points(intype, outtype, inpv, outpv, pr):
|
||||
preamble(intype, outtype, inpv, outpv, pr, prim='points')
|
||||
print(' for (i = start, j = 0; j < out_nr; j++, i++) { ')
|
||||
do_point( intype, outtype, 'out+j', 'i' );
|
||||
print(' }')
|
||||
postamble()
|
||||
|
||||
def lines(intype, outtype, inpv, outpv, pr):
|
||||
preamble(intype, outtype, inpv, outpv, pr, prim='lines')
|
||||
print(' for (i = start, j = 0; j < out_nr; j+=2, i+=2) { ')
|
||||
do_line( intype, outtype, 'out+j', 'i', 'i+1', inpv, outpv );
|
||||
print(' }')
|
||||
postamble()
|
||||
|
||||
def linestrip(intype, outtype, inpv, outpv, pr):
|
||||
preamble(intype, outtype, inpv, outpv, pr, prim='linestrip')
|
||||
print(' for (i = start, j = 0; j < out_nr; j+=2, i++) { ')
|
||||
do_line( intype, outtype, 'out+j', 'i', 'i+1', inpv, outpv );
|
||||
print(' }')
|
||||
postamble()
|
||||
|
||||
def lineloop(intype, outtype, inpv, outpv, pr):
|
||||
preamble(intype, outtype, inpv, outpv, pr, prim='lineloop')
|
||||
print(' unsigned end = start;')
|
||||
print(' for (i = start, j = 0; j < out_nr - 2; j+=2, i++) { ')
|
||||
if pr == PRENABLE:
|
||||
def close_func(index):
|
||||
do_line( intype, outtype, 'out+j', 'end', 'start', inpv, outpv )
|
||||
print(' start = i;')
|
||||
print(' end = start;')
|
||||
print(' j += 2;')
|
||||
|
||||
prim_restart(2, 2, 1, close_func)
|
||||
|
||||
do_line( intype, outtype, 'out+j', 'i', 'i+1', inpv, outpv );
|
||||
print(' end = i+1;')
|
||||
print(' }')
|
||||
do_line( intype, outtype, 'out+j', 'end', 'start', inpv, outpv );
|
||||
postamble()
|
||||
|
||||
def tris(intype, outtype, inpv, outpv, pr):
|
||||
preamble(intype, outtype, inpv, outpv, pr, prim='tris')
|
||||
print(' for (i = start, j = 0; j < out_nr; j+=3, i+=3) { ')
|
||||
do_tri( intype, outtype, 'out+j', 'i', 'i+1', 'i+2', inpv, outpv );
|
||||
print(' }')
|
||||
postamble()
|
||||
|
||||
|
||||
def tristrip(intype, outtype, inpv, outpv, pr):
|
||||
preamble(intype, outtype, inpv, outpv, pr, prim='tristrip')
|
||||
print(' for (i = start, j = 0; j < out_nr; j+=3, i++) { ')
|
||||
if inpv == FIRST:
|
||||
do_tri( intype, outtype, 'out+j', 'i', 'i+1+(i&1)', 'i+2-(i&1)', inpv, outpv );
|
||||
else:
|
||||
do_tri( intype, outtype, 'out+j', 'i+(i&1)', 'i+1-(i&1)', 'i+2', inpv, outpv );
|
||||
print(' }')
|
||||
postamble()
|
||||
|
||||
|
||||
def trifan(intype, outtype, inpv, outpv, pr):
|
||||
preamble(intype, outtype, inpv, outpv, pr, prim='trifan')
|
||||
print(' for (i = start, j = 0; j < out_nr; j+=3, i++) { ')
|
||||
|
||||
if pr == PRENABLE:
|
||||
def close_func(index):
|
||||
print(' start = i;')
|
||||
prim_restart(3, 3, 1, close_func)
|
||||
|
||||
if inpv == FIRST:
|
||||
do_tri( intype, outtype, 'out+j', 'i+1', 'i+2', 'start', inpv, outpv );
|
||||
else:
|
||||
do_tri( intype, outtype, 'out+j', 'start', 'i+1', 'i+2', inpv, outpv );
|
||||
|
||||
print(' }')
|
||||
postamble()
|
||||
|
||||
|
||||
|
||||
def polygon(intype, outtype, inpv, outpv, pr):
|
||||
preamble(intype, outtype, inpv, outpv, pr, prim='polygon')
|
||||
print(' for (i = start, j = 0; j < out_nr; j+=3, i++) { ')
|
||||
if pr == PRENABLE:
|
||||
def close_func(index):
|
||||
print(' start = i;')
|
||||
prim_restart(3, 3, 1, close_func)
|
||||
|
||||
if inpv == FIRST:
|
||||
do_tri( intype, outtype, 'out+j', 'start', 'i+1', 'i+2', inpv, outpv );
|
||||
else:
|
||||
do_tri( intype, outtype, 'out+j', 'i+1', 'i+2', 'start', inpv, outpv );
|
||||
print(' }')
|
||||
postamble()
|
||||
|
||||
|
||||
def quads(intype, outtype, inpv, outpv, pr):
|
||||
preamble(intype, outtype, inpv, outpv, pr, prim='quads')
|
||||
print(' for (i = start, j = 0; j < out_nr; j+=6, i+=4) { ')
|
||||
if pr == PRENABLE:
|
||||
prim_restart(4, 3, 2)
|
||||
|
||||
do_quad( intype, outtype, 'out+j', 'i+0', 'i+1', 'i+2', 'i+3', inpv, outpv );
|
||||
print(' }')
|
||||
postamble()
|
||||
|
||||
|
||||
def quadstrip(intype, outtype, inpv, outpv, pr):
|
||||
preamble(intype, outtype, inpv, outpv, pr, prim='quadstrip')
|
||||
print(' for (i = start, j = 0; j < out_nr; j+=6, i+=2) { ')
|
||||
if pr == PRENABLE:
|
||||
prim_restart(4, 3, 2)
|
||||
|
||||
if inpv == LAST:
|
||||
do_quad( intype, outtype, 'out+j', 'i+2', 'i+0', 'i+1', 'i+3', inpv, outpv );
|
||||
else:
|
||||
do_quad( intype, outtype, 'out+j', 'i+0', 'i+1', 'i+3', 'i+2', inpv, outpv );
|
||||
print(' }')
|
||||
postamble()
|
||||
|
||||
|
||||
def linesadj(intype, outtype, inpv, outpv, pr):
|
||||
preamble(intype, outtype, inpv, outpv, pr, prim='linesadj')
|
||||
print(' for (i = start, j = 0; j < out_nr; j+=4, i+=4) { ')
|
||||
do_lineadj( intype, outtype, 'out+j', 'i+0', 'i+1', 'i+2', 'i+3', inpv, outpv )
|
||||
print(' }')
|
||||
postamble()
|
||||
|
||||
|
||||
def linestripadj(intype, outtype, inpv, outpv, pr):
|
||||
preamble(intype, outtype, inpv, outpv, pr, prim='linestripadj')
|
||||
print(' for (i = start, j = 0; j < out_nr; j+=4, i++) {')
|
||||
do_lineadj( intype, outtype, 'out+j', 'i+0', 'i+1', 'i+2', 'i+3', inpv, outpv )
|
||||
print(' }')
|
||||
postamble()
|
||||
|
||||
|
||||
def trisadj(intype, outtype, inpv, outpv, pr):
|
||||
preamble(intype, outtype, inpv, outpv, pr, prim='trisadj')
|
||||
print(' for (i = start, j = 0; j < out_nr; j+=6, i+=6) { ')
|
||||
do_triadj( intype, outtype, 'out+j', 'i+0', 'i+1', 'i+2', 'i+3',
|
||||
'i+4', 'i+5', inpv, outpv )
|
||||
print(' }')
|
||||
postamble()
|
||||
|
||||
|
||||
def tristripadj(intype, outtype, inpv, outpv, pr):
|
||||
preamble(intype, outtype, inpv, outpv, pr, prim='tristripadj')
|
||||
print(' for (i = start, j = 0; j < out_nr; i+=2, j+=6) { ')
|
||||
print(' if (i % 4 == 0) {')
|
||||
print(' /* even triangle */')
|
||||
do_triadj( intype, outtype, 'out+j',
|
||||
'i+0', 'i+1', 'i+2', 'i+3', 'i+4', 'i+5', inpv, outpv )
|
||||
print(' } else {')
|
||||
print(' /* odd triangle */')
|
||||
do_triadj( intype, outtype, 'out+j',
|
||||
'i+2', 'i-2', 'i+0', 'i+3', 'i+4', 'i+6', inpv, outpv )
|
||||
print(' }')
|
||||
print(' }')
|
||||
postamble()
|
||||
|
||||
|
||||
def emit_funcs():
|
||||
for intype in INTYPES:
|
||||
for outtype in OUTTYPES:
|
||||
for inpv in (FIRST, LAST):
|
||||
for outpv in (FIRST, LAST):
|
||||
for pr in (PRDISABLE, PRENABLE):
|
||||
if pr == PRENABLE and intype == GENERATE:
|
||||
continue
|
||||
points(intype, outtype, inpv, outpv, pr)
|
||||
lines(intype, outtype, inpv, outpv, pr)
|
||||
linestrip(intype, outtype, inpv, outpv, pr)
|
||||
lineloop(intype, outtype, inpv, outpv, pr)
|
||||
tris(intype, outtype, inpv, outpv, pr)
|
||||
tristrip(intype, outtype, inpv, outpv, pr)
|
||||
trifan(intype, outtype, inpv, outpv, pr)
|
||||
quads(intype, outtype, inpv, outpv, pr)
|
||||
quadstrip(intype, outtype, inpv, outpv, pr)
|
||||
polygon(intype, outtype, inpv, outpv, pr)
|
||||
linesadj(intype, outtype, inpv, outpv, pr)
|
||||
linestripadj(intype, outtype, inpv, outpv, pr)
|
||||
trisadj(intype, outtype, inpv, outpv, pr)
|
||||
tristripadj(intype, outtype, inpv, outpv, pr)
|
||||
|
||||
def init(intype, outtype, inpv, outpv, pr, prim):
|
||||
if intype == GENERATE:
|
||||
print ('generate[' +
|
||||
outtype_idx[outtype] +
|
||||
'][' + pv_idx[inpv] +
|
||||
'][' + pv_idx[outpv] +
|
||||
'][' + longprim[prim] +
|
||||
'] = ' + name( intype, outtype, inpv, outpv, pr, prim ) + ';')
|
||||
else:
|
||||
print ('translate[' +
|
||||
intype_idx[intype] +
|
||||
'][' + outtype_idx[outtype] +
|
||||
'][' + pv_idx[inpv] +
|
||||
'][' + pv_idx[outpv] +
|
||||
'][' + pr_idx[pr] +
|
||||
'][' + longprim[prim] +
|
||||
'] = ' + name( intype, outtype, inpv, outpv, pr, prim ) + ';')
|
||||
|
||||
|
||||
def emit_all_inits():
|
||||
for intype in INTYPES:
|
||||
for outtype in OUTTYPES:
|
||||
for inpv in PVS:
|
||||
for outpv in PVS:
|
||||
for pr in PRS:
|
||||
for prim in PRIMS:
|
||||
init(intype, outtype, inpv, outpv, pr, prim)
|
||||
|
||||
def emit_init():
|
||||
print('void u_index_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_indices.c"')
|
||||
|
||||
|
||||
def main():
|
||||
prolog()
|
||||
emit_funcs()
|
||||
emit_init()
|
||||
epilog()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef U_INDICES_PRIV_H
|
||||
#define U_INDICES_PRIV_H
|
||||
|
||||
#include "pipe/p_compiler.h"
|
||||
#include "u_indices.h"
|
||||
|
||||
#define IN_UBYTE 0
|
||||
#define IN_USHORT 1
|
||||
#define IN_UINT 2
|
||||
#define IN_COUNT 3
|
||||
|
||||
#define OUT_USHORT 0
|
||||
#define OUT_UINT 1
|
||||
#define OUT_COUNT 2
|
||||
|
||||
|
||||
#define PRIM_COUNT (PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY + 1)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,359 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
|
||||
*
|
||||
* 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
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*
|
||||
* Authors:
|
||||
* Rob Clark <robclark@freedesktop.org>
|
||||
*/
|
||||
|
||||
/**
|
||||
* This module converts provides a more convenient front-end to u_indices,
|
||||
* etc, utils to convert primitive types supported not supported by the
|
||||
* hardware. It handles binding new index buffer state, and restoring
|
||||
* previous state after. To use, put something like this at the front of
|
||||
* drivers pipe->draw_vbo():
|
||||
*
|
||||
* // emulate unsupported primitives:
|
||||
* if (info->mode needs emulating) {
|
||||
* util_primconvert_save_rasterizer_state(ctx->primconvert, ctx->rasterizer);
|
||||
* util_primconvert_draw_vbo(ctx->primconvert, info);
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
#include "util/u_draw.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/u_prim.h"
|
||||
#include "util/u_prim_restart.h"
|
||||
#include "util/u_upload_mgr.h"
|
||||
|
||||
#include "indices/u_indices.h"
|
||||
#include "indices/u_primconvert.h"
|
||||
|
||||
struct primconvert_context
|
||||
{
|
||||
struct pipe_context *pipe;
|
||||
struct primconvert_config cfg;
|
||||
unsigned api_pv;
|
||||
};
|
||||
|
||||
|
||||
struct primconvert_context *
|
||||
util_primconvert_create_config(struct pipe_context *pipe,
|
||||
struct primconvert_config *cfg)
|
||||
{
|
||||
struct primconvert_context *pc = CALLOC_STRUCT(primconvert_context);
|
||||
if (!pc)
|
||||
return NULL;
|
||||
pc->pipe = pipe;
|
||||
pc->cfg = *cfg;
|
||||
return pc;
|
||||
}
|
||||
|
||||
struct primconvert_context *
|
||||
util_primconvert_create(struct pipe_context *pipe, uint32_t primtypes_mask)
|
||||
{
|
||||
struct primconvert_config cfg = { .primtypes_mask = primtypes_mask, .restart_primtypes_mask = primtypes_mask };
|
||||
return util_primconvert_create_config(pipe, &cfg);
|
||||
}
|
||||
|
||||
void
|
||||
util_primconvert_destroy(struct primconvert_context *pc)
|
||||
{
|
||||
FREE(pc);
|
||||
}
|
||||
|
||||
void
|
||||
util_primconvert_save_rasterizer_state(struct primconvert_context *pc,
|
||||
const struct pipe_rasterizer_state
|
||||
*rast)
|
||||
{
|
||||
util_primconvert_save_flatshade_first(pc, rast->flatshade_first);
|
||||
}
|
||||
|
||||
void
|
||||
util_primconvert_save_flatshade_first(struct primconvert_context *pc, bool flatshade_first)
|
||||
{
|
||||
/* if we actually translated the provoking vertex for the buffer,
|
||||
* we would actually need to save/restore rasterizer state. As
|
||||
* it is, we just need to make note of the pv.
|
||||
*/
|
||||
pc->api_pv = flatshade_first ? PV_FIRST : PV_LAST;
|
||||
}
|
||||
|
||||
static bool
|
||||
primconvert_init_draw(struct primconvert_context *pc,
|
||||
const struct pipe_draw_info *info,
|
||||
const struct pipe_draw_indirect_info *indirect,
|
||||
const struct pipe_draw_start_count_bias *draws,
|
||||
struct pipe_draw_info *new_info,
|
||||
struct pipe_draw_start_count_bias *new_draw)
|
||||
{
|
||||
struct pipe_draw_start_count_bias *direct_draws = NULL;
|
||||
unsigned num_direct_draws = 0;
|
||||
struct pipe_transfer *src_transfer = NULL;
|
||||
u_translate_func trans_func, direct_draw_func;
|
||||
u_generate_func gen_func;
|
||||
const void *src = NULL;
|
||||
void *dst;
|
||||
unsigned ib_offset;
|
||||
unsigned total_index_count = draws->count;
|
||||
void *rewrite_buffer = NULL;
|
||||
|
||||
const struct pipe_draw_start_count_bias *draw = &draws[0];
|
||||
|
||||
/* Filter out degenerate primitives, u_upload_alloc() will assert
|
||||
* on size==0 so just bail:
|
||||
*/
|
||||
if (!info->primitive_restart &&
|
||||
!u_trim_pipe_prim(info->mode, (unsigned*)&draw->count))
|
||||
return false;
|
||||
|
||||
util_draw_init_info(new_info);
|
||||
new_info->index_bounds_valid = info->index_bounds_valid;
|
||||
new_info->min_index = info->min_index;
|
||||
new_info->max_index = info->max_index;
|
||||
new_info->start_instance = info->start_instance;
|
||||
new_info->instance_count = info->instance_count;
|
||||
new_info->primitive_restart = info->primitive_restart;
|
||||
new_info->restart_index = info->restart_index;
|
||||
if (info->index_size) {
|
||||
enum pipe_prim_type mode = new_info->mode = u_index_prim_type_convert(pc->cfg.primtypes_mask, info->mode, true);
|
||||
unsigned index_size = info->index_size;
|
||||
new_info->index_size = u_index_size_convert(info->index_size);
|
||||
|
||||
src = info->has_user_indices ? info->index.user : NULL;
|
||||
if (!src) {
|
||||
src = pipe_buffer_map(pc->pipe, info->index.resource,
|
||||
PIPE_MAP_READ, &src_transfer);
|
||||
}
|
||||
src = (const uint8_t *)src;
|
||||
|
||||
/* if the resulting primitive type is not supported by the driver for primitive restart,
|
||||
* or if the original primitive type was not supported by the driver,
|
||||
* the draw needs to be rewritten to not use primitive restart
|
||||
*/
|
||||
if (info->primitive_restart &&
|
||||
(!(pc->cfg.restart_primtypes_mask & BITFIELD_BIT(mode)) ||
|
||||
!(pc->cfg.primtypes_mask & BITFIELD_BIT(info->mode)))) {
|
||||
/* step 1: rewrite draw to not use primitive primitive restart;
|
||||
* this pre-filters degenerate primitives
|
||||
*/
|
||||
direct_draws = util_prim_restart_convert_to_direct(src, info, draw, &num_direct_draws,
|
||||
&new_info->min_index, &new_info->max_index, &total_index_count);
|
||||
new_info->primitive_restart = false;
|
||||
/* step 2: get a translator function which does nothing but handle any index size conversions
|
||||
* which may or may not occur (8bit -> 16bit)
|
||||
*/
|
||||
u_index_translator(0xffff,
|
||||
info->mode, index_size, total_index_count,
|
||||
pc->api_pv, pc->api_pv,
|
||||
PR_DISABLE,
|
||||
&mode, &index_size, &new_draw->count,
|
||||
&direct_draw_func);
|
||||
/* this should always be a direct translation */
|
||||
assert(new_draw->count == total_index_count);
|
||||
/* step 3: allocate a temp buffer for an intermediate rewrite step
|
||||
* if no indices were found, this was a single incomplete restart and can be discarded
|
||||
*/
|
||||
if (total_index_count)
|
||||
rewrite_buffer = malloc(index_size * total_index_count);
|
||||
if (!rewrite_buffer) {
|
||||
if (src_transfer)
|
||||
pipe_buffer_unmap(pc->pipe, src_transfer);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* (step 4: get the actual primitive conversion translator function) */
|
||||
u_index_translator(pc->cfg.primtypes_mask,
|
||||
info->mode, index_size, total_index_count,
|
||||
pc->api_pv, pc->api_pv,
|
||||
new_info->primitive_restart ? PR_ENABLE : PR_DISABLE,
|
||||
&mode, &index_size, &new_draw->count,
|
||||
&trans_func);
|
||||
assert(new_info->mode == mode);
|
||||
assert(new_info->index_size == index_size);
|
||||
}
|
||||
else {
|
||||
enum pipe_prim_type mode = 0;
|
||||
unsigned index_size;
|
||||
|
||||
u_index_generator(pc->cfg.primtypes_mask,
|
||||
info->mode, draw->start, draw->count,
|
||||
pc->api_pv, pc->api_pv,
|
||||
&mode, &index_size, &new_draw->count,
|
||||
&gen_func);
|
||||
new_info->mode = mode;
|
||||
new_info->index_size = index_size;
|
||||
}
|
||||
|
||||
/* (step 5: allocate gpu memory sized for the FINAL index count) */
|
||||
u_upload_alloc(pc->pipe->stream_uploader, 0, new_info->index_size * new_draw->count, 4,
|
||||
&ib_offset, &new_info->index.resource, &dst);
|
||||
new_draw->start = ib_offset / new_info->index_size;
|
||||
new_draw->index_bias = info->index_size ? draw->index_bias : 0;
|
||||
|
||||
if (info->index_size) {
|
||||
if (num_direct_draws) {
|
||||
uint8_t *ptr = rewrite_buffer;
|
||||
uint8_t *dst_ptr = dst;
|
||||
/* step 6: if rewriting a prim-restart draw to direct draws,
|
||||
* loop over all the direct draws in order to rewrite them into a single index buffer
|
||||
* and draw in order to match the original call
|
||||
*/
|
||||
for (unsigned i = 0; i < num_direct_draws; i++) {
|
||||
/* step 6a: get the index count for this draw, once converted */
|
||||
unsigned tmp_count = u_index_count_converted_indices(pc->cfg.primtypes_mask, true, info->mode, direct_draws[i].count);
|
||||
/* step 6b: handle index size conversion using the temp buffer; no change in index count
|
||||
* TODO: this step can be optimized out if the index size is known to not change
|
||||
*/
|
||||
direct_draw_func(src, direct_draws[i].start, direct_draws[i].count, direct_draws[i].count, info->restart_index, ptr);
|
||||
/* step 6c: handle the primitive type conversion rewriting to the converted index count */
|
||||
trans_func(ptr, 0, direct_draws[i].count, tmp_count, info->restart_index, dst_ptr);
|
||||
/* step 6d: increment the temp buffer and mapped final index buffer pointers */
|
||||
ptr += new_info->index_size * direct_draws[i].count;
|
||||
dst_ptr += new_info->index_size * tmp_count;
|
||||
}
|
||||
/* step 7: set the final index count, which is the converted total index count from the original draw rewrite */
|
||||
new_draw->count = u_index_count_converted_indices(pc->cfg.primtypes_mask, true, info->mode, total_index_count);
|
||||
} else
|
||||
trans_func(src, draw->start, draw->count, new_draw->count, info->restart_index, dst);
|
||||
|
||||
if (pc->cfg.fixed_prim_restart && new_info->primitive_restart) {
|
||||
new_info->restart_index = (1ull << (new_info->index_size * 8)) - 1;
|
||||
if (info->restart_index != new_info->restart_index)
|
||||
util_translate_prim_restart_data(new_info->index_size, dst, dst,
|
||||
new_draw->count,
|
||||
info->restart_index);
|
||||
}
|
||||
}
|
||||
else {
|
||||
gen_func(draw->start, new_draw->count, dst);
|
||||
}
|
||||
|
||||
if (src_transfer)
|
||||
pipe_buffer_unmap(pc->pipe, src_transfer);
|
||||
|
||||
u_upload_unmap(pc->pipe->stream_uploader);
|
||||
|
||||
free(direct_draws);
|
||||
free(rewrite_buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
util_primconvert_draw_vbo(struct primconvert_context *pc,
|
||||
const struct pipe_draw_info *info,
|
||||
unsigned drawid_offset,
|
||||
const struct pipe_draw_indirect_info *indirect,
|
||||
const struct pipe_draw_start_count_bias *draws,
|
||||
unsigned num_draws)
|
||||
{
|
||||
struct pipe_draw_info new_info;
|
||||
struct pipe_draw_start_count_bias new_draw;
|
||||
|
||||
if (indirect && indirect->buffer) {
|
||||
/* this is stupid, but we're already doing a readback,
|
||||
* so this thing may as well get the rest of the job done
|
||||
*/
|
||||
unsigned draw_count = 0;
|
||||
struct u_indirect_params *new_draws = util_draw_indirect_read(pc->pipe, info, indirect, &draw_count);
|
||||
if (!new_draws)
|
||||
return;
|
||||
|
||||
for (unsigned i = 0; i < draw_count; i++)
|
||||
util_primconvert_draw_vbo(pc, &new_draws[i].info, drawid_offset + i, NULL, &new_draws[i].draw, 1);
|
||||
free(new_draws);
|
||||
return;
|
||||
}
|
||||
|
||||
if (num_draws > 1) {
|
||||
unsigned drawid = drawid_offset;
|
||||
for (unsigned i = 0; i < num_draws; i++) {
|
||||
if (draws[i].count && info->instance_count)
|
||||
util_primconvert_draw_vbo(pc, info, drawid, NULL, &draws[i], 1);
|
||||
if (info->increment_draw_id)
|
||||
drawid++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!primconvert_init_draw(pc, info, indirect, draws, &new_info, &new_draw))
|
||||
return;
|
||||
/* to the translated draw: */
|
||||
pc->pipe->draw_vbo(pc->pipe, &new_info, drawid_offset, NULL, &new_draw, 1);
|
||||
|
||||
pipe_resource_reference(&new_info.index.resource, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
util_primconvert_draw_vertex_state(struct primconvert_context *pc,
|
||||
struct pipe_vertex_state *vstate,
|
||||
uint32_t partial_velem_mask,
|
||||
struct pipe_draw_vertex_state_info info,
|
||||
const struct pipe_draw_start_count_bias *draws,
|
||||
unsigned num_draws)
|
||||
{
|
||||
struct pipe_draw_info new_info;
|
||||
struct pipe_draw_start_count_bias new_draw;
|
||||
|
||||
if (pc->cfg.primtypes_mask & BITFIELD_BIT(info.mode)) {
|
||||
pc->pipe->draw_vertex_state(pc->pipe, vstate, partial_velem_mask, info, draws, num_draws);
|
||||
return;
|
||||
}
|
||||
|
||||
if (num_draws > 1) {
|
||||
for (unsigned i = 0; i < num_draws; i++) {
|
||||
if (draws[i].count)
|
||||
util_primconvert_draw_vertex_state(pc, vstate, partial_velem_mask, info, &draws[i], 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
struct pipe_draw_info dinfo = {0};
|
||||
dinfo.mode = info.mode;
|
||||
dinfo.index_size = 4;
|
||||
dinfo.instance_count = 1;
|
||||
dinfo.index.resource = vstate->input.indexbuf;
|
||||
if (!primconvert_init_draw(pc, &dinfo, NULL, draws, &new_info, &new_draw))
|
||||
return;
|
||||
|
||||
struct pipe_vertex_state *new_state = pc->pipe->screen->create_vertex_state(pc->pipe->screen,
|
||||
&vstate->input.vbuffer,
|
||||
vstate->input.elements,
|
||||
vstate->input.num_elements,
|
||||
new_info.index.resource,
|
||||
vstate->input.full_velem_mask);
|
||||
if (new_state) {
|
||||
struct pipe_draw_vertex_state_info new_vinfo;
|
||||
new_vinfo.mode = new_info.mode;
|
||||
new_vinfo.take_vertex_state_ownership = true;
|
||||
/* to the translated draw: */
|
||||
pc->pipe->draw_vertex_state(pc->pipe, new_state, partial_velem_mask, new_vinfo, &new_draw, 1);
|
||||
}
|
||||
if (info.take_vertex_state_ownership)
|
||||
pipe_vertex_state_reference(&vstate, NULL);
|
||||
|
||||
pipe_resource_reference(&new_info.index.resource, NULL);
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
|
||||
*
|
||||
* 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
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
|
||||
*
|
||||
* Authors:
|
||||
* Rob Clark <robclark@freedesktop.org>
|
||||
*/
|
||||
|
||||
#ifndef U_PRIMCONVERT_H_
|
||||
#define U_PRIMCONVERT_H_
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct primconvert_context;
|
||||
|
||||
struct primconvert_config {
|
||||
uint32_t primtypes_mask;
|
||||
uint32_t restart_primtypes_mask;
|
||||
bool fixed_prim_restart;
|
||||
};
|
||||
|
||||
struct primconvert_context *util_primconvert_create(struct pipe_context *pipe,
|
||||
uint32_t primtypes_mask);
|
||||
struct primconvert_context *util_primconvert_create_config(struct pipe_context *pipe,
|
||||
struct primconvert_config *cfg);
|
||||
|
||||
void util_primconvert_destroy(struct primconvert_context *pc);
|
||||
void util_primconvert_save_rasterizer_state(struct primconvert_context *pc,
|
||||
const struct pipe_rasterizer_state
|
||||
*rast);
|
||||
void
|
||||
util_primconvert_save_flatshade_first(struct primconvert_context *pc, bool flatshade_first);
|
||||
void util_primconvert_draw_vbo(struct primconvert_context *pc,
|
||||
const struct pipe_draw_info *info,
|
||||
unsigned drawid_offset,
|
||||
const struct pipe_draw_indirect_info *indirect,
|
||||
const struct pipe_draw_start_count_bias *draws,
|
||||
unsigned num_draws);
|
||||
void
|
||||
util_primconvert_draw_vertex_state(struct primconvert_context *pc,
|
||||
struct pipe_vertex_state *state,
|
||||
uint32_t partial_velem_mask,
|
||||
struct pipe_draw_vertex_state_info info,
|
||||
const struct pipe_draw_start_count_bias *draws,
|
||||
unsigned num_draws);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* U_PRIMCONVERT_H_ */
|
||||
@@ -0,0 +1,272 @@
|
||||
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',
|
||||
'trisadj',
|
||||
'tristripadj')
|
||||
|
||||
LONGPRIMS=('PIPE_PRIM_TRIANGLES',
|
||||
'PIPE_PRIM_TRIANGLE_FAN',
|
||||
'PIPE_PRIM_TRIANGLE_STRIP',
|
||||
'PIPE_PRIM_QUADS',
|
||||
'PIPE_PRIM_QUAD_STRIP',
|
||||
'PIPE_PRIM_POLYGON',
|
||||
'PIPE_PRIM_TRIANGLES_ADJACENCY',
|
||||
'PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY')
|
||||
|
||||
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(' (' + 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 start,')
|
||||
if intype != GENERATE:
|
||||
print(' unsigned in_nr,')
|
||||
print(' unsigned out_nr,')
|
||||
if intype != GENERATE:
|
||||
print(' unsigned restart_index,')
|
||||
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 (i = start, j = 0; j < out_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 (i = start, j = 0; j < out_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 (i = start, j = 0; j < out_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 (i = start, j = 0; j < out_nr; j+=2, i++) { ')
|
||||
line( intype, outtype, 'out+j', 'i', '(i+1)%(out_nr/2)' )
|
||||
print(' }')
|
||||
postamble()
|
||||
|
||||
|
||||
def quads(intype, outtype):
|
||||
preamble(intype, outtype, prim='quads')
|
||||
print(' for (i = start, j = 0; j < out_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 (i = start, j = 0; j < out_nr; j+=8, i+=2) { ')
|
||||
do_quad( intype, outtype, 'out+j', 'i+2', 'i+0', 'i+1', 'i+3' );
|
||||
print(' }')
|
||||
postamble()
|
||||
|
||||
|
||||
def trisadj(intype, outtype):
|
||||
preamble(intype, outtype, prim='trisadj')
|
||||
print(' for (i = start, j = 0; j < out_nr; j+=6, i+=6) { ')
|
||||
do_tri( intype, outtype, 'out+j', 'i', 'i+2', 'i+4' );
|
||||
print(' }')
|
||||
postamble()
|
||||
|
||||
|
||||
def tristripadj(intype, outtype):
|
||||
preamble(intype, outtype, prim='tristripadj')
|
||||
print(' for (i = start, j = 0; j < out_nr; j+=6, i+=2) { ')
|
||||
do_tri( intype, outtype, 'out+j', 'i', 'i+2', 'i+4' );
|
||||
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)
|
||||
trisadj(intype, outtype)
|
||||
tristripadj(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()
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* NOTE: This file is not compiled by itself. It's actually #included
|
||||
* by the generated u_unfilled_gen.c file!
|
||||
*/
|
||||
|
||||
#include "u_indices.h"
|
||||
#include "u_indices_priv.h"
|
||||
#include "util/u_prim.h"
|
||||
|
||||
|
||||
static void translate_ubyte_ushort( const void *in,
|
||||
unsigned start,
|
||||
unsigned in_nr,
|
||||
unsigned out_nr,
|
||||
unsigned restart_index,
|
||||
void *out )
|
||||
{
|
||||
const ubyte *in_ub = (const ubyte *)in;
|
||||
ushort *out_us = (ushort *)out;
|
||||
unsigned i;
|
||||
for (i = 0; i < out_nr; i++)
|
||||
out_us[i] = (ushort) in_ub[i+start];
|
||||
}
|
||||
|
||||
static void translate_memcpy_ushort( const void *in,
|
||||
unsigned start,
|
||||
unsigned in_nr,
|
||||
unsigned out_nr,
|
||||
unsigned restart_index,
|
||||
void *out )
|
||||
{
|
||||
memcpy(out, &((short *)in)[start], out_nr*sizeof(short));
|
||||
}
|
||||
|
||||
static void translate_memcpy_uint( const void *in,
|
||||
unsigned start,
|
||||
unsigned in_nr,
|
||||
unsigned out_nr,
|
||||
unsigned restart_index,
|
||||
void *out )
|
||||
{
|
||||
memcpy(out, &((int *)in)[start], out_nr*sizeof(int));
|
||||
}
|
||||
|
||||
|
||||
static void generate_linear_ushort( unsigned start,
|
||||
unsigned nr,
|
||||
void *out )
|
||||
{
|
||||
ushort *out_us = (ushort *)out;
|
||||
unsigned i;
|
||||
for (i = 0; i < nr; i++)
|
||||
out_us[i] = (ushort)(i + start);
|
||||
}
|
||||
|
||||
static void generate_linear_uint( unsigned start,
|
||||
unsigned nr,
|
||||
void *out )
|
||||
{
|
||||
unsigned *out_ui = (unsigned *)out;
|
||||
unsigned i;
|
||||
for (i = 0; i < nr; i++)
|
||||
out_ui[i] = i + start;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a primitive type and number of vertices, return the number of vertices
|
||||
* needed to draw the primitive with fill mode = PIPE_POLYGON_MODE_LINE using
|
||||
* separate lines (PIPE_PRIM_LINES).
|
||||
*/
|
||||
static unsigned
|
||||
nr_lines(enum pipe_prim_type 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 2 * nr; /* a line (two verts) for each polygon edge */
|
||||
/* Note: these cases can't really be handled since drawing lines instead
|
||||
* of triangles would also require changing the GS. But if there's no GS,
|
||||
* this should work.
|
||||
*/
|
||||
case PIPE_PRIM_TRIANGLES_ADJACENCY:
|
||||
return (nr / 6) * 6;
|
||||
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
|
||||
return ((nr - 4) / 2) * 6;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum indices_mode
|
||||
u_unfilled_translator(enum pipe_prim_type prim,
|
||||
unsigned in_index_size,
|
||||
unsigned nr,
|
||||
unsigned unfilled_mode,
|
||||
enum pipe_prim_type *out_prim,
|
||||
unsigned *out_index_size,
|
||||
unsigned *out_nr,
|
||||
u_translate_func *out_translate)
|
||||
{
|
||||
unsigned in_idx;
|
||||
unsigned out_idx;
|
||||
|
||||
assert(u_reduced_prim(prim) == PIPE_PRIM_TRIANGLES);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility for converting unfilled polygons into points, lines, triangles.
|
||||
* Few drivers have direct support for OpenGL's glPolygonMode.
|
||||
* This function helps with converting triangles into points or lines
|
||||
* when the front and back fill modes are the same. When there's
|
||||
* different front/back fill modes, that can be handled with the
|
||||
* 'draw' module.
|
||||
*/
|
||||
enum indices_mode
|
||||
u_unfilled_generator(enum pipe_prim_type prim,
|
||||
unsigned start,
|
||||
unsigned nr,
|
||||
unsigned unfilled_mode,
|
||||
enum pipe_prim_type *out_prim,
|
||||
unsigned *out_index_size,
|
||||
unsigned *out_nr,
|
||||
u_generate_func *out_generate)
|
||||
{
|
||||
unsigned out_idx;
|
||||
|
||||
assert(u_reduced_prim(prim) == PIPE_PRIM_TRIANGLES);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
+21
-1
@@ -150,6 +150,10 @@ files_mesa_util = files(
|
||||
'vma.c',
|
||||
'vma.h',
|
||||
'xxhash.h',
|
||||
'indices/u_indices.h',
|
||||
'indices/u_indices_priv.h',
|
||||
'indices/u_primconvert.c',
|
||||
'indices/u_primconvert.h',
|
||||
)
|
||||
|
||||
files_drirc = files('00-mesa-defaults.conf')
|
||||
@@ -227,9 +231,25 @@ endif
|
||||
|
||||
u_trace_py = files('perf/u_trace.py')
|
||||
|
||||
u_indices_gen_c = custom_target(
|
||||
'u_indices_gen.c',
|
||||
input : 'indices/u_indices_gen.py',
|
||||
output : 'u_indices_gen.c',
|
||||
command : [prog_python, '@INPUT@'],
|
||||
capture : true,
|
||||
)
|
||||
|
||||
u_unfilled_gen_c = custom_target(
|
||||
'u_unfilled_gen.c',
|
||||
input : 'indices/u_unfilled_gen.py',
|
||||
output : 'u_unfilled_gen.c',
|
||||
command : [prog_python, '@INPUT@'],
|
||||
capture : true,
|
||||
)
|
||||
|
||||
_libmesa_util = static_library(
|
||||
'mesa_util',
|
||||
[files_mesa_util, files_debug_stack, format_srgb],
|
||||
[files_mesa_util, files_debug_stack, format_srgb, u_indices_gen_c, u_unfilled_gen_c],
|
||||
include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux],
|
||||
dependencies : deps_for_libmesa_util,
|
||||
link_with: libmesa_format,
|
||||
|
||||
Reference in New Issue
Block a user