diff options
Diffstat (limited to 'src/gallium/auxiliary')
98 files changed, 8167 insertions, 1112 deletions
diff --git a/src/gallium/auxiliary/cso_cache/cso_cache.c b/src/gallium/auxiliary/cso_cache/cso_cache.c index 0bc77a5728..e6dce3f0e5 100644 --- a/src/gallium/auxiliary/cso_cache/cso_cache.c +++ b/src/gallium/auxiliary/cso_cache/cso_cache.c @@ -361,6 +361,10 @@ void cso_for_each_state(struct cso_cache *sc, enum cso_cache_type type, void cso_cache_delete(struct cso_cache *sc) { assert(sc); + + if (!sc) + return; + /* delete driver data */ cso_for_each_state(sc, CSO_BLEND, delete_blend_state, 0); cso_for_each_state(sc, CSO_DEPTH_STENCIL_ALPHA, delete_depth_stencil_state, 0); diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index f388bf5d95..36c882acb7 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -55,14 +55,14 @@ struct cso_context { void *samplers[PIPE_MAX_SAMPLERS]; unsigned nr_samplers; - void *samplers_saved[PIPE_MAX_SAMPLERS]; unsigned nr_samplers_saved; + void *samplers_saved[PIPE_MAX_SAMPLERS]; struct pipe_texture *textures[PIPE_MAX_SAMPLERS]; uint nr_textures; - struct pipe_texture *textures_saved[PIPE_MAX_SAMPLERS]; uint nr_textures_saved; + struct pipe_texture *textures_saved[PIPE_MAX_SAMPLERS]; /** Current and saved state. * The saved state is used as a 1-deep stack. diff --git a/src/gallium/auxiliary/draw/draw_pipe.c b/src/gallium/auxiliary/draw/draw_pipe.c index 3cfae2de83..1c6d657297 100644 --- a/src/gallium/auxiliary/draw/draw_pipe.c +++ b/src/gallium/auxiliary/draw/draw_pipe.c @@ -248,22 +248,22 @@ void draw_pipeline_run( struct draw_context *draw, ( DRAW_PIPE_RESET_STIPPLE | \ DRAW_PIPE_EDGE_FLAG_0 | \ DRAW_PIPE_EDGE_FLAG_2 ), \ - verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \ - verts + stride * (i1), \ + verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \ + verts + stride * (i1), \ verts + stride * (i3)); \ - do_triangle( draw, \ - ( DRAW_PIPE_EDGE_FLAG_0 | \ - DRAW_PIPE_EDGE_FLAG_1 ), \ - verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \ - verts + stride * (i2), \ - verts + stride * (i3)) + do_triangle( draw, \ + ( DRAW_PIPE_EDGE_FLAG_0 | \ + DRAW_PIPE_EDGE_FLAG_1 ), \ + verts + stride * ((i1) & ~DRAW_PIPE_FLAG_MASK), \ + verts + stride * (i2), \ + verts + stride * (i3)) #define TRIANGLE(flags,i0,i1,i2) \ do_triangle( draw, \ flags, /* flags */ \ - verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \ - verts + stride * (i1), \ - verts + stride * (i2)) + verts + stride * ((i0) & ~DRAW_PIPE_FLAG_MASK), \ + verts + stride * (i1), \ + verts + stride * (i2)) #define LINE(flags,i0,i1) \ do_line( draw, \ diff --git a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c index 30a6d2919d..283502cdf3 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_pstipple.c +++ b/src/gallium/auxiliary/draw/draw_pipe_pstipple.c @@ -256,7 +256,10 @@ pstip_transform_inst(struct tgsi_transform_context *ctx, uint size = 4; immed = tgsi_default_full_immediate(); immed.Immediate.NrTokens = 1 + size; /* one for the token itself */ - immed.u.Pointer = (void *) value; + immed.u[0].Float = value[0]; + immed.u[1].Float = value[1]; + immed.u[2].Float = value[2]; + immed.u[3].Float = value[3]; ctx->emit_immediate(ctx, &immed); } diff --git a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c index a5d840b96e..1a5269c0de 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c +++ b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c @@ -159,8 +159,19 @@ vbuf_tri( struct draw_stage *stage, check_space( vbuf, 3 ); - for (i = 0; i < 3; i++) { - vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[i] ); + if (vbuf->stage.draw->rasterizer->flatshade_first) { + /* Put provoking vertex in position expected by the driver. + * Emit last provoking vertex in first pos. + * Swap verts 0 & 1 to preserve polygon winding. + */ + vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[2] ); + vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[0] ); + vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[1] ); + } + else { + for (i = 0; i < 3; i++) { + vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[i] ); + } } } diff --git a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c index d84bab9eaa..7d76a7dbf3 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c +++ b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c @@ -28,6 +28,30 @@ /* Authors: Keith Whitwell <keith@tungstengraphics.com> */ +/** + * Notes on wide points and sprite mode: + * + * In wide point/sprite mode we effectively need to convert each incoming + * vertex into four outgoing vertices specifying the corners of a quad. + * Since we don't (yet) have geometry shaders, we have to handle this here + * in the draw module. + * + * For sprites, it also means that this is where we have to handle texcoords + * for the vertices of the quad. OpenGL's GL_COORD_REPLACE state specifies + * if/how enabled texcoords are automatically generated for sprites. We pass + * that info through gallium in the pipe_rasterizer_state::sprite_coord_mode + * array. + * + * Additionally, GLSL's gl_PointCoord fragment attribute has to be handled + * here as well. This is basically an additional texture/generic attribute + * that varies .x from 0 to 1 horizontally across the point and varies .y + * vertically from 0 to 1 down the sprite. + * + * With geometry shaders, the state tracker could create a GS to do + * most/all of this. + */ + + #include "util/u_math.h" #include "util/u_memory.h" #include "pipe/p_defines.h" @@ -52,7 +76,7 @@ struct widepoint_stage { int psize_slot; - int point_coord_fs_input; /**< input for pointcoord (and fog) */ + int point_coord_fs_input; /**< input for pointcoord */ }; @@ -64,8 +88,6 @@ widepoint_stage( struct draw_stage *stage ) } - - /** * Set the vertex texcoords for sprite mode. * Coords may be left untouched or set to a right-side-up or upside-down @@ -89,10 +111,12 @@ static void set_texcoords(const struct widepoint_stage *wide, } if (wide->point_coord_fs_input >= 0) { - /* put gl_PointCoord into extra vertex output's zw components */ - uint k = wide->stage.draw->extra_vp_outputs.slot; - v->data[k][2] = tc[0]; - v->data[k][3] = tc[1]; + /* put gl_PointCoord into the extra vertex slot */ + uint slot = wide->stage.draw->extra_vp_outputs.slot; + v->data[slot][0] = tc[0]; + v->data[slot][1] = tc[1]; + v->data[slot][2] = 0.0F; + v->data[slot][3] = 1.0F; } } @@ -181,6 +205,16 @@ static void widepoint_point( struct draw_stage *stage, } +static int +find_pntc_input_attrib(struct draw_context *draw) +{ + /* Scan the fragment program's input decls to find the pointcoord + * attribute. The xy components will store the point coord. + */ + return 0; /* XXX fix this */ +} + + static void widepoint_first_point( struct draw_stage *stage, struct prim_header *header ) { @@ -219,8 +253,8 @@ static void widepoint_first_point( struct draw_stage *stage, } wide->num_texcoords = j; - /* find fragment shader PointCoord/Fog input */ - wide->point_coord_fs_input = 0; /* XXX fix this! */ + /* find fragment shader PointCoord input */ + wide->point_coord_fs_input = find_pntc_input_attrib(draw); /* setup extra vp output (point coord implemented as a texcoord) */ draw->extra_vp_outputs.semantic_name = TGSI_SEMANTIC_GENERIC; diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h index 81e4eae401..41fcb16a0a 100644 --- a/src/gallium/auxiliary/draw/draw_private.h +++ b/src/gallium/auxiliary/draw/draw_private.h @@ -44,7 +44,6 @@ #include "pipe/p_state.h" #include "pipe/p_defines.h" -#include "tgsi/tgsi_exec.h" #include "tgsi/tgsi_scan.h" @@ -55,6 +54,8 @@ struct draw_vertex_shader; struct draw_context; struct draw_stage; struct vbuf_render; +struct tgsi_exec_machine; +struct tgsi_sampler; /** @@ -185,7 +186,7 @@ struct draw_context uint position_output; /** TGSI program interpreter runtime state */ - struct tgsi_exec_machine machine; + struct tgsi_exec_machine *machine; uint num_samplers; struct tgsi_sampler **samplers; diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c index 9ea0cbe599..dbb5ac7182 100644 --- a/src/gallium/auxiliary/draw/draw_pt.c +++ b/src/gallium/auxiliary/draw/draw_pt.c @@ -36,6 +36,7 @@ #include "draw/draw_vs.h" #include "tgsi/tgsi_dump.h" #include "util/u_math.h" +#include "util/u_prim.h" static unsigned trim( unsigned count, unsigned first, unsigned incr ) { @@ -278,7 +279,7 @@ void draw_arrays(struct draw_context *draw, unsigned prim, unsigned start, unsigned count) { - unsigned reduced_prim = draw_pt_reduced_prim(prim); + unsigned reduced_prim = u_reduced_prim(prim); if (reduced_prim != draw->reduced_prim) { draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); draw->reduced_prim = reduced_prim; diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h index 8ef0ea8011..7a17a9fb6b 100644 --- a/src/gallium/auxiliary/draw/draw_pt.h +++ b/src/gallium/auxiliary/draw/draw_pt.h @@ -228,7 +228,6 @@ void draw_pt_post_vs_destroy( struct pt_post_vs *pvs ); * Utils: */ void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr); -unsigned draw_pt_reduced_prim(unsigned prim); #endif diff --git a/src/gallium/auxiliary/draw/draw_pt_decompose.h b/src/gallium/auxiliary/draw/draw_pt_decompose.h index 3fb0695687..4ca5b52020 100644 --- a/src/gallium/auxiliary/draw/draw_pt_decompose.h +++ b/src/gallium/auxiliary/draw/draw_pt_decompose.h @@ -47,10 +47,19 @@ static void FUNC( ARGS, case PIPE_PRIM_TRIANGLES: for (i = 0; i+2 < count; i += 3) { - TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, - (i + 0), - (i + 1), - (i + 2 )); + if (flatfirst) { + /* put provoking vertex in last pos for clipper */ + TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + (i + 1), + (i + 2), + (i + 0 )); + } + else { + TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, + (i + 0), + (i + 1), + (i + 2 )); + } } break; @@ -58,9 +67,9 @@ static void FUNC( ARGS, if (flatfirst) { for (i = 0; i+2 < count; i++) { TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, - (i + 0), (i + 1 + (i&1)), - (i + 2 - (i&1))); + (i + 2 - (i&1)), + (i + 0) ); } } else { @@ -78,9 +87,9 @@ static void FUNC( ARGS, if (flatfirst) { for (i = 0; i+2 < count; i++) { TRIANGLE( DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL, - (i + 1), (i + 2), - (0 )); + 0, + (i + 1) ); } } else { @@ -96,20 +105,40 @@ static void FUNC( ARGS, case PIPE_PRIM_QUADS: - for (i = 0; i+3 < count; i += 4) { - QUAD( (i + 0), - (i + 1), - (i + 2), - (i + 3)); + if (flatfirst) { + for (i = 0; i+3 < count; i += 4) { + QUAD( (i + 1), + (i + 2), + (i + 3), + (i + 0) ); + } + } + else { + for (i = 0; i+3 < count; i += 4) { + QUAD( (i + 0), + (i + 1), + (i + 2), + (i + 3)); + } } break; case PIPE_PRIM_QUAD_STRIP: - for (i = 0; i+3 < count; i += 2) { - QUAD( (i + 2), - (i + 0), - (i + 1), - (i + 3)); + if (flatfirst) { + for (i = 0; i+3 < count; i += 2) { + QUAD( (i + 1), + (i + 3), + (i + 2), + (i + 0) ); + } + } + else { + for (i = 0; i+3 < count; i += 2) { + QUAD( (i + 2), + (i + 0), + (i + 1), + (i + 3)); + } } break; diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c index 6b7d02a19b..e7fe6b3b76 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c @@ -130,6 +130,10 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle, unsigned output_format; switch (vinfo->attrib[i].emit) { + case EMIT_4UB: + output_format = PIPE_FORMAT_R8G8B8A8_UNORM; + emit_sz = 4 * sizeof(unsigned char); + break; case EMIT_4F: output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; emit_sz = 4 * sizeof(float); @@ -153,6 +157,8 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle, output_format = PIPE_FORMAT_R32_FLOAT; emit_sz = 1 * sizeof(float); break; + case EMIT_OMIT: + continue; default: assert(0); output_format = PIPE_FORMAT_NONE; diff --git a/src/gallium/auxiliary/draw/draw_pt_util.c b/src/gallium/auxiliary/draw/draw_pt_util.c index 3bc7939c55..b61fa29143 100644 --- a/src/gallium/auxiliary/draw/draw_pt_util.c +++ b/src/gallium/auxiliary/draw/draw_pt_util.c @@ -75,28 +75,3 @@ void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr) break; } } - - -unsigned draw_pt_reduced_prim(unsigned 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_POLYGON: - case PIPE_PRIM_QUADS: - case PIPE_PRIM_QUAD_STRIP: - return PIPE_PRIM_TRIANGLES; - default: - assert(0); - return PIPE_PRIM_POINTS; - } -} - - diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache.c b/src/gallium/auxiliary/draw/draw_pt_vcache.c index 5d268a2226..1a0527be63 100644 --- a/src/gallium/auxiliary/draw/draw_pt_vcache.c +++ b/src/gallium/auxiliary/draw/draw_pt_vcache.c @@ -31,6 +31,7 @@ */ #include "util/u_memory.h" +#include "util/u_prim.h" #include "draw/draw_context.h" #include "draw/draw_private.h" #include "draw/draw_pt.h" @@ -193,16 +194,30 @@ vcache_ef_quad( struct vcache_frontend *vcache, unsigned i2, unsigned i3 ) { - vcache_triangle_flags( vcache, - ( DRAW_PIPE_RESET_STIPPLE | - DRAW_PIPE_EDGE_FLAG_0 | - DRAW_PIPE_EDGE_FLAG_2 ), - i0, i1, i3 ); - - vcache_triangle_flags( vcache, - ( DRAW_PIPE_EDGE_FLAG_0 | - DRAW_PIPE_EDGE_FLAG_1 ), - i1, i2, i3 ); + if (vcache->draw->rasterizer->flatshade_first) { + vcache_triangle_flags( vcache, + ( DRAW_PIPE_RESET_STIPPLE | + DRAW_PIPE_EDGE_FLAG_0 | + DRAW_PIPE_EDGE_FLAG_1 ), + i0, i1, i2 ); + + vcache_triangle_flags( vcache, + ( DRAW_PIPE_EDGE_FLAG_2 | + DRAW_PIPE_EDGE_FLAG_1 ), + i0, i2, i3 ); + } + else { + vcache_triangle_flags( vcache, + ( DRAW_PIPE_RESET_STIPPLE | + DRAW_PIPE_EDGE_FLAG_0 | + DRAW_PIPE_EDGE_FLAG_2 ), + i0, i1, i3 ); + + vcache_triangle_flags( vcache, + ( DRAW_PIPE_EDGE_FLAG_0 | + DRAW_PIPE_EDGE_FLAG_1 ), + i1, i2, i3 ); + } } /* At least for now, we're back to using a template include file for @@ -453,7 +468,7 @@ vcache_prepare( struct draw_pt_front_end *frontend, } vcache->input_prim = prim; - vcache->output_prim = draw_pt_reduced_prim(prim); + vcache->output_prim = u_reduced_prim(prim); vcache->middle = middle; vcache->opt = opt; diff --git a/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h b/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h index ec05bbeab4..62822a3d56 100644 --- a/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h +++ b/src/gallium/auxiliary/draw/draw_pt_vcache_tmp.h @@ -118,21 +118,39 @@ static void FUNC( struct draw_pt_front_end *frontend, case PIPE_PRIM_QUADS: for (i = 0; i+3 < count; i += 4) { - QUAD( vcache, - get_elt(elts, i + 0), - get_elt(elts, i + 1), - get_elt(elts, i + 2), - get_elt(elts, i + 3)); + if (flatfirst) { + QUAD( vcache, + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 2), + get_elt(elts, i + 3) ); + } + else { + QUAD( vcache, + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 2), + get_elt(elts, i + 3) ); + } } break; case PIPE_PRIM_QUAD_STRIP: for (i = 0; i+3 < count; i += 2) { - QUAD( vcache, - get_elt(elts, i + 2), - get_elt(elts, i + 0), - get_elt(elts, i + 1), - get_elt(elts, i + 3)); + if (flatfirst) { + QUAD( vcache, + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 3), + get_elt(elts, i + 2) ); + } + else { + QUAD( vcache, + get_elt(elts, i + 2), + get_elt(elts, i + 0), + get_elt(elts, i + 1), + get_elt(elts, i + 3) ); + } } break; @@ -144,19 +162,38 @@ static void FUNC( struct draw_pt_front_end *frontend, const ushort edge_first = DRAW_PIPE_EDGE_FLAG_2; const ushort edge_middle = DRAW_PIPE_EDGE_FLAG_0; const ushort edge_last = DRAW_PIPE_EDGE_FLAG_1; + ushort edge_next, edge_finish; - flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle; + if (flatfirst) { + flags = DRAW_PIPE_RESET_STIPPLE | edge_middle | edge_last; + edge_next = edge_last; + edge_finish = edge_first; + } + else { + flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle; + edge_next = edge_middle; + edge_finish = edge_last; + } - for (i = 0; i+2 < count; i++, flags = edge_middle) { + for (i = 0; i+2 < count; i++, flags = edge_next) { if (i + 3 == count) - flags |= edge_last; + flags |= edge_finish; - TRIANGLE( vcache, - flags, - get_elt(elts, i + 1), - get_elt(elts, i + 2), - get_elt(elts, 0)); + if (flatfirst) { + TRIANGLE( vcache, + flags, + get_elt(elts, 0), + get_elt(elts, i + 1), + get_elt(elts, i + 2) ); + } + else { + TRIANGLE( vcache, + flags, + get_elt(elts, i + 1), + get_elt(elts, i + 2), + get_elt(elts, 0)); + } } } break; diff --git a/src/gallium/auxiliary/draw/draw_vs.c b/src/gallium/auxiliary/draw/draw_vs.c index c057cd67fd..790e89ed82 100644 --- a/src/gallium/auxiliary/draw/draw_vs.c +++ b/src/gallium/auxiliary/draw/draw_vs.c @@ -43,6 +43,8 @@ #include "translate/translate.h" #include "translate/translate_cache.h" +#include "tgsi/tgsi_exec.h" + @@ -146,16 +148,8 @@ draw_delete_vertex_shader(struct draw_context *draw, boolean draw_vs_init( struct draw_context *draw ) { - tgsi_exec_machine_init(&draw->vs.machine); - - /* FIXME: give this machine thing a proper constructor: - */ - draw->vs.machine.Inputs = align_malloc(PIPE_MAX_ATTRIBS * sizeof(struct tgsi_exec_vector), 16); - if (!draw->vs.machine.Inputs) - return FALSE; - - draw->vs.machine.Outputs = align_malloc(PIPE_MAX_ATTRIBS * sizeof(struct tgsi_exec_vector), 16); - if (!draw->vs.machine.Outputs) + draw->vs.machine = tgsi_exec_machine_create(); + if (!draw->vs.machine) return FALSE; draw->vs.emit_cache = translate_cache_create(); @@ -178,12 +172,6 @@ draw_vs_init( struct draw_context *draw ) void draw_vs_destroy( struct draw_context *draw ) { - if (draw->vs.machine.Inputs) - align_free(draw->vs.machine.Inputs); - - if (draw->vs.machine.Outputs) - align_free(draw->vs.machine.Outputs); - if (draw->vs.fetch_cache) translate_cache_destroy(draw->vs.fetch_cache); @@ -196,8 +184,7 @@ draw_vs_destroy( struct draw_context *draw ) if (draw->vs.aligned_constant_storage) align_free((void*)draw->vs.aligned_constant_storage); - tgsi_exec_machine_free_data(&draw->vs.machine); - + tgsi_exec_machine_destroy(draw->vs.machine); } diff --git a/src/gallium/auxiliary/draw/draw_vs_aos.c b/src/gallium/auxiliary/draw/draw_vs_aos.c index 9e37a26c1e..62e04a65f3 100644 --- a/src/gallium/auxiliary/draw/draw_vs_aos.c +++ b/src/gallium/auxiliary/draw/draw_vs_aos.c @@ -1758,24 +1758,24 @@ emit_instruction( struct aos_compilation *cp, case TGSI_OPCODE_SUB: return emit_SUB(cp, inst); - case TGSI_OPCODE_LERP: + case TGSI_OPCODE_LRP: // return emit_LERP(cp, inst); return FALSE; - case TGSI_OPCODE_FRAC: + case TGSI_OPCODE_FRC: return emit_FRC(cp, inst); case TGSI_OPCODE_CLAMP: // return emit_CLAMP(cp, inst); return FALSE; - case TGSI_OPCODE_FLOOR: + case TGSI_OPCODE_FLR: return emit_FLR(cp, inst); case TGSI_OPCODE_ROUND: return emit_RND(cp, inst); - case TGSI_OPCODE_EXPBASE2: + case TGSI_OPCODE_EX2: #if FAST_MATH return emit_EXPBASE2(cp, inst); #elif 0 @@ -1787,13 +1787,13 @@ emit_instruction( struct aos_compilation *cp, return FALSE; #endif - case TGSI_OPCODE_LOGBASE2: + case TGSI_OPCODE_LG2: return emit_LG2(cp, inst); - case TGSI_OPCODE_POWER: + case TGSI_OPCODE_POW: return emit_POW(cp, inst); - case TGSI_OPCODE_CROSSPRODUCT: + case TGSI_OPCODE_XPD: return emit_XPD(cp, inst); case TGSI_OPCODE_ABS: @@ -1891,8 +1891,9 @@ static boolean note_immediate( struct aos_compilation *cp, unsigned pos = cp->num_immediates++; unsigned j; + assert( imm->Immediate.NrTokens <= 4 + 1 ); for (j = 0; j < imm->Immediate.NrTokens - 1; j++) { - cp->vaos->machine->immediate[pos][j] = imm->u.ImmediateFloat32[j].Float; + cp->vaos->machine->immediate[pos][j] = imm->u[j].Float; } return TRUE; diff --git a/src/gallium/auxiliary/draw/draw_vs_exec.c b/src/gallium/auxiliary/draw/draw_vs_exec.c index dbbc33fffa..41cc802613 100644 --- a/src/gallium/auxiliary/draw/draw_vs_exec.c +++ b/src/gallium/auxiliary/draw/draw_vs_exec.c @@ -41,6 +41,7 @@ #include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_scan.h" +#include "tgsi/tgsi_exec.h" struct exec_vertex_shader { @@ -114,6 +115,12 @@ vs_exec_run_linear( struct draw_vertex_shader *shader, #endif for (slot = 0; slot < shader->info.num_inputs; slot++) { +#if 0 + assert(!util_is_inf_or_nan(input[slot][0])); + assert(!util_is_inf_or_nan(input[slot][1])); + assert(!util_is_inf_or_nan(input[slot][2])); + assert(!util_is_inf_or_nan(input[slot][3])); +#endif machine->Inputs[slot].xyzw[0].f[j] = input[slot][0]; machine->Inputs[slot].xyzw[1].f[j] = input[slot][1]; machine->Inputs[slot].xyzw[2].f[j] = input[slot][2]; @@ -195,7 +202,7 @@ draw_create_vs_exec(struct draw_context *draw, vs->base.run_linear = vs_exec_run_linear; vs->base.delete = vs_exec_delete; vs->base.create_varient = draw_vs_varient_generic; - vs->machine = &draw->vs.machine; + vs->machine = draw->vs.machine; return &vs->base; } diff --git a/src/gallium/auxiliary/draw/draw_vs_llvm.c b/src/gallium/auxiliary/draw/draw_vs_llvm.c index 727977bc3a..b3535c0e48 100644 --- a/src/gallium/auxiliary/draw/draw_vs_llvm.c +++ b/src/gallium/auxiliary/draw/draw_vs_llvm.c @@ -119,7 +119,7 @@ draw_create_vs_llvm(struct draw_context *draw, vs->base.create_varient = draw_vs_varient_generic; vs->base.run_linear = vs_llvm_run_linear; vs->base.delete = vs_llvm_delete; - vs->machine = &draw->vs.machine; + vs->machine = draw->vs.machine; { struct gallivm_ir *ir = gallivm_ir_new(GALLIVM_VS); diff --git a/src/gallium/auxiliary/draw/draw_vs_ppc.c b/src/gallium/auxiliary/draw/draw_vs_ppc.c index d35db57d57..ad184bd696 100644 --- a/src/gallium/auxiliary/draw/draw_vs_ppc.c +++ b/src/gallium/auxiliary/draw/draw_vs_ppc.c @@ -48,6 +48,7 @@ #include "rtasm/rtasm_ppc.h" #include "tgsi/tgsi_ppc.h" #include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_exec.h" diff --git a/src/gallium/auxiliary/draw/draw_vs_sse.c b/src/gallium/auxiliary/draw/draw_vs_sse.c index 77ba5152f9..702051387a 100644 --- a/src/gallium/auxiliary/draw/draw_vs_sse.c +++ b/src/gallium/auxiliary/draw/draw_vs_sse.c @@ -48,27 +48,16 @@ #include "rtasm/rtasm_x86sse.h" #include "tgsi/tgsi_sse2.h" #include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_exec.h" #define SSE_MAX_VERTICES 4 -typedef void (PIPE_CDECL *codegen_function) ( - const struct tgsi_exec_vector *input, /* 1 */ - struct tgsi_exec_vector *output, /* 2 */ - float (*constant)[4], /* 3 */ - struct tgsi_exec_vector *temporary, /* 4 */ - float (*immediates)[4], /* 5 */ - const float (*aos_input)[4], /* 6 */ - uint num_inputs, /* 7 */ - uint input_stride, /* 8 */ - float (*aos_output)[4], /* 9 */ - uint num_outputs, /* 10 */ - uint output_stride ); /* 11 */ struct draw_sse_vertex_shader { struct draw_vertex_shader base; struct x86_function sse2_program; - codegen_function func; + tgsi_sse2_vs_func func; struct tgsi_exec_machine *machine; }; @@ -78,6 +67,10 @@ static void vs_sse_prepare( struct draw_vertex_shader *base, struct draw_context *draw ) { + struct draw_sse_vertex_shader *shader = (struct draw_sse_vertex_shader *)base; + struct tgsi_exec_machine *machine = shader->machine; + + machine->Samplers = draw->vs.samplers; } @@ -118,11 +111,9 @@ vs_sse_run_linear( struct draw_vertex_shader *base, /* run compiled shader */ - shader->func(machine->Inputs, - machine->Outputs, - (float (*)[4])constants, - machine->Temps, - (float (*)[4])shader->base.immediates, + shader->func(machine, + constants, + shader->base.immediates, input, base->info.num_inputs, input_stride, @@ -184,7 +175,7 @@ draw_create_vs_sse(struct draw_context *draw, vs->base.immediates = align_malloc(TGSI_EXEC_NUM_IMMEDIATES * 4 * sizeof(float), 16); - vs->machine = &draw->vs.machine; + vs->machine = draw->vs.machine; x86_init_func( &vs->sse2_program ); @@ -194,7 +185,7 @@ draw_create_vs_sse(struct draw_context *draw, TRUE )) goto fail; - vs->func = (codegen_function) x86_get_func( &vs->sse2_program ); + vs->func = (tgsi_sse2_vs_func) x86_get_func( &vs->sse2_program ); if (!vs->func) { goto fail; } diff --git a/src/gallium/auxiliary/gallivm/instructionssoa.cpp b/src/gallium/auxiliary/gallivm/instructionssoa.cpp index 925e948763..721b7d2d83 100644 --- a/src/gallium/auxiliary/gallivm/instructionssoa.cpp +++ b/src/gallium/auxiliary/gallivm/instructionssoa.cpp @@ -24,6 +24,8 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * **************************************************************************/ + +#include <cstdio> #include "instructionssoa.h" #include "storagesoa.h" @@ -126,7 +128,7 @@ void InstructionsSoa::createFunctionMap() m_functionsMap[TGSI_OPCODE_DP4] = "dp4"; m_functionsMap[TGSI_OPCODE_MIN] = "min"; m_functionsMap[TGSI_OPCODE_MAX] = "max"; - m_functionsMap[TGSI_OPCODE_POWER] = "pow"; + m_functionsMap[TGSI_OPCODE_POW] = "pow"; m_functionsMap[TGSI_OPCODE_LIT] = "lit"; m_functionsMap[TGSI_OPCODE_RSQ] = "rsq"; m_functionsMap[TGSI_OPCODE_SLT] = "slt"; @@ -309,7 +311,7 @@ std::vector<llvm::Value*> InstructionsSoa::mul(const std::vector<llvm::Value*> i std::vector<llvm::Value*> InstructionsSoa::pow(const std::vector<llvm::Value*> in1, const std::vector<llvm::Value*> in2) { - llvm::Function *func = function(TGSI_OPCODE_POWER); + llvm::Function *func = function(TGSI_OPCODE_POW); return callBuiltin(func, in1, in2); } diff --git a/src/gallium/auxiliary/gallivm/tgsitollvm.cpp b/src/gallium/auxiliary/gallivm/tgsitollvm.cpp index 5b08200d14..bf84401e11 100644 --- a/src/gallium/auxiliary/gallivm/tgsitollvm.cpp +++ b/src/gallium/auxiliary/gallivm/tgsitollvm.cpp @@ -160,10 +160,11 @@ translate_immediate(Storage *storage, { float vec[4]; int i; + assert( imm->Immediate.NrTokens <= 4 + 1 ); for (i = 0; i < imm->Immediate.NrTokens - 1; ++i) { switch (imm->Immediate.DataType) { case TGSI_IMM_FLOAT32: - vec[i] = imm->u.ImmediateFloat32[i].Float; + vec[i] = imm->u[i].Float; break; default: assert(0); @@ -179,10 +180,11 @@ translate_immediateir(StorageSoa *storage, { float vec[4]; int i; + assert( imm->Immediate.NrTokens <= 4 + 1 ); for (i = 0; i < imm->Immediate.NrTokens - 1; ++i) { switch (imm->Immediate.DataType) { case TGSI_IMM_FLOAT32: - vec[i] = imm->u.ImmediateFloat32[i].Float; + vec[i] = imm->u[i].Float; break; default: assert(0); @@ -336,7 +338,7 @@ translate_instruction(llvm::Module *module, out = instr->sub(inputs[0], inputs[1]); } break; - case TGSI_OPCODE_LERP: { + case TGSI_OPCODE_LRP: { out = instr->lerp(inputs[0], inputs[1], inputs[2]); } break; @@ -348,17 +350,11 @@ translate_instruction(llvm::Module *module, out = instr->cnd0(inputs[0], inputs[1], inputs[2]); } break; - case TGSI_OPCODE_DOT2ADD: { + case TGSI_OPCODE_DP2A: { out = instr->dot2add(inputs[0], inputs[1], inputs[2]); } break; - case TGSI_OPCODE_INDEX: - break; - case TGSI_OPCODE_NEGATE: { - out = instr->neg(inputs[0]); - } - break; - case TGSI_OPCODE_FRAC: { + case TGSI_OPCODE_FRC: { out = instr->frc(inputs[0]); } break; @@ -366,30 +362,28 @@ translate_instruction(llvm::Module *module, out = instr->clamp(inputs[0]); } break; - case TGSI_OPCODE_FLOOR: { + case TGSI_OPCODE_FLR: { out = instr->floor(inputs[0]); } break; case TGSI_OPCODE_ROUND: break; - case TGSI_OPCODE_EXPBASE2: { + case TGSI_OPCODE_EX2: { out = instr->ex2(inputs[0]); } break; - case TGSI_OPCODE_LOGBASE2: { + case TGSI_OPCODE_LG2: { out = instr->lg2(inputs[0]); } break; - case TGSI_OPCODE_POWER: { + case TGSI_OPCODE_POW: { out = instr->pow(inputs[0], inputs[1]); } break; - case TGSI_OPCODE_CROSSPRODUCT: { + case TGSI_OPCODE_XPD: { out = instr->cross(inputs[0], inputs[1]); } break; - case TGSI_OPCODE_MULTIPLYMATRIX: - break; case TGSI_OPCODE_ABS: { out = instr->abs(inputs[0]); } @@ -522,7 +516,7 @@ translate_instruction(llvm::Module *module, return; //just update the state } break; - case TGSI_OPCODE_LOOP: + case TGSI_OPCODE_BGNFOR: break; case TGSI_OPCODE_REP: break; @@ -538,7 +532,7 @@ translate_instruction(llvm::Module *module, return; //just update the state } break; - case TGSI_OPCODE_ENDLOOP: + case TGSI_OPCODE_ENDFOR: break; case TGSI_OPCODE_ENDREP: break; @@ -580,7 +574,7 @@ translate_instruction(llvm::Module *module, break; case TGSI_OPCODE_ENDPRIM: break; - case TGSI_OPCODE_BGNLOOP2: { + case TGSI_OPCODE_BGNLOOP: { instr->beginLoop(); storage->setCurrentBlock(instr->currentBlock()); return; @@ -593,7 +587,7 @@ translate_instruction(llvm::Module *module, return; } break; - case TGSI_OPCODE_ENDLOOP2: { + case TGSI_OPCODE_ENDLOOP: { instr->endLoop(); storage->setCurrentBlock(instr->currentBlock()); return; @@ -617,14 +611,6 @@ translate_instruction(llvm::Module *module, break; case TGSI_OPCODE_NOP: break; - case TGSI_OPCODE_M4X3: - break; - case TGSI_OPCODE_M3X4: - break; - case TGSI_OPCODE_M3X3: - break; - case TGSI_OPCODE_M3X2: - break; case TGSI_OPCODE_CALLNZ: break; case TGSI_OPCODE_IFC: @@ -778,44 +764,38 @@ translate_instructionir(llvm::Module *module, out = instr->sub(inputs[0], inputs[1]); } break; - case TGSI_OPCODE_LERP: { + case TGSI_OPCODE_LRP: { } break; case TGSI_OPCODE_CND: break; case TGSI_OPCODE_CND0: break; - case TGSI_OPCODE_DOT2ADD: + case TGSI_OPCODE_DP2A: break; - case TGSI_OPCODE_INDEX: - break; - case TGSI_OPCODE_NEGATE: - break; - case TGSI_OPCODE_FRAC: { + case TGSI_OPCODE_FRC: { } break; case TGSI_OPCODE_CLAMP: break; - case TGSI_OPCODE_FLOOR: { + case TGSI_OPCODE_FLR: { } break; case TGSI_OPCODE_ROUND: break; - case TGSI_OPCODE_EXPBASE2: { + case TGSI_OPCODE_EX2: { } break; - case TGSI_OPCODE_LOGBASE2: { + case TGSI_OPCODE_LG2: { } break; - case TGSI_OPCODE_POWER: { + case TGSI_OPCODE_POW: { out = instr->pow(inputs[0], inputs[1]); } break; - case TGSI_OPCODE_CROSSPRODUCT: { + case TGSI_OPCODE_XPD: { } break; - case TGSI_OPCODE_MULTIPLYMATRIX: - break; case TGSI_OPCODE_ABS: { out = instr->abs(inputs[0]); } @@ -910,7 +890,7 @@ translate_instructionir(llvm::Module *module, case TGSI_OPCODE_IF: { } break; - case TGSI_OPCODE_LOOP: + case TGSI_OPCODE_BGNFOR: break; case TGSI_OPCODE_REP: break; @@ -920,7 +900,7 @@ translate_instructionir(llvm::Module *module, case TGSI_OPCODE_ENDIF: { } break; - case TGSI_OPCODE_ENDLOOP: + case TGSI_OPCODE_ENDFOR: break; case TGSI_OPCODE_ENDREP: break; @@ -961,13 +941,13 @@ translate_instructionir(llvm::Module *module, break; case TGSI_OPCODE_ENDPRIM: break; - case TGSI_OPCODE_BGNLOOP2: { + case TGSI_OPCODE_BGNLOOP: { } break; case TGSI_OPCODE_BGNSUB: { } break; - case TGSI_OPCODE_ENDLOOP2: { + case TGSI_OPCODE_ENDLOOP: { } break; case TGSI_OPCODE_ENDSUB: { @@ -983,14 +963,6 @@ translate_instructionir(llvm::Module *module, break; case TGSI_OPCODE_NOP: break; - case TGSI_OPCODE_M4X3: - break; - case TGSI_OPCODE_M3X4: - break; - case TGSI_OPCODE_M3X3: - break; - case TGSI_OPCODE_M3X2: - break; case TGSI_OPCODE_NRM4: break; case TGSI_OPCODE_CALLNZ: diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c b/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c index 0760d60716..6bdce5fcb0 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer_malloc.c @@ -53,6 +53,8 @@ static INLINE struct malloc_buffer * malloc_buffer(struct pb_buffer *buf) { assert(buf); + if (!buf) + return NULL; assert(buf->vtbl == &malloc_buffer_vtbl); return (struct malloc_buffer *)buf; } diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_ondemand.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_ondemand.c index bc3093f620..cb32d25136 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_ondemand.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_ondemand.c @@ -74,6 +74,8 @@ static INLINE struct pb_ondemand_buffer * pb_ondemand_buffer(struct pb_buffer *buf) { assert(buf); + if (!buf) + return NULL; assert(buf->vtbl == &pb_ondemand_buffer_vtbl); return (struct pb_ondemand_buffer *)buf; } diff --git a/src/gallium/auxiliary/rbug/Makefile b/src/gallium/auxiliary/rbug/Makefile new file mode 100644 index 0000000000..cd12e8468f --- /dev/null +++ b/src/gallium/auxiliary/rbug/Makefile @@ -0,0 +1,14 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = rbug + +C_SOURCES = \ + rbug_connection.c \ + rbug_core.c \ + rbug_texture.c \ + rbug_context.c \ + rbug_shader.c \ + rbug_demarshal.c + +include ../../Makefile.template diff --git a/src/gallium/auxiliary/rbug/README b/src/gallium/auxiliary/rbug/README new file mode 100644 index 0000000000..33d76371de --- /dev/null +++ b/src/gallium/auxiliary/rbug/README @@ -0,0 +1,21 @@ + GALLIUM REMOTE DEBUGGING COMMON CODE + += About = + +This directory contains the common code for the Gallium 3D remote debugging +driver and clients. The code is two parts the connection managment code and +the (de)marsheller. + +The code currently uses tcp and ip4v for connections. + +Information about driver integration can be found in: + +src/gallium/drivers/trace/README + +for information about applications look in: + +progs/rbug/README + + +-- +Jakob Bornecrantz <jakob@vmware.com> diff --git a/src/gallium/auxiliary/rbug/SConscript b/src/gallium/auxiliary/rbug/SConscript new file mode 100644 index 0000000000..4a9afb45d3 --- /dev/null +++ b/src/gallium/auxiliary/rbug/SConscript @@ -0,0 +1,14 @@ +Import('*') + +rbug = env.ConvenienceLibrary( + target = 'rbug', + source = [ + 'rbug_core.c', + 'rbug_shader.c', + 'rbug_context.c', + 'rbug_texture.c', + 'rbug_demarshal.c', + 'rbug_connection.c', + ]) + +auxiliaries.insert(0, rbug) diff --git a/src/gallium/auxiliary/rbug/rbug.h b/src/gallium/auxiliary/rbug/rbug.h new file mode 100644 index 0000000000..259bfc6c79 --- /dev/null +++ b/src/gallium/auxiliary/rbug/rbug.h @@ -0,0 +1,33 @@ +/* + * 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 all for users the remote debugger protocol code. + */ + +#include "rbug/rbug_core.h" +#include "rbug/rbug_shader.h" +#include "rbug/rbug_context.h" +#include "rbug/rbug_texture.h" +#include "rbug/rbug_connection.h" diff --git a/src/gallium/auxiliary/rbug/rbug_connection.c b/src/gallium/auxiliary/rbug/rbug_connection.c new file mode 100644 index 0000000000..52acb700af --- /dev/null +++ b/src/gallium/auxiliary/rbug/rbug_connection.c @@ -0,0 +1,167 @@ +/* + * 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 "rbug/rbug.h" +#include "rbug/rbug_internal.h" + +#include "util/u_network.h" + +struct rbug_connection +{ + int socket; + uint32_t send_serial; + uint32_t recv_serial; + enum rbug_opcode opcode; +}; + +/** + * Create a rbug connection from a socket created with u_socket. + * + * Result: + * A new allocated connection using socket as communication path + */ +struct rbug_connection * +rbug_from_socket(int socket) +{ + struct rbug_connection *c = CALLOC_STRUCT(rbug_connection); + c->socket = socket; + return c; +} + +/** + * Free a connection, also closes socket. + */ +void +rbug_disconnect(struct rbug_connection *c) +{ + u_socket_close(c->socket); + FREE(c); +} + +/** + * Waits for a message to be fully received. + * Also returns the serial for the message, serial is not touched for replys. + * + * Result: + * demarshaled message on success, NULL on connection error + */ +struct rbug_header * +rbug_get_message(struct rbug_connection *c, uint32_t *serial) +{ + struct rbug_proto_header header; + struct rbug_header *out; + struct rbug_proto_header *data; + size_t length = 0; + size_t read = 0; + int ret; + + + ret = u_socket_peek(c->socket, &header, sizeof(header)); + if (ret <= 0) { + return NULL; + } + + length = (size_t)header.length * 4; + data = MALLOC(length); + if (!data) { + return NULL; + } + + do { + uint8_t *ptr = ((uint8_t*)data) + read; + ret = u_socket_recv(c->socket, ptr, length - read); + + if (ret <= 0) { + FREE(data); + return NULL; + } + + read += ret; + } while(read < length); + + out = rbug_demarshal(data); + if (!out) + FREE(data); + else if (serial) + *serial = c->recv_serial++; + else + c->recv_serial++; + + return out; +} + +/** + * Frees a message and associated data. + */ +void +rbug_free_header(struct rbug_header *header) +{ + if (!header) + return; + + FREE(header->__message); + FREE(header); +} + +/** + * Internal function used by rbug_send_* functions. + * + * Start sending a message. + */ +int +rbug_connection_send_start(struct rbug_connection *c, enum rbug_opcode opcode, uint32_t length) +{ + c->opcode = opcode; + return 0; +} + +/** + * Internal function used by rbug_send_* functions. + * + * Write data to the socket. + */ +int +rbug_connection_write(struct rbug_connection *c, void *to, uint32_t size) +{ + int ret = u_socket_send(c->socket, to, size); + return ret; +} + +/** + * Internal function used by rbug_send_* functions. + * + * Finish writeing data to the socket. + * Ups the send_serial and sets the serial argument if supplied. + */ +int rbug_connection_send_finish(struct rbug_connection *c, uint32_t *serial) +{ + if (c->opcode < 0) + return 0; + else if (serial) + *serial = c->send_serial++; + else + c->send_serial++; + + return 0; +} diff --git a/src/gallium/auxiliary/rbug/rbug_connection.h b/src/gallium/auxiliary/rbug/rbug_connection.h new file mode 100644 index 0000000000..1f2c9ff347 --- /dev/null +++ b/src/gallium/auxiliary/rbug/rbug_connection.h @@ -0,0 +1,45 @@ +/* + * 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. + */ + +/* + * This file contains the function defentions for connection see c file for + * more comments covering function use. + */ + +#ifndef _RBUG_CONNECTION_H_ +#define _RBUG_CONNECTION_H_ + +#include "rbug/rbug_proto.h" + +struct rbug_connection * rbug_from_socket(int socket); + +void rbug_disconnect(struct rbug_connection *c); + +struct rbug_header * rbug_get_message(struct rbug_connection *c, uint32_t *serial); + +void rbug_free_header(struct rbug_header *header); + +struct rbug_header * rbug_demarshal(struct rbug_proto_header *header); + +#endif diff --git a/src/gallium/auxiliary/rbug/rbug_context.c b/src/gallium/auxiliary/rbug/rbug_context.c new file mode 100644 index 0000000000..1832425658 --- /dev/null +++ b/src/gallium/auxiliary/rbug/rbug_context.c @@ -0,0 +1,759 @@ +/* + * 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. + */ + +/* + * This file holds the function implementation for one of the rbug extensions. + * Prototypes and declerations of functions and structs is in the same folder + * in the header file matching this file's name. + * + * The functions starting rbug_send_* encodes a call to the write format and + * sends that to the supplied connection, while functions starting with + * rbug_demarshal_* demarshal data in the wire protocol. + * + * Functions ending with _reply are replies to requests. + */ + +#include "rbug_internal.h" +#include "rbug/rbug_context.h" + +int rbug_send_context_list(struct rbug_connection *__con, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_LIST)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_CONTEXT_LIST, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_context_info(struct rbug_connection *__con, + rbug_context_t context, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(8); /* context */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_INFO)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(8, rbug_context_t, context); /* context */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_CONTEXT_INFO, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_context_draw_block(struct rbug_connection *__con, + rbug_context_t context, + rbug_block_t block, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(8); /* context */ + LEN(4); /* block */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_DRAW_BLOCK)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(8, rbug_context_t, context); /* context */ + WRITE(4, rbug_block_t, block); /* block */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_CONTEXT_DRAW_BLOCK, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_context_draw_step(struct rbug_connection *__con, + rbug_context_t context, + rbug_block_t step, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(8); /* context */ + LEN(4); /* step */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_DRAW_STEP)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(8, rbug_context_t, context); /* context */ + WRITE(4, rbug_block_t, step); /* step */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_CONTEXT_DRAW_STEP, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_context_draw_unblock(struct rbug_connection *__con, + rbug_context_t context, + rbug_block_t unblock, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(8); /* context */ + LEN(4); /* unblock */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_DRAW_UNBLOCK)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(8, rbug_context_t, context); /* context */ + WRITE(4, rbug_block_t, unblock); /* unblock */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_CONTEXT_DRAW_UNBLOCK, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_context_draw_rule(struct rbug_connection *__con, + rbug_context_t context, + rbug_shader_t vertex, + rbug_shader_t fragment, + rbug_texture_t texture, + rbug_texture_t surface, + rbug_block_t block, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(8); /* context */ + LEN(8); /* vertex */ + LEN(8); /* fragment */ + LEN(8); /* texture */ + LEN(8); /* surface */ + LEN(4); /* block */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_DRAW_RULE)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(8, rbug_context_t, context); /* context */ + WRITE(8, rbug_shader_t, vertex); /* vertex */ + WRITE(8, rbug_shader_t, fragment); /* fragment */ + WRITE(8, rbug_texture_t, texture); /* texture */ + WRITE(8, rbug_texture_t, surface); /* surface */ + WRITE(4, rbug_block_t, block); /* block */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_CONTEXT_DRAW_RULE, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_context_flush(struct rbug_connection *__con, + rbug_context_t context, + int32_t flags, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(8); /* context */ + LEN(4); /* flags */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_FLUSH)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(8, rbug_context_t, context); /* context */ + WRITE(4, int32_t, flags); /* flags */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_CONTEXT_FLUSH, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_context_list_reply(struct rbug_connection *__con, + uint32_t serial, + rbug_context_t *contexts, + uint32_t contexts_len, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(4); /* serial */ + LEN_ARRAY(8, contexts); /* contexts */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_LIST_REPLY)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(4, uint32_t, serial); /* serial */ + WRITE_ARRAY(8, rbug_context_t, contexts); /* contexts */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_CONTEXT_LIST_REPLY, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_context_info_reply(struct rbug_connection *__con, + uint32_t serial, + rbug_shader_t vertex, + rbug_shader_t fragment, + rbug_texture_t *texs, + uint32_t texs_len, + rbug_texture_t *cbufs, + uint32_t cbufs_len, + rbug_texture_t zsbuf, + rbug_block_t blocker, + rbug_block_t blocked, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(4); /* serial */ + LEN(8); /* vertex */ + LEN(8); /* fragment */ + LEN_ARRAY(8, texs); /* texs */ + LEN_ARRAY(8, cbufs); /* cbufs */ + LEN(8); /* zsbuf */ + LEN(4); /* blocker */ + LEN(4); /* blocked */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_INFO_REPLY)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(4, uint32_t, serial); /* serial */ + WRITE(8, rbug_shader_t, vertex); /* vertex */ + WRITE(8, rbug_shader_t, fragment); /* fragment */ + WRITE_ARRAY(8, rbug_texture_t, texs); /* texs */ + WRITE_ARRAY(8, rbug_texture_t, cbufs); /* cbufs */ + WRITE(8, rbug_texture_t, zsbuf); /* zsbuf */ + WRITE(4, rbug_block_t, blocker); /* blocker */ + WRITE(4, rbug_block_t, blocked); /* blocked */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_CONTEXT_INFO_REPLY, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_context_draw_blocked(struct rbug_connection *__con, + rbug_context_t context, + rbug_block_t block, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(8); /* context */ + LEN(4); /* block */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_CONTEXT_DRAW_BLOCKED)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(8, rbug_context_t, context); /* context */ + WRITE(4, rbug_block_t, block); /* block */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_CONTEXT_DRAW_BLOCKED, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +struct rbug_proto_context_list * rbug_demarshal_context_list(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_context_list *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_CONTEXT_LIST) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + + return ret; +} + +struct rbug_proto_context_info * rbug_demarshal_context_info(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_context_info *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_CONTEXT_INFO) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(8, rbug_context_t, context); /* context */ + + return ret; +} + +struct rbug_proto_context_draw_block * rbug_demarshal_context_draw_block(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_context_draw_block *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_CONTEXT_DRAW_BLOCK) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(8, rbug_context_t, context); /* context */ + READ(4, rbug_block_t, block); /* block */ + + return ret; +} + +struct rbug_proto_context_draw_step * rbug_demarshal_context_draw_step(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_context_draw_step *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_CONTEXT_DRAW_STEP) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(8, rbug_context_t, context); /* context */ + READ(4, rbug_block_t, step); /* step */ + + return ret; +} + +struct rbug_proto_context_draw_unblock * rbug_demarshal_context_draw_unblock(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_context_draw_unblock *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_CONTEXT_DRAW_UNBLOCK) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(8, rbug_context_t, context); /* context */ + READ(4, rbug_block_t, unblock); /* unblock */ + + return ret; +} + +struct rbug_proto_context_draw_rule * rbug_demarshal_context_draw_rule(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_context_draw_rule *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_CONTEXT_DRAW_RULE) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(8, rbug_context_t, context); /* context */ + READ(8, rbug_shader_t, vertex); /* vertex */ + READ(8, rbug_shader_t, fragment); /* fragment */ + READ(8, rbug_texture_t, texture); /* texture */ + READ(8, rbug_texture_t, surface); /* surface */ + READ(4, rbug_block_t, block); /* block */ + + return ret; +} + +struct rbug_proto_context_flush * rbug_demarshal_context_flush(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_context_flush *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_CONTEXT_FLUSH) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(8, rbug_context_t, context); /* context */ + READ(4, int32_t, flags); /* flags */ + + return ret; +} + +struct rbug_proto_context_list_reply * rbug_demarshal_context_list_reply(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_context_list_reply *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_CONTEXT_LIST_REPLY) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(4, uint32_t, serial); /* serial */ + READ_ARRAY(8, rbug_context_t, contexts); /* contexts */ + + return ret; +} + +struct rbug_proto_context_info_reply * rbug_demarshal_context_info_reply(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_context_info_reply *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_CONTEXT_INFO_REPLY) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(4, uint32_t, serial); /* serial */ + READ(8, rbug_shader_t, vertex); /* vertex */ + READ(8, rbug_shader_t, fragment); /* fragment */ + READ_ARRAY(8, rbug_texture_t, texs); /* texs */ + READ_ARRAY(8, rbug_texture_t, cbufs); /* cbufs */ + READ(8, rbug_texture_t, zsbuf); /* zsbuf */ + READ(4, rbug_block_t, blocker); /* blocker */ + READ(4, rbug_block_t, blocked); /* blocked */ + + return ret; +} + +struct rbug_proto_context_draw_blocked * rbug_demarshal_context_draw_blocked(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_context_draw_blocked *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_CONTEXT_DRAW_BLOCKED) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(8, rbug_context_t, context); /* context */ + READ(4, rbug_block_t, block); /* block */ + + return ret; +} diff --git a/src/gallium/auxiliary/rbug/rbug_context.h b/src/gallium/auxiliary/rbug/rbug_context.h new file mode 100644 index 0000000000..da61c2365b --- /dev/null +++ b/src/gallium/auxiliary/rbug/rbug_context.h @@ -0,0 +1,212 @@ +/* + * 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. + */ + +/* + * This file holds structs decelerations and function prototypes for one of + * the rbug extensions. Implementation of the functions is in the same folder + * in the c file matching this file's name. + * + * The structs what is returned from the demarshal functions. The functions + * starting rbug_send_* encodes a call to the write format and sends that to + * the supplied connection, while functions starting with rbug_demarshal_* + * demarshal data from the wire protocol. + * + * Structs and functions ending with _reply are replies to requests. + */ + +#ifndef _RBUG_PROTO_CONTEXT_H_ +#define _RBUG_PROTO_CONTEXT_H_ + +#include "rbug/rbug_proto.h" +#include "rbug/rbug_core.h" + +typedef enum +{ + RBUG_BLOCK_BEFORE = 1, + RBUG_BLOCK_AFTER = 2, + RBUG_BLOCK_RULE = 4, + RBUG_BLOCK_MASK = 7, +} rbug_block_t; + +struct rbug_proto_context_list +{ + struct rbug_header header; +}; + +struct rbug_proto_context_info +{ + struct rbug_header header; + rbug_context_t context; +}; + +struct rbug_proto_context_draw_block +{ + struct rbug_header header; + rbug_context_t context; + rbug_block_t block; +}; + +struct rbug_proto_context_draw_step +{ + struct rbug_header header; + rbug_context_t context; + rbug_block_t step; +}; + +struct rbug_proto_context_draw_unblock +{ + struct rbug_header header; + rbug_context_t context; + rbug_block_t unblock; +}; + +struct rbug_proto_context_draw_rule +{ + struct rbug_header header; + rbug_context_t context; + rbug_shader_t vertex; + rbug_shader_t fragment; + rbug_texture_t texture; + rbug_texture_t surface; + rbug_block_t block; +}; + +struct rbug_proto_context_flush +{ + struct rbug_header header; + rbug_context_t context; + int32_t flags; +}; + +struct rbug_proto_context_list_reply +{ + struct rbug_header header; + uint32_t serial; + rbug_context_t *contexts; + uint32_t contexts_len; +}; + +struct rbug_proto_context_info_reply +{ + struct rbug_header header; + uint32_t serial; + rbug_shader_t vertex; + rbug_shader_t fragment; + rbug_texture_t *texs; + uint32_t texs_len; + rbug_texture_t *cbufs; + uint32_t cbufs_len; + rbug_texture_t zsbuf; + rbug_block_t blocker; + rbug_block_t blocked; +}; + +struct rbug_proto_context_draw_blocked +{ + struct rbug_header header; + rbug_context_t context; + rbug_block_t block; +}; + +int rbug_send_context_list(struct rbug_connection *__con, + uint32_t *__serial); + +int rbug_send_context_info(struct rbug_connection *__con, + rbug_context_t context, + uint32_t *__serial); + +int rbug_send_context_draw_block(struct rbug_connection *__con, + rbug_context_t context, + rbug_block_t block, + uint32_t *__serial); + +int rbug_send_context_draw_step(struct rbug_connection *__con, + rbug_context_t context, + rbug_block_t step, + uint32_t *__serial); + +int rbug_send_context_draw_unblock(struct rbug_connection *__con, + rbug_context_t context, + rbug_block_t unblock, + uint32_t *__serial); + +int rbug_send_context_draw_rule(struct rbug_connection *__con, + rbug_context_t context, + rbug_shader_t vertex, + rbug_shader_t fragment, + rbug_texture_t texture, + rbug_texture_t surface, + rbug_block_t block, + uint32_t *__serial); + +int rbug_send_context_flush(struct rbug_connection *__con, + rbug_context_t context, + int32_t flags, + uint32_t *__serial); + +int rbug_send_context_list_reply(struct rbug_connection *__con, + uint32_t serial, + rbug_context_t *contexts, + uint32_t contexts_len, + uint32_t *__serial); + +int rbug_send_context_info_reply(struct rbug_connection *__con, + uint32_t serial, + rbug_shader_t vertex, + rbug_shader_t fragment, + rbug_texture_t *texs, + uint32_t texs_len, + rbug_texture_t *cbufs, + uint32_t cbufs_len, + rbug_texture_t zsbuf, + rbug_block_t blocker, + rbug_block_t blocked, + uint32_t *__serial); + +int rbug_send_context_draw_blocked(struct rbug_connection *__con, + rbug_context_t context, + rbug_block_t block, + uint32_t *__serial); + +struct rbug_proto_context_list * rbug_demarshal_context_list(struct rbug_proto_header *header); + +struct rbug_proto_context_info * rbug_demarshal_context_info(struct rbug_proto_header *header); + +struct rbug_proto_context_draw_block * rbug_demarshal_context_draw_block(struct rbug_proto_header *header); + +struct rbug_proto_context_draw_step * rbug_demarshal_context_draw_step(struct rbug_proto_header *header); + +struct rbug_proto_context_draw_unblock * rbug_demarshal_context_draw_unblock(struct rbug_proto_header *header); + +struct rbug_proto_context_draw_rule * rbug_demarshal_context_draw_rule(struct rbug_proto_header *header); + +struct rbug_proto_context_flush * rbug_demarshal_context_flush(struct rbug_proto_header *header); + +struct rbug_proto_context_list_reply * rbug_demarshal_context_list_reply(struct rbug_proto_header *header); + +struct rbug_proto_context_info_reply * rbug_demarshal_context_info_reply(struct rbug_proto_header *header); + +struct rbug_proto_context_draw_blocked * rbug_demarshal_context_draw_blocked(struct rbug_proto_header *header); + +#endif diff --git a/src/gallium/auxiliary/rbug/rbug_core.c b/src/gallium/auxiliary/rbug/rbug_core.c new file mode 100644 index 0000000000..876ae5a0ce --- /dev/null +++ b/src/gallium/auxiliary/rbug/rbug_core.c @@ -0,0 +1,359 @@ +/* + * 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. + */ + +/* + * This file holds the function implementation for one of the rbug extensions. + * Prototypes and declerations of functions and structs is in the same folder + * in the header file matching this file's name. + * + * The functions starting rbug_send_* encodes a call to the write format and + * sends that to the supplied connection, while functions starting with + * rbug_demarshal_* demarshal data in the wire protocol. + * + * Functions ending with _reply are replies to requests. + */ + +#include "rbug_internal.h" +#include "rbug/rbug_core.h" + +int rbug_send_noop(struct rbug_connection *__con, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_NOOP)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_NOOP, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_ping(struct rbug_connection *__con, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_PING)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_PING, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_error(struct rbug_connection *__con, + uint32_t error, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(4); /* error */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_ERROR)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(4, uint32_t, error); /* error */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_ERROR, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_ping_reply(struct rbug_connection *__con, + uint32_t serial, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(4); /* serial */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_PING_REPLY)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(4, uint32_t, serial); /* serial */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_PING_REPLY, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_error_reply(struct rbug_connection *__con, + uint32_t serial, + uint32_t error, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(4); /* serial */ + LEN(4); /* error */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_ERROR_REPLY)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(4, uint32_t, serial); /* serial */ + WRITE(4, uint32_t, error); /* error */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_ERROR_REPLY, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +struct rbug_proto_noop * rbug_demarshal_noop(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_noop *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_NOOP) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + + return ret; +} + +struct rbug_proto_ping * rbug_demarshal_ping(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_ping *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_PING) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + + return ret; +} + +struct rbug_proto_error * rbug_demarshal_error(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_error *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_ERROR) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(4, uint32_t, error); /* error */ + + return ret; +} + +struct rbug_proto_ping_reply * rbug_demarshal_ping_reply(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_ping_reply *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_PING_REPLY) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(4, uint32_t, serial); /* serial */ + + return ret; +} + +struct rbug_proto_error_reply * rbug_demarshal_error_reply(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_error_reply *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_ERROR_REPLY) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(4, uint32_t, serial); /* serial */ + READ(4, uint32_t, error); /* error */ + + return ret; +} diff --git a/src/gallium/auxiliary/rbug/rbug_core.h b/src/gallium/auxiliary/rbug/rbug_core.h new file mode 100644 index 0000000000..99a36a0163 --- /dev/null +++ b/src/gallium/auxiliary/rbug/rbug_core.h @@ -0,0 +1,105 @@ +/* + * 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. + */ + +/* + * This file holds structs decelerations and function prototypes for one of + * the rbug extensions. Implementation of the functions is in the same folder + * in the c file matching this file's name. + * + * The structs what is returned from the demarshal functions. The functions + * starting rbug_send_* encodes a call to the write format and sends that to + * the supplied connection, while functions starting with rbug_demarshal_* + * demarshal data from the wire protocol. + * + * Structs and functions ending with _reply are replies to requests. + */ + +#ifndef _RBUG_PROTO_CORE_H_ +#define _RBUG_PROTO_CORE_H_ + +#include "rbug/rbug_proto.h" + +typedef uint64_t rbug_shader_t; +typedef uint64_t rbug_context_t; +typedef uint64_t rbug_texture_t; + +struct rbug_proto_noop +{ + struct rbug_header header; +}; + +struct rbug_proto_ping +{ + struct rbug_header header; +}; + +struct rbug_proto_error +{ + struct rbug_header header; + uint32_t error; +}; + +struct rbug_proto_ping_reply +{ + struct rbug_header header; + uint32_t serial; +}; + +struct rbug_proto_error_reply +{ + struct rbug_header header; + uint32_t serial; + uint32_t error; +}; + +int rbug_send_noop(struct rbug_connection *__con, + uint32_t *__serial); + +int rbug_send_ping(struct rbug_connection *__con, + uint32_t *__serial); + +int rbug_send_error(struct rbug_connection *__con, + uint32_t error, + uint32_t *__serial); + +int rbug_send_ping_reply(struct rbug_connection *__con, + uint32_t serial, + uint32_t *__serial); + +int rbug_send_error_reply(struct rbug_connection *__con, + uint32_t serial, + uint32_t error, + uint32_t *__serial); + +struct rbug_proto_noop * rbug_demarshal_noop(struct rbug_proto_header *header); + +struct rbug_proto_ping * rbug_demarshal_ping(struct rbug_proto_header *header); + +struct rbug_proto_error * rbug_demarshal_error(struct rbug_proto_header *header); + +struct rbug_proto_ping_reply * rbug_demarshal_ping_reply(struct rbug_proto_header *header); + +struct rbug_proto_error_reply * rbug_demarshal_error_reply(struct rbug_proto_header *header); + +#endif diff --git a/src/gallium/auxiliary/rbug/rbug_demarshal.c b/src/gallium/auxiliary/rbug/rbug_demarshal.c new file mode 100644 index 0000000000..47390fbcee --- /dev/null +++ b/src/gallium/auxiliary/rbug/rbug_demarshal.c @@ -0,0 +1,93 @@ +/* + * 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 "rbug.h" + +/** + * Small function that looks at the proto_header and selects the correct + * demarshal functions and return the result. + */ +struct rbug_header * rbug_demarshal(struct rbug_proto_header *header) +{ + switch(header->opcode) { + case RBUG_OP_NOOP: + return (struct rbug_header *)rbug_demarshal_noop(header); + case RBUG_OP_PING: + return (struct rbug_header *)rbug_demarshal_ping(header); + case RBUG_OP_ERROR: + return (struct rbug_header *)rbug_demarshal_error(header); + case RBUG_OP_PING_REPLY: + return (struct rbug_header *)rbug_demarshal_ping_reply(header); + case RBUG_OP_ERROR_REPLY: + return (struct rbug_header *)rbug_demarshal_error_reply(header); + case RBUG_OP_TEXTURE_LIST: + return (struct rbug_header *)rbug_demarshal_texture_list(header); + case RBUG_OP_TEXTURE_INFO: + return (struct rbug_header *)rbug_demarshal_texture_info(header); + case RBUG_OP_TEXTURE_WRITE: + return (struct rbug_header *)rbug_demarshal_texture_write(header); + case RBUG_OP_TEXTURE_READ: + return (struct rbug_header *)rbug_demarshal_texture_read(header); + case RBUG_OP_TEXTURE_LIST_REPLY: + return (struct rbug_header *)rbug_demarshal_texture_list_reply(header); + case RBUG_OP_TEXTURE_INFO_REPLY: + return (struct rbug_header *)rbug_demarshal_texture_info_reply(header); + case RBUG_OP_TEXTURE_READ_REPLY: + return (struct rbug_header *)rbug_demarshal_texture_read_reply(header); + case RBUG_OP_CONTEXT_LIST: + return (struct rbug_header *)rbug_demarshal_context_list(header); + case RBUG_OP_CONTEXT_INFO: + return (struct rbug_header *)rbug_demarshal_context_info(header); + case RBUG_OP_CONTEXT_DRAW_BLOCK: + return (struct rbug_header *)rbug_demarshal_context_draw_block(header); + case RBUG_OP_CONTEXT_DRAW_STEP: + return (struct rbug_header *)rbug_demarshal_context_draw_step(header); + case RBUG_OP_CONTEXT_DRAW_UNBLOCK: + return (struct rbug_header *)rbug_demarshal_context_draw_unblock(header); + case RBUG_OP_CONTEXT_DRAW_RULE: + return (struct rbug_header *)rbug_demarshal_context_draw_rule(header); + case RBUG_OP_CONTEXT_FLUSH: + return (struct rbug_header *)rbug_demarshal_context_flush(header); + case RBUG_OP_CONTEXT_LIST_REPLY: + return (struct rbug_header *)rbug_demarshal_context_list_reply(header); + case RBUG_OP_CONTEXT_INFO_REPLY: + return (struct rbug_header *)rbug_demarshal_context_info_reply(header); + case RBUG_OP_CONTEXT_DRAW_BLOCKED: + return (struct rbug_header *)rbug_demarshal_context_draw_blocked(header); + case RBUG_OP_SHADER_LIST: + return (struct rbug_header *)rbug_demarshal_shader_list(header); + case RBUG_OP_SHADER_INFO: + return (struct rbug_header *)rbug_demarshal_shader_info(header); + case RBUG_OP_SHADER_DISABLE: + return (struct rbug_header *)rbug_demarshal_shader_disable(header); + case RBUG_OP_SHADER_REPLACE: + return (struct rbug_header *)rbug_demarshal_shader_replace(header); + case RBUG_OP_SHADER_LIST_REPLY: + return (struct rbug_header *)rbug_demarshal_shader_list_reply(header); + case RBUG_OP_SHADER_INFO_REPLY: + return (struct rbug_header *)rbug_demarshal_shader_info_reply(header); + default: + return NULL; + } +} diff --git a/src/gallium/auxiliary/rbug/rbug_internal.h b/src/gallium/auxiliary/rbug/rbug_internal.h new file mode 100644 index 0000000000..4aba1a810f --- /dev/null +++ b/src/gallium/auxiliary/rbug/rbug_internal.h @@ -0,0 +1,100 @@ +/* + * 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. + */ + +/* + * This file is internal to the rbug protocol code, and contains asorted + * features needed by the code. + */ + +#ifndef _RBUG_INTERNAL_H_ +#define _RBUG_INTERNAL_H_ + +#include "rbug/rbug_proto.h" + +#include "util/u_memory.h" +#include "util/u_debug.h" +#include <errno.h> + +int rbug_connection_send_start(struct rbug_connection *con, enum rbug_opcode opcode, uint32_t length); +int rbug_connection_write(struct rbug_connection *con, void *data, uint32_t size); +int rbug_connection_send_finish(struct rbug_connection *con, uint32_t *c); + +/** + * Only works with multiples of 2 + */ +#define PAD(from, to) \ +do { \ + from = (from + to - 1) & ~(to - 1); \ +} while(0) + +#define LEN(size) \ +do { \ + PAD(__len, size); \ + __len += size; \ +} while(0) + +#define LEN_ARRAY(size, name) \ +do { \ + LEN(4); \ + PAD(__len, size); \ + __len += size * name##_len; \ +} while(0) + +#define WRITE(size, type, name) \ +do { \ + PAD(__pos, size); \ + *((type *)(&__data[__pos])) = name; \ + __pos += size; \ +} while(0) + +#define WRITE_ARRAY(size, type, name) \ +do { \ + WRITE(4, uint32_t, name##_len); \ + PAD(__pos, size); \ + memcpy(&__data[__pos], name, size * name##_len); \ + __pos += size * name##_len; \ +} while(0) + +#define READ(size, type, name) \ +do { \ + PAD(pos, size); \ + pos += size; \ + if (pos > len) \ + break; \ + ret->name = *((type *)(&data[pos - size])); \ +} while(0) + +#define READ_ARRAY(size, type, name) \ +do { \ + READ(4, uint32_t, name##_len); \ + if (pos > len) \ + break; \ + PAD(pos, size); \ + pos += size * ret->name##_len; \ + if (pos > len) \ + break; \ + ret->name = (type *)&data[pos - size * ret->name##_len]; \ +} while(0) + +#endif diff --git a/src/gallium/auxiliary/rbug/rbug_proto.h b/src/gallium/auxiliary/rbug/rbug_proto.h new file mode 100644 index 0000000000..d273be0166 --- /dev/null +++ b/src/gallium/auxiliary/rbug/rbug_proto.h @@ -0,0 +1,94 @@ +/* + * 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. + */ + +/* + * This file holds common definitions of the gallium remote debugging protocol. + */ + +#ifndef _RBUG_PROTO_H_ +#define _RBUG_PROTO_H_ + +#include "pipe/p_compiler.h" + +/** + * Uniqe indentifier for each command. + * + * Replys are designated by negative. + */ +enum rbug_opcode +{ + RBUG_OP_NOOP = 0, + RBUG_OP_PING = 1, + RBUG_OP_ERROR = 2, + RBUG_OP_PING_REPLY = -1, + RBUG_OP_ERROR_REPLY = -2, + RBUG_OP_TEXTURE_LIST = 256, + RBUG_OP_TEXTURE_INFO = 257, + RBUG_OP_TEXTURE_WRITE = 258, + RBUG_OP_TEXTURE_READ = 259, + RBUG_OP_TEXTURE_LIST_REPLY = -256, + RBUG_OP_TEXTURE_INFO_REPLY = -257, + RBUG_OP_TEXTURE_READ_REPLY = -259, + RBUG_OP_CONTEXT_LIST = 512, + RBUG_OP_CONTEXT_INFO = 513, + RBUG_OP_CONTEXT_DRAW_BLOCK = 514, + RBUG_OP_CONTEXT_DRAW_STEP = 515, + RBUG_OP_CONTEXT_DRAW_UNBLOCK = 516, + RBUG_OP_CONTEXT_DRAW_RULE = 518, + RBUG_OP_CONTEXT_FLUSH = 519, + RBUG_OP_CONTEXT_LIST_REPLY = -512, + RBUG_OP_CONTEXT_INFO_REPLY = -513, + RBUG_OP_CONTEXT_DRAW_BLOCKED = 517, + RBUG_OP_SHADER_LIST = 768, + RBUG_OP_SHADER_INFO = 769, + RBUG_OP_SHADER_DISABLE = 770, + RBUG_OP_SHADER_REPLACE = 771, + RBUG_OP_SHADER_LIST_REPLY = -768, + RBUG_OP_SHADER_INFO_REPLY = -769, +}; + +/** + * Header for demarshaled message. + */ +struct rbug_header +{ + enum rbug_opcode opcode; + void *__message; +}; + +/** + * Header for a message in wire format. + */ +struct rbug_proto_header +{ + int32_t opcode; + uint32_t length; +}; + +/** + * Forward declare connection here, as this file is included by all users. + */ +struct rbug_connection; + +#endif diff --git a/src/gallium/auxiliary/rbug/rbug_shader.c b/src/gallium/auxiliary/rbug/rbug_shader.c new file mode 100644 index 0000000000..fccd2f55ef --- /dev/null +++ b/src/gallium/auxiliary/rbug/rbug_shader.c @@ -0,0 +1,468 @@ +/* + * 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. + */ + +/* + * This file holds the function implementation for one of the rbug extensions. + * Prototypes and declerations of functions and structs is in the same folder + * in the header file matching this file's name. + * + * The functions starting rbug_send_* encodes a call to the write format and + * sends that to the supplied connection, while functions starting with + * rbug_demarshal_* demarshal data in the wire protocol. + * + * Functions ending with _reply are replies to requests. + */ + +#include "rbug_internal.h" +#include "rbug/rbug_shader.h" + +int rbug_send_shader_list(struct rbug_connection *__con, + rbug_context_t context, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(8); /* context */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_SHADER_LIST)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(8, rbug_context_t, context); /* context */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_SHADER_LIST, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_shader_info(struct rbug_connection *__con, + rbug_context_t context, + rbug_shader_t shader, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(8); /* context */ + LEN(8); /* shader */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_SHADER_INFO)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(8, rbug_context_t, context); /* context */ + WRITE(8, rbug_shader_t, shader); /* shader */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_SHADER_INFO, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_shader_disable(struct rbug_connection *__con, + rbug_context_t context, + rbug_shader_t shader, + uint8_t disable, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(8); /* context */ + LEN(8); /* shader */ + LEN(1); /* disable */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_SHADER_DISABLE)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(8, rbug_context_t, context); /* context */ + WRITE(8, rbug_shader_t, shader); /* shader */ + WRITE(1, uint8_t, disable); /* disable */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_SHADER_DISABLE, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_shader_replace(struct rbug_connection *__con, + rbug_context_t context, + rbug_shader_t shader, + uint32_t *tokens, + uint32_t tokens_len, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(8); /* context */ + LEN(8); /* shader */ + LEN_ARRAY(4, tokens); /* tokens */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_SHADER_REPLACE)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(8, rbug_context_t, context); /* context */ + WRITE(8, rbug_shader_t, shader); /* shader */ + WRITE_ARRAY(4, uint32_t, tokens); /* tokens */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_SHADER_REPLACE, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_shader_list_reply(struct rbug_connection *__con, + uint32_t serial, + rbug_shader_t *shaders, + uint32_t shaders_len, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(4); /* serial */ + LEN_ARRAY(8, shaders); /* shaders */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_SHADER_LIST_REPLY)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(4, uint32_t, serial); /* serial */ + WRITE_ARRAY(8, rbug_shader_t, shaders); /* shaders */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_SHADER_LIST_REPLY, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_shader_info_reply(struct rbug_connection *__con, + uint32_t serial, + uint32_t *original, + uint32_t original_len, + uint32_t *replaced, + uint32_t replaced_len, + uint8_t disabled, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(4); /* serial */ + LEN_ARRAY(4, original); /* original */ + LEN_ARRAY(4, replaced); /* replaced */ + LEN(1); /* disabled */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_SHADER_INFO_REPLY)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(4, uint32_t, serial); /* serial */ + WRITE_ARRAY(4, uint32_t, original); /* original */ + WRITE_ARRAY(4, uint32_t, replaced); /* replaced */ + WRITE(1, uint8_t, disabled); /* disabled */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_SHADER_INFO_REPLY, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +struct rbug_proto_shader_list * rbug_demarshal_shader_list(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_shader_list *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_SHADER_LIST) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(8, rbug_context_t, context); /* context */ + + return ret; +} + +struct rbug_proto_shader_info * rbug_demarshal_shader_info(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_shader_info *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_SHADER_INFO) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(8, rbug_context_t, context); /* context */ + READ(8, rbug_shader_t, shader); /* shader */ + + return ret; +} + +struct rbug_proto_shader_disable * rbug_demarshal_shader_disable(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_shader_disable *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_SHADER_DISABLE) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(8, rbug_context_t, context); /* context */ + READ(8, rbug_shader_t, shader); /* shader */ + READ(1, uint8_t, disable); /* disable */ + + return ret; +} + +struct rbug_proto_shader_replace * rbug_demarshal_shader_replace(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_shader_replace *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_SHADER_REPLACE) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(8, rbug_context_t, context); /* context */ + READ(8, rbug_shader_t, shader); /* shader */ + READ_ARRAY(4, uint32_t, tokens); /* tokens */ + + return ret; +} + +struct rbug_proto_shader_list_reply * rbug_demarshal_shader_list_reply(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_shader_list_reply *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_SHADER_LIST_REPLY) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(4, uint32_t, serial); /* serial */ + READ_ARRAY(8, rbug_shader_t, shaders); /* shaders */ + + return ret; +} + +struct rbug_proto_shader_info_reply * rbug_demarshal_shader_info_reply(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_shader_info_reply *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_SHADER_INFO_REPLY) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(4, uint32_t, serial); /* serial */ + READ_ARRAY(4, uint32_t, original); /* original */ + READ_ARRAY(4, uint32_t, replaced); /* replaced */ + READ(1, uint8_t, disabled); /* disabled */ + + return ret; +} diff --git a/src/gallium/auxiliary/rbug/rbug_shader.h b/src/gallium/auxiliary/rbug/rbug_shader.h new file mode 100644 index 0000000000..b5d886781d --- /dev/null +++ b/src/gallium/auxiliary/rbug/rbug_shader.h @@ -0,0 +1,142 @@ +/* + * 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. + */ + +/* + * This file holds structs decelerations and function prototypes for one of + * the rbug extensions. Implementation of the functions is in the same folder + * in the c file matching this file's name. + * + * The structs what is returned from the demarshal functions. The functions + * starting rbug_send_* encodes a call to the write format and sends that to + * the supplied connection, while functions starting with rbug_demarshal_* + * demarshal data from the wire protocol. + * + * Structs and functions ending with _reply are replies to requests. + */ + +#ifndef _RBUG_PROTO_SHADER_H_ +#define _RBUG_PROTO_SHADER_H_ + +#include "rbug/rbug_proto.h" +#include "rbug/rbug_core.h" + +struct rbug_proto_shader_list +{ + struct rbug_header header; + rbug_context_t context; +}; + +struct rbug_proto_shader_info +{ + struct rbug_header header; + rbug_context_t context; + rbug_shader_t shader; +}; + +struct rbug_proto_shader_disable +{ + struct rbug_header header; + rbug_context_t context; + rbug_shader_t shader; + uint8_t disable; +}; + +struct rbug_proto_shader_replace +{ + struct rbug_header header; + rbug_context_t context; + rbug_shader_t shader; + uint32_t *tokens; + uint32_t tokens_len; +}; + +struct rbug_proto_shader_list_reply +{ + struct rbug_header header; + uint32_t serial; + rbug_shader_t *shaders; + uint32_t shaders_len; +}; + +struct rbug_proto_shader_info_reply +{ + struct rbug_header header; + uint32_t serial; + uint32_t *original; + uint32_t original_len; + uint32_t *replaced; + uint32_t replaced_len; + uint8_t disabled; +}; + +int rbug_send_shader_list(struct rbug_connection *__con, + rbug_context_t context, + uint32_t *__serial); + +int rbug_send_shader_info(struct rbug_connection *__con, + rbug_context_t context, + rbug_shader_t shader, + uint32_t *__serial); + +int rbug_send_shader_disable(struct rbug_connection *__con, + rbug_context_t context, + rbug_shader_t shader, + uint8_t disable, + uint32_t *__serial); + +int rbug_send_shader_replace(struct rbug_connection *__con, + rbug_context_t context, + rbug_shader_t shader, + uint32_t *tokens, + uint32_t tokens_len, + uint32_t *__serial); + +int rbug_send_shader_list_reply(struct rbug_connection *__con, + uint32_t serial, + rbug_shader_t *shaders, + uint32_t shaders_len, + uint32_t *__serial); + +int rbug_send_shader_info_reply(struct rbug_connection *__con, + uint32_t serial, + uint32_t *original, + uint32_t original_len, + uint32_t *replaced, + uint32_t replaced_len, + uint8_t disabled, + uint32_t *__serial); + +struct rbug_proto_shader_list * rbug_demarshal_shader_list(struct rbug_proto_header *header); + +struct rbug_proto_shader_info * rbug_demarshal_shader_info(struct rbug_proto_header *header); + +struct rbug_proto_shader_disable * rbug_demarshal_shader_disable(struct rbug_proto_header *header); + +struct rbug_proto_shader_replace * rbug_demarshal_shader_replace(struct rbug_proto_header *header); + +struct rbug_proto_shader_list_reply * rbug_demarshal_shader_list_reply(struct rbug_proto_header *header); + +struct rbug_proto_shader_info_reply * rbug_demarshal_shader_info_reply(struct rbug_proto_header *header); + +#endif diff --git a/src/gallium/auxiliary/rbug/rbug_texture.c b/src/gallium/auxiliary/rbug/rbug_texture.c new file mode 100644 index 0000000000..5a918fe6bc --- /dev/null +++ b/src/gallium/auxiliary/rbug/rbug_texture.c @@ -0,0 +1,631 @@ +/* + * 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. + */ + +/* + * This file holds the function implementation for one of the rbug extensions. + * Prototypes and declerations of functions and structs is in the same folder + * in the header file matching this file's name. + * + * The functions starting rbug_send_* encodes a call to the write format and + * sends that to the supplied connection, while functions starting with + * rbug_demarshal_* demarshal data in the wire protocol. + * + * Functions ending with _reply are replies to requests. + */ + +#include "rbug_internal.h" +#include "rbug/rbug_texture.h" + +int rbug_send_texture_list(struct rbug_connection *__con, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_LIST)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_TEXTURE_LIST, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_texture_info(struct rbug_connection *__con, + rbug_texture_t texture, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(8); /* texture */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_INFO)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(8, rbug_texture_t, texture); /* texture */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_TEXTURE_INFO, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_texture_write(struct rbug_connection *__con, + rbug_texture_t texture, + uint32_t face, + uint32_t level, + uint32_t zslice, + uint32_t x, + uint32_t y, + uint32_t w, + uint32_t h, + uint8_t *data, + uint32_t data_len, + uint32_t stride, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(8); /* texture */ + LEN(4); /* face */ + LEN(4); /* level */ + LEN(4); /* zslice */ + LEN(4); /* x */ + LEN(4); /* y */ + LEN(4); /* w */ + LEN(4); /* h */ + LEN_ARRAY(1, data); /* data */ + LEN(4); /* stride */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_WRITE)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(8, rbug_texture_t, texture); /* texture */ + WRITE(4, uint32_t, face); /* face */ + WRITE(4, uint32_t, level); /* level */ + WRITE(4, uint32_t, zslice); /* zslice */ + WRITE(4, uint32_t, x); /* x */ + WRITE(4, uint32_t, y); /* y */ + WRITE(4, uint32_t, w); /* w */ + WRITE(4, uint32_t, h); /* h */ + WRITE_ARRAY(1, uint8_t, data); /* data */ + WRITE(4, uint32_t, stride); /* stride */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_TEXTURE_WRITE, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_texture_read(struct rbug_connection *__con, + rbug_texture_t texture, + uint32_t face, + uint32_t level, + uint32_t zslice, + uint32_t x, + uint32_t y, + uint32_t w, + uint32_t h, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(8); /* texture */ + LEN(4); /* face */ + LEN(4); /* level */ + LEN(4); /* zslice */ + LEN(4); /* x */ + LEN(4); /* y */ + LEN(4); /* w */ + LEN(4); /* h */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_READ)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(8, rbug_texture_t, texture); /* texture */ + WRITE(4, uint32_t, face); /* face */ + WRITE(4, uint32_t, level); /* level */ + WRITE(4, uint32_t, zslice); /* zslice */ + WRITE(4, uint32_t, x); /* x */ + WRITE(4, uint32_t, y); /* y */ + WRITE(4, uint32_t, w); /* w */ + WRITE(4, uint32_t, h); /* h */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_TEXTURE_READ, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_texture_list_reply(struct rbug_connection *__con, + uint32_t serial, + rbug_texture_t *textures, + uint32_t textures_len, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(4); /* serial */ + LEN_ARRAY(8, textures); /* textures */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_LIST_REPLY)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(4, uint32_t, serial); /* serial */ + WRITE_ARRAY(8, rbug_texture_t, textures); /* textures */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_TEXTURE_LIST_REPLY, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_texture_info_reply(struct rbug_connection *__con, + uint32_t serial, + uint32_t target, + uint32_t format, + uint32_t *width, + uint32_t width_len, + uint32_t *height, + uint32_t height_len, + uint32_t *depth, + uint32_t depth_len, + uint32_t blockw, + uint32_t blockh, + uint32_t blocksize, + uint32_t last_level, + uint32_t nr_samples, + uint32_t tex_usage, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(4); /* serial */ + LEN(4); /* target */ + LEN(4); /* format */ + LEN_ARRAY(4, width); /* width */ + LEN_ARRAY(4, height); /* height */ + LEN_ARRAY(4, depth); /* depth */ + LEN(4); /* blockw */ + LEN(4); /* blockh */ + LEN(4); /* blocksize */ + LEN(4); /* last_level */ + LEN(4); /* nr_samples */ + LEN(4); /* tex_usage */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_INFO_REPLY)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(4, uint32_t, serial); /* serial */ + WRITE(4, uint32_t, target); /* target */ + WRITE(4, uint32_t, format); /* format */ + WRITE_ARRAY(4, uint32_t, width); /* width */ + WRITE_ARRAY(4, uint32_t, height); /* height */ + WRITE_ARRAY(4, uint32_t, depth); /* depth */ + WRITE(4, uint32_t, blockw); /* blockw */ + WRITE(4, uint32_t, blockh); /* blockh */ + WRITE(4, uint32_t, blocksize); /* blocksize */ + WRITE(4, uint32_t, last_level); /* last_level */ + WRITE(4, uint32_t, nr_samples); /* nr_samples */ + WRITE(4, uint32_t, tex_usage); /* tex_usage */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_TEXTURE_INFO_REPLY, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +int rbug_send_texture_read_reply(struct rbug_connection *__con, + uint32_t serial, + uint32_t format, + uint32_t blockw, + uint32_t blockh, + uint32_t blocksize, + uint8_t *data, + uint32_t data_len, + uint32_t stride, + uint32_t *__serial) +{ + uint32_t __len = 0; + uint32_t __pos = 0; + uint8_t *__data = NULL; + int __ret = 0; + + LEN(8); /* header */ + LEN(4); /* serial */ + LEN(4); /* format */ + LEN(4); /* blockw */ + LEN(4); /* blockh */ + LEN(4); /* blocksize */ + LEN_ARRAY(1, data); /* data */ + LEN(4); /* stride */ + + /* align */ + PAD(__len, 8); + + __data = (uint8_t*)MALLOC(__len); + if (!__data) + return -ENOMEM; + + WRITE(4, int32_t, ((int32_t)RBUG_OP_TEXTURE_READ_REPLY)); + WRITE(4, uint32_t, ((uint32_t)(__len / 4))); + WRITE(4, uint32_t, serial); /* serial */ + WRITE(4, uint32_t, format); /* format */ + WRITE(4, uint32_t, blockw); /* blockw */ + WRITE(4, uint32_t, blockh); /* blockh */ + WRITE(4, uint32_t, blocksize); /* blocksize */ + WRITE_ARRAY(1, uint8_t, data); /* data */ + WRITE(4, uint32_t, stride); /* stride */ + + /* final pad */ + PAD(__pos, 8); + + if (__pos != __len) { + __ret = -EINVAL; + } else { + rbug_connection_send_start(__con, RBUG_OP_TEXTURE_READ_REPLY, __len); + rbug_connection_write(__con, __data, __len); + __ret = rbug_connection_send_finish(__con, __serial); + } + + FREE(__data); + return __ret; +} + +struct rbug_proto_texture_list * rbug_demarshal_texture_list(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_texture_list *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_TEXTURE_LIST) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + + return ret; +} + +struct rbug_proto_texture_info * rbug_demarshal_texture_info(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_texture_info *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_TEXTURE_INFO) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(8, rbug_texture_t, texture); /* texture */ + + return ret; +} + +struct rbug_proto_texture_write * rbug_demarshal_texture_write(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_texture_write *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_TEXTURE_WRITE) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(8, rbug_texture_t, texture); /* texture */ + READ(4, uint32_t, face); /* face */ + READ(4, uint32_t, level); /* level */ + READ(4, uint32_t, zslice); /* zslice */ + READ(4, uint32_t, x); /* x */ + READ(4, uint32_t, y); /* y */ + READ(4, uint32_t, w); /* w */ + READ(4, uint32_t, h); /* h */ + READ_ARRAY(1, uint8_t, data); /* data */ + READ(4, uint32_t, stride); /* stride */ + + return ret; +} + +struct rbug_proto_texture_read * rbug_demarshal_texture_read(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_texture_read *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_TEXTURE_READ) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(8, rbug_texture_t, texture); /* texture */ + READ(4, uint32_t, face); /* face */ + READ(4, uint32_t, level); /* level */ + READ(4, uint32_t, zslice); /* zslice */ + READ(4, uint32_t, x); /* x */ + READ(4, uint32_t, y); /* y */ + READ(4, uint32_t, w); /* w */ + READ(4, uint32_t, h); /* h */ + + return ret; +} + +struct rbug_proto_texture_list_reply * rbug_demarshal_texture_list_reply(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_texture_list_reply *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_TEXTURE_LIST_REPLY) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(4, uint32_t, serial); /* serial */ + READ_ARRAY(8, rbug_texture_t, textures); /* textures */ + + return ret; +} + +struct rbug_proto_texture_info_reply * rbug_demarshal_texture_info_reply(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_texture_info_reply *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_TEXTURE_INFO_REPLY) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(4, uint32_t, serial); /* serial */ + READ(4, uint32_t, target); /* target */ + READ(4, uint32_t, format); /* format */ + READ_ARRAY(4, uint32_t, width); /* width */ + READ_ARRAY(4, uint32_t, height); /* height */ + READ_ARRAY(4, uint32_t, depth); /* depth */ + READ(4, uint32_t, blockw); /* blockw */ + READ(4, uint32_t, blockh); /* blockh */ + READ(4, uint32_t, blocksize); /* blocksize */ + READ(4, uint32_t, last_level); /* last_level */ + READ(4, uint32_t, nr_samples); /* nr_samples */ + READ(4, uint32_t, tex_usage); /* tex_usage */ + + return ret; +} + +struct rbug_proto_texture_read_reply * rbug_demarshal_texture_read_reply(struct rbug_proto_header *header) +{ + uint32_t len = 0; + uint32_t pos = 0; + uint8_t *data = NULL; + struct rbug_proto_texture_read_reply *ret; + + if (!header) + return NULL; + if (header->opcode != (int16_t)RBUG_OP_TEXTURE_READ_REPLY) + return NULL; + + pos = 0; + len = header->length * 4; + data = (uint8_t*)&header[1]; + ret = MALLOC(sizeof(*ret)); + if (!ret) + return NULL; + + ret->header.__message = header; + ret->header.opcode = header->opcode; + + READ(4, uint32_t, serial); /* serial */ + READ(4, uint32_t, format); /* format */ + READ(4, uint32_t, blockw); /* blockw */ + READ(4, uint32_t, blockh); /* blockh */ + READ(4, uint32_t, blocksize); /* blocksize */ + READ_ARRAY(1, uint8_t, data); /* data */ + READ(4, uint32_t, stride); /* stride */ + + return ret; +} diff --git a/src/gallium/auxiliary/rbug/rbug_texture.h b/src/gallium/auxiliary/rbug/rbug_texture.h new file mode 100644 index 0000000000..fbb247e1d4 --- /dev/null +++ b/src/gallium/auxiliary/rbug/rbug_texture.h @@ -0,0 +1,206 @@ +/* + * 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. + */ + +/* + * This file holds structs decelerations and function prototypes for one of + * the rbug extensions. Implementation of the functions is in the same folder + * in the c file matching this file's name. + * + * The structs what is returned from the demarshal functions. The functions + * starting rbug_send_* encodes a call to the write format and sends that to + * the supplied connection, while functions starting with rbug_demarshal_* + * demarshal data from the wire protocol. + * + * Structs and functions ending with _reply are replies to requests. + */ + +#ifndef _RBUG_PROTO_TEXTURE_H_ +#define _RBUG_PROTO_TEXTURE_H_ + +#include "rbug/rbug_proto.h" +#include "rbug/rbug_core.h" + +struct rbug_proto_texture_list +{ + struct rbug_header header; +}; + +struct rbug_proto_texture_info +{ + struct rbug_header header; + rbug_texture_t texture; +}; + +struct rbug_proto_texture_write +{ + struct rbug_header header; + rbug_texture_t texture; + uint32_t face; + uint32_t level; + uint32_t zslice; + uint32_t x; + uint32_t y; + uint32_t w; + uint32_t h; + uint8_t *data; + uint32_t data_len; + uint32_t stride; +}; + +struct rbug_proto_texture_read +{ + struct rbug_header header; + rbug_texture_t texture; + uint32_t face; + uint32_t level; + uint32_t zslice; + uint32_t x; + uint32_t y; + uint32_t w; + uint32_t h; +}; + +struct rbug_proto_texture_list_reply +{ + struct rbug_header header; + uint32_t serial; + rbug_texture_t *textures; + uint32_t textures_len; +}; + +struct rbug_proto_texture_info_reply +{ + struct rbug_header header; + uint32_t serial; + uint32_t target; + uint32_t format; + uint32_t *width; + uint32_t width_len; + uint32_t *height; + uint32_t height_len; + uint32_t *depth; + uint32_t depth_len; + uint32_t blockw; + uint32_t blockh; + uint32_t blocksize; + uint32_t last_level; + uint32_t nr_samples; + uint32_t tex_usage; +}; + +struct rbug_proto_texture_read_reply +{ + struct rbug_header header; + uint32_t serial; + uint32_t format; + uint32_t blockw; + uint32_t blockh; + uint32_t blocksize; + uint8_t *data; + uint32_t data_len; + uint32_t stride; +}; + +int rbug_send_texture_list(struct rbug_connection *__con, + uint32_t *__serial); + +int rbug_send_texture_info(struct rbug_connection *__con, + rbug_texture_t texture, + uint32_t *__serial); + +int rbug_send_texture_write(struct rbug_connection *__con, + rbug_texture_t texture, + uint32_t face, + uint32_t level, + uint32_t zslice, + uint32_t x, + uint32_t y, + uint32_t w, + uint32_t h, + uint8_t *data, + uint32_t data_len, + uint32_t stride, + uint32_t *__serial); + +int rbug_send_texture_read(struct rbug_connection *__con, + rbug_texture_t texture, + uint32_t face, + uint32_t level, + uint32_t zslice, + uint32_t x, + uint32_t y, + uint32_t w, + uint32_t h, + uint32_t *__serial); + +int rbug_send_texture_list_reply(struct rbug_connection *__con, + uint32_t serial, + rbug_texture_t *textures, + uint32_t textures_len, + uint32_t *__serial); + +int rbug_send_texture_info_reply(struct rbug_connection *__con, + uint32_t serial, + uint32_t target, + uint32_t format, + uint32_t *width, + uint32_t width_len, + uint32_t *height, + uint32_t height_len, + uint32_t *depth, + uint32_t depth_len, + uint32_t blockw, + uint32_t blockh, + uint32_t blocksize, + uint32_t last_level, + uint32_t nr_samples, + uint32_t tex_usage, + uint32_t *__serial); + +int rbug_send_texture_read_reply(struct rbug_connection *__con, + uint32_t serial, + uint32_t format, + uint32_t blockw, + uint32_t blockh, + uint32_t blocksize, + uint8_t *data, + uint32_t data_len, + uint32_t stride, + uint32_t *__serial); + +struct rbug_proto_texture_list * rbug_demarshal_texture_list(struct rbug_proto_header *header); + +struct rbug_proto_texture_info * rbug_demarshal_texture_info(struct rbug_proto_header *header); + +struct rbug_proto_texture_write * rbug_demarshal_texture_write(struct rbug_proto_header *header); + +struct rbug_proto_texture_read * rbug_demarshal_texture_read(struct rbug_proto_header *header); + +struct rbug_proto_texture_list_reply * rbug_demarshal_texture_list_reply(struct rbug_proto_header *header); + +struct rbug_proto_texture_info_reply * rbug_demarshal_texture_info_reply(struct rbug_proto_header *header); + +struct rbug_proto_texture_read_reply * rbug_demarshal_texture_read_reply(struct rbug_proto_header *header); + +#endif diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c index 57fcf6de2a..1acf3c373e 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_x86sse.c +++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.c @@ -993,6 +993,15 @@ void sse_pmovmskb( struct x86_function *p, emit_modrm(p, dst, src); } +void sse_movmskps( struct x86_function *p, + struct x86_reg dst, + struct x86_reg src) +{ + DUMP_RR( dst, src ); + emit_2ub(p, X86_TWOB, 0x50); + emit_modrm(p, dst, src); +} + /*********************************************************************** * SSE2 instructions */ diff --git a/src/gallium/auxiliary/rtasm/rtasm_x86sse.h b/src/gallium/auxiliary/rtasm/rtasm_x86sse.h index 1b5eaaca85..731a651796 100644 --- a/src/gallium/auxiliary/rtasm/rtasm_x86sse.h +++ b/src/gallium/auxiliary/rtasm/rtasm_x86sse.h @@ -223,6 +223,7 @@ void sse_unpckhps( struct x86_function *p, struct x86_reg dst, struct x86_reg sr void sse_unpcklps( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); void sse_pmovmskb( struct x86_function *p, struct x86_reg dest, struct x86_reg src ); void sse2_punpcklbw( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); +void sse_movmskps( struct x86_function *p, struct x86_reg dst, struct x86_reg src); void x86_add( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); void x86_and( struct x86_function *p, struct x86_reg dst, struct x86_reg src ); diff --git a/src/gallium/auxiliary/tgsi/Makefile b/src/gallium/auxiliary/tgsi/Makefile index b4900e8dba..5f0a580b09 100644 --- a/src/gallium/auxiliary/tgsi/Makefile +++ b/src/gallium/auxiliary/tgsi/Makefile @@ -16,6 +16,7 @@ C_SOURCES = \ tgsi_sse2.c \ tgsi_text.c \ tgsi_transform.c \ + tgsi_ureg.c \ tgsi_util.c include ../../Makefile.template diff --git a/src/gallium/auxiliary/tgsi/SConscript b/src/gallium/auxiliary/tgsi/SConscript index 8200cce42f..b6bc2924f0 100644 --- a/src/gallium/auxiliary/tgsi/SConscript +++ b/src/gallium/auxiliary/tgsi/SConscript @@ -16,6 +16,7 @@ tgsi = env.ConvenienceLibrary( 'tgsi_sse2.c', 'tgsi_text.c', 'tgsi_transform.c', + 'tgsi_ureg.c', 'tgsi_util.c', ]) diff --git a/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt b/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt index a3f4947c73..eb492076b7 100644 --- a/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt +++ b/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt @@ -187,11 +187,7 @@ TGSI Instruction Specification 1.2.6 CND0 - Condition Zero - dst.x = (src2.x >= 0.0) ? src0.x : src1.x - dst.y = (src2.y >= 0.0) ? src0.y : src1.y - dst.z = (src2.z >= 0.0) ? src0.z : src1.z - dst.w = (src2.w >= 0.0) ? src0.w : src1.w - + Removed. Use (CMP src2, src1, src0) instead. 1.2.7 DOT2ADD - 2-component Dot Product And Add @@ -665,9 +661,18 @@ TGSI Instruction Specification TBD -1.9.8 LOOP - Loop +1.9.8 BGNFOR - Begin a For-Loop - TBD + dst.x = floor(src.x) + dst.y = floor(src.y) + dst.z = floor(src.z) + + if (dst.y <= 0) + pc = [matching ENDFOR] + 1 + endif + + Note: The destination must be a loop register. + The source must be a constant register. 1.9.9 REP - Repeat @@ -685,9 +690,16 @@ TGSI Instruction Specification TBD -1.9.12 ENDLOOP - End Loop +1.9.12 ENDFOR - End a For-Loop - TBD + dst.x = dst.x + dst.z + dst.y = dst.y - 1.0 + + if (dst.y > 0) + pc = [matching BGNFOR instruction] + 1 + endif + + Note: The destination must be a loop register. 1.9.13 ENDREP - End Repeat @@ -840,7 +852,7 @@ TGSI Instruction Specification ---------- -1.13.1 BGNLOOP2 - Begin Loop +1.13.1 BGNLOOP - Begin a Loop TBD @@ -850,7 +862,7 @@ TGSI Instruction Specification TBD -1.13.3 ENDLOOP2 - End Loop +1.13.3 ENDLOOP - End a Loop TBD @@ -1015,12 +1027,12 @@ TGSI Instruction Specification 1.18.1 EXPP - Approximate Exponential Base 2 - Alias for EXP. + Use EXP. See also 1.19.3. 1.18.2 LOGP - Logarithm Base 2 - Alias for LG2. + Use LOG. See also 1.19.4. 1.19 vs_2_0 @@ -1037,6 +1049,16 @@ TGSI Instruction Specification Alias for ARR. +1.19.3 EXPP - Approximate Exponential Base 2 + + Use EX2. + + +1.19.4 LOGP - Logarithm Base 2 + + Use LG2. + + 2 Explanation of symbols used ============================== diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.c b/src/gallium/auxiliary/tgsi/tgsi_build.c index 94d9c638e1..e0cfc54420 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_build.c +++ b/src/gallium/auxiliary/tgsi/tgsi_build.c @@ -335,7 +335,10 @@ tgsi_default_full_immediate( void ) struct tgsi_full_immediate fullimm; fullimm.Immediate = tgsi_default_immediate(); - fullimm.u.Pointer = (void *) 0; + fullimm.u[0].Float = 0.0f; + fullimm.u[1].Float = 0.0f; + fullimm.u[2].Float = 0.0f; + fullimm.u[3].Float = 0.0f; return fullimm; } @@ -352,19 +355,19 @@ immediate_grow( header_bodysize_grow( header ); } -struct tgsi_immediate_float32 +union tgsi_immediate_data tgsi_build_immediate_float32( float value, struct tgsi_immediate *immediate, struct tgsi_header *header ) { - struct tgsi_immediate_float32 immediate_float32; + union tgsi_immediate_data immediate_data; - immediate_float32.Float = value; + immediate_data.Float = value; immediate_grow( immediate, header ); - return immediate_float32; + return immediate_data; } unsigned @@ -384,16 +387,18 @@ tgsi_build_full_immediate( *immediate = tgsi_build_immediate( header ); + assert( full_imm->Immediate.NrTokens <= 4 + 1 ); + for( i = 0; i < full_imm->Immediate.NrTokens - 1; i++ ) { - struct tgsi_immediate_float32 *if32; + union tgsi_immediate_data *data; if( maxsize <= size ) return 0; - if32 = (struct tgsi_immediate_float32 *) &tokens[size]; + data = (union tgsi_immediate_data *) &tokens[size]; size++; - *if32 = tgsi_build_immediate_float32( - full_imm->u.ImmediateFloat32[i].Float, + *data = tgsi_build_immediate_float32( + full_imm->u[i].Float, immediate, header ); } diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.h b/src/gallium/auxiliary/tgsi/tgsi_build.h index 9a3a077cf2..17d977b059 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_build.h +++ b/src/gallium/auxiliary/tgsi/tgsi_build.h @@ -119,7 +119,7 @@ tgsi_build_immediate( struct tgsi_full_immediate tgsi_default_full_immediate( void ); -struct tgsi_immediate_float32 +union tgsi_immediate_data tgsi_build_immediate_float32( float value, struct tgsi_immediate *immediate, diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump.c b/src/gallium/auxiliary/tgsi/tgsi_dump.c index a6994ecd48..111d95b666 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_dump.c +++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c @@ -33,12 +33,20 @@ #include "tgsi_info.h" #include "tgsi_iterate.h" + +/** Number of spaces to indent for IF/LOOP/etc */ +static const int indent_spaces = 3; + + struct dump_ctx { struct tgsi_iterate_context iter; uint instno; + int indent; + uint indentation; + void (*printf)(struct dump_ctx *ctx, const char *format, ...); }; @@ -82,7 +90,7 @@ static const char *processor_type_names[] = "GEOM" }; -static const char *file_names[] = +static const char *file_names[TGSI_FILE_COUNT] = { "NULL", "CONST", @@ -91,7 +99,8 @@ static const char *file_names[] = "TEMP", "SAMP", "ADDR", - "IMM" + "IMM", + "LOOP" }; static const char *interpolate_names[] = @@ -295,10 +304,12 @@ iter_immediate( ENM( imm->Immediate.DataType, immediate_type_names ); TXT( " { " ); + + assert( imm->Immediate.NrTokens <= 4 + 1 ); for (i = 0; i < imm->Immediate.NrTokens - 1; i++) { switch (imm->Immediate.DataType) { case TGSI_IMM_FLOAT32: - FLT( imm->u.ImmediateFloat32[i].Float ); + FLT( imm->u[i].Float ); break; default: assert( 0 ); @@ -332,13 +343,19 @@ iter_instruction( { struct dump_ctx *ctx = (struct dump_ctx *) iter; uint instno = ctx->instno++; - + const struct tgsi_opcode_info *info = tgsi_get_opcode_info( inst->Instruction.Opcode ); uint i; boolean first_reg = TRUE; INSTID( instno ); TXT( ": " ); - TXT( tgsi_get_opcode_info( inst->Instruction.Opcode )->mnemonic ); + + ctx->indent -= info->pre_dedent; + for(i = 0; (int)i < ctx->indent; ++i) + TXT( " " ); + ctx->indent += info->post_indent; + + TXT( info->mnemonic ); switch (inst->Instruction.Saturate) { case TGSI_SAT_NONE: @@ -470,14 +487,22 @@ iter_instruction( switch (inst->Instruction.Opcode) { case TGSI_OPCODE_IF: case TGSI_OPCODE_ELSE: - case TGSI_OPCODE_BGNLOOP2: - case TGSI_OPCODE_ENDLOOP2: + case TGSI_OPCODE_BGNLOOP: + case TGSI_OPCODE_ENDLOOP: case TGSI_OPCODE_CAL: TXT( " :" ); UID( inst->InstructionExtLabel.Label ); break; } + /* update indentation */ + if (inst->Instruction.Opcode == TGSI_OPCODE_IF || + inst->Instruction.Opcode == TGSI_OPCODE_ELSE || + inst->Instruction.Opcode == TGSI_OPCODE_BGNFOR || + inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP) { + ctx->indentation += indent_spaces; + } + EOL(); return TRUE; @@ -491,7 +516,9 @@ tgsi_dump_instruction( struct dump_ctx ctx; ctx.instno = instno; + ctx.indent = 0; ctx.printf = dump_ctx_printf; + ctx.indentation = 0; iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst ); } @@ -523,7 +550,9 @@ tgsi_dump( ctx.iter.epilog = NULL; ctx.instno = 0; + ctx.indent = 0; ctx.printf = dump_ctx_printf; + ctx.indentation = 0; tgsi_iterate_shader( tokens, &ctx.iter ); } @@ -575,7 +604,9 @@ tgsi_dump_str( ctx.base.iter.epilog = NULL; ctx.base.instno = 0; + ctx.base.indent = 0; ctx.base.printf = &str_dump_ctx_printf; + ctx.base.indentation = 0; ctx.str = str; ctx.str[0] = 0; diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump_c.c b/src/gallium/auxiliary/tgsi/tgsi_dump_c.c index 3dc61c48ca..4a9c02b141 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_dump_c.c +++ b/src/gallium/auxiliary/tgsi/tgsi_dump_c.c @@ -69,7 +69,7 @@ static const char *TGSI_TOKEN_TYPES[] = "TOKEN_TYPE_INSTRUCTION" }; -static const char *TGSI_FILES[] = +static const char *TGSI_FILES[TGSI_FILE_COUNT] = { "FILE_NULL", "FILE_CONSTANT", @@ -78,7 +78,8 @@ static const char *TGSI_FILES[] = "FILE_TEMPORARY", "FILE_SAMPLER", "FILE_ADDRESS", - "FILE_IMMEDIATE" + "FILE_IMMEDIATE", + "FILE_LOOP" }; static const char *TGSI_INTERPOLATES[] = @@ -283,12 +284,13 @@ dump_immediate_verbose( UIX( imm->Immediate.Padding ); } + assert( imm->Immediate.NrTokens <= 4 + 1 ); for( i = 0; i < imm->Immediate.NrTokens - 1; i++ ) { EOL(); switch( imm->Immediate.DataType ) { case TGSI_IMM_FLOAT32: TXT( "\nFloat: " ); - FLT( imm->u.ImmediateFloat32[i].Float ); + FLT( imm->u[i].Float ); break; default: diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c index 259894e72e..c79c56debd 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c @@ -304,14 +304,14 @@ tgsi_exec_machine_bind_shader( case TGSI_TOKEN_TYPE_IMMEDIATE: { uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1; - assert( size % 4 == 0 ); - assert( mach->ImmLimit + size / 4 <= TGSI_EXEC_NUM_IMMEDIATES ); + assert( size <= 4 ); + assert( mach->ImmLimit + 1 <= TGSI_EXEC_NUM_IMMEDIATES ); for( i = 0; i < size; i++ ) { - mach->Imms[mach->ImmLimit + i / 4][i % 4] = - parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float; + mach->Imms[mach->ImmLimit][i] = + parse.FullToken.FullImmediate.u[i].Float; } - mach->ImmLimit += size / 4; + mach->ImmLimit += 1; } break; @@ -373,13 +373,18 @@ tgsi_exec_machine_bind_shader( } -void -tgsi_exec_machine_init( - struct tgsi_exec_machine *mach ) +struct tgsi_exec_machine * +tgsi_exec_machine_create( void ) { + struct tgsi_exec_machine *mach; uint i; - mach->Temps = (struct tgsi_exec_vector *) tgsi_align_128bit( mach->_Temps); + mach = align_malloc( sizeof *mach, 16 ); + if (!mach) + goto fail; + + memset(mach, 0, sizeof(*mach)); + mach->Addrs = &mach->Temps[TGSI_EXEC_TEMP_ADDR]; /* Setup constants. */ @@ -401,22 +406,24 @@ tgsi_exec_machine_init( (void) print_chan; (void) print_temp; #endif + + return mach; + +fail: + align_free(mach); + return NULL; } void -tgsi_exec_machine_free_data(struct tgsi_exec_machine *mach) +tgsi_exec_machine_destroy(struct tgsi_exec_machine *mach) { - if (mach->Instructions) { + if (mach) { FREE(mach->Instructions); - mach->Instructions = NULL; - mach->NumInstructions = 0; - } - if (mach->Declarations) { FREE(mach->Declarations); - mach->Declarations = NULL; - mach->NumDeclarations = 0; } + + align_free(mach); } @@ -2015,8 +2022,7 @@ exec_instruction( switch (inst->Instruction.Opcode) { case TGSI_OPCODE_ARL: - case TGSI_OPCODE_FLOOR: - /* TGSI_OPCODE_FLR */ + case TGSI_OPCODE_FLR: FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { FETCH( &r[0], 0, chan_index ); micro_flr( &r[0], &r[0] ); @@ -2299,8 +2305,7 @@ exec_instruction( } break; - case TGSI_OPCODE_LERP: - /* TGSI_OPCODE_LRP */ + case TGSI_OPCODE_LRP: FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { FETCH(&r[0], 0, chan_index); FETCH(&r[1], 1, chan_index); @@ -2324,18 +2329,7 @@ exec_instruction( } break; - case TGSI_OPCODE_CND0: - FOR_EACH_ENABLED_CHANNEL(*inst, chan_index) { - FETCH(&r[0], 0, chan_index); - FETCH(&r[1], 1, chan_index); - FETCH(&r[2], 2, chan_index); - micro_le(&r[0], &mach->Temps[TEMP_0_I].xyzw[TEMP_0_C], &r[2], &r[0], &r[1]); - STORE(&r[0], 0, chan_index); - } - break; - - case TGSI_OPCODE_DOT2ADD: - /* TGSI_OPCODE_DP2A */ + case TGSI_OPCODE_DP2A: FETCH( &r[0], 0, CHAN_X ); FETCH( &r[1], 1, CHAN_X ); micro_mul( &r[0], &r[0], &r[1] ); @@ -2353,18 +2347,7 @@ exec_instruction( } break; - case TGSI_OPCODE_INDEX: - /* XXX: considered for removal */ - assert (0); - break; - - case TGSI_OPCODE_NEGATE: - /* XXX: considered for removal */ - assert (0); - break; - - case TGSI_OPCODE_FRAC: - /* TGSI_OPCODE_FRC */ + case TGSI_OPCODE_FRC: FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { FETCH( &r[0], 0, chan_index ); micro_frc( &r[0], &r[0] ); @@ -2392,8 +2375,7 @@ exec_instruction( } break; - case TGSI_OPCODE_EXPBASE2: - /* TGSI_OPCODE_EX2 */ + case TGSI_OPCODE_EX2: FETCH(&r[0], 0, CHAN_X); #if FAST_MATH @@ -2407,8 +2389,7 @@ exec_instruction( } break; - case TGSI_OPCODE_LOGBASE2: - /* TGSI_OPCODE_LG2 */ + case TGSI_OPCODE_LG2: FETCH( &r[0], 0, CHAN_X ); micro_lg2( &r[0], &r[0] ); FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { @@ -2416,8 +2397,7 @@ exec_instruction( } break; - case TGSI_OPCODE_POWER: - /* TGSI_OPCODE_POW */ + case TGSI_OPCODE_POW: FETCH(&r[0], 0, CHAN_X); FETCH(&r[1], 1, CHAN_X); @@ -2428,8 +2408,7 @@ exec_instruction( } break; - case TGSI_OPCODE_CROSSPRODUCT: - /* TGSI_OPCODE_XPD */ + case TGSI_OPCODE_XPD: FETCH(&r[0], 0, CHAN_Y); FETCH(&r[1], 1, CHAN_Z); @@ -2471,11 +2450,6 @@ exec_instruction( } break; - case TGSI_OPCODE_MULTIPLYMATRIX: - /* XXX: considered for removal */ - assert (0); - break; - case TGSI_OPCODE_ABS: FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { FETCH(&r[0], 0, chan_index); @@ -2782,19 +2756,32 @@ exec_instruction( if (mach->ExecMask) { /* do the call */ - /* push the Cond, Loop, Cont stacks */ + /* First, record the depths of the execution stacks. + * This is important for deeply nested/looped return statements. + * We have to unwind the stacks by the correct amount. For a + * real code generator, we could determine the number of entries + * to pop off each stack with simple static analysis and avoid + * implementing this data structure at run time. + */ + mach->CallStack[mach->CallStackTop].CondStackTop = mach->CondStackTop; + mach->CallStack[mach->CallStackTop].LoopStackTop = mach->LoopStackTop; + mach->CallStack[mach->CallStackTop].ContStackTop = mach->ContStackTop; + /* note that PC was already incremented above */ + mach->CallStack[mach->CallStackTop].ReturnAddr = *pc; + + mach->CallStackTop++; + + /* Second, push the Cond, Loop, Cont, Func stacks */ assert(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING); mach->CondStack[mach->CondStackTop++] = mach->CondMask; assert(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING); mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask; assert(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING); mach->ContStack[mach->ContStackTop++] = mach->ContMask; - assert(mach->FuncStackTop < TGSI_EXEC_MAX_CALL_NESTING); mach->FuncStack[mach->FuncStackTop++] = mach->FuncMask; - /* note that PC was already incremented above */ - mach->CallStack[mach->CallStackTop++] = *pc; + /* Finally, jump to the subroutine */ *pc = inst->InstructionExtLabel.Label; } break; @@ -2811,18 +2798,24 @@ exec_instruction( *pc = -1; return; } - *pc = mach->CallStack[--mach->CallStackTop]; - /* pop the Cond, Loop, Cont stacks */ - assert(mach->CondStackTop > 0); - mach->CondMask = mach->CondStack[--mach->CondStackTop]; - assert(mach->LoopStackTop > 0); - mach->LoopMask = mach->LoopStack[--mach->LoopStackTop]; - assert(mach->ContStackTop > 0); - mach->ContMask = mach->ContStack[--mach->ContStackTop]; + assert(mach->CallStackTop > 0); + mach->CallStackTop--; + + mach->CondStackTop = mach->CallStack[mach->CallStackTop].CondStackTop; + mach->CondMask = mach->CondStack[mach->CondStackTop]; + + mach->LoopStackTop = mach->CallStack[mach->CallStackTop].LoopStackTop; + mach->LoopMask = mach->LoopStack[mach->LoopStackTop]; + + mach->ContStackTop = mach->CallStack[mach->CallStackTop].ContStackTop; + mach->ContMask = mach->ContStack[mach->ContStackTop]; + assert(mach->FuncStackTop > 0); mach->FuncMask = mach->FuncStack[--mach->FuncStackTop]; + *pc = mach->CallStack[mach->CallStackTop].ReturnAddr; + UPDATE_EXEC_MASK(mach); } break; @@ -3119,26 +3112,81 @@ exec_instruction( mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]] = 0; break; - case TGSI_OPCODE_LOOP: + case TGSI_OPCODE_BGNFOR: + assert(mach->LoopCounterStackTop < TGSI_EXEC_MAX_LOOP_NESTING); + for (chan_index = 0; chan_index < 3; chan_index++) { + FETCH( &mach->LoopCounterStack[mach->LoopCounterStackTop].xyzw[chan_index], 0, chan_index ); + } + STORE( &mach->LoopCounterStack[mach->LoopCounterStackTop].xyzw[CHAN_Y], 0, CHAN_X ); + ++mach->LoopCounterStackTop; /* fall-through (for now) */ - case TGSI_OPCODE_BGNLOOP2: + case TGSI_OPCODE_BGNLOOP: /* push LoopMask and ContMasks */ assert(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING); mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask; assert(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING); mach->ContStack[mach->ContStackTop++] = mach->ContMask; + assert(mach->LoopLabelStackTop < TGSI_EXEC_MAX_LOOP_NESTING); + mach->LoopLabelStack[mach->LoopLabelStackTop++] = *pc - 1; + break; + + case TGSI_OPCODE_ENDFOR: + assert(mach->LoopCounterStackTop > 0); + micro_sub( &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X], + &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X], + &mach->Temps[TEMP_1_I].xyzw[TEMP_1_C] ); + /* update LoopMask */ + if( mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X].f[0] <= 0) { + mach->LoopMask &= ~0x1; + } + if( mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X].f[1] <= 0 ) { + mach->LoopMask &= ~0x2; + } + if( mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X].f[2] <= 0 ) { + mach->LoopMask &= ~0x4; + } + if( mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_X].f[3] <= 0 ) { + mach->LoopMask &= ~0x8; + } + micro_add( &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_Y], + &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_Y], + &mach->LoopCounterStack[mach->LoopCounterStackTop - 1].xyzw[CHAN_Z]); + assert(mach->LoopLabelStackTop > 0); + inst = mach->Instructions + mach->LoopLabelStack[mach->LoopLabelStackTop - 1]; + STORE( &mach->LoopCounterStack[mach->LoopCounterStackTop].xyzw[CHAN_Y], 0, CHAN_X ); + /* Restore ContMask, but don't pop */ + assert(mach->ContStackTop > 0); + mach->ContMask = mach->ContStack[mach->ContStackTop - 1]; + UPDATE_EXEC_MASK(mach); + if (mach->ExecMask) { + /* repeat loop: jump to instruction just past BGNLOOP */ + assert(mach->LoopLabelStackTop > 0); + *pc = mach->LoopLabelStack[mach->LoopLabelStackTop - 1] + 1; + } + else { + /* exit loop: pop LoopMask */ + assert(mach->LoopStackTop > 0); + mach->LoopMask = mach->LoopStack[--mach->LoopStackTop]; + /* pop ContMask */ + assert(mach->ContStackTop > 0); + mach->ContMask = mach->ContStack[--mach->ContStackTop]; + assert(mach->LoopLabelStackTop > 0); + --mach->LoopLabelStackTop; + assert(mach->LoopCounterStackTop > 0); + --mach->LoopCounterStackTop; + } + UPDATE_EXEC_MASK(mach); break; - + case TGSI_OPCODE_ENDLOOP: - /* fall-through (for now at least) */ - case TGSI_OPCODE_ENDLOOP2: /* Restore ContMask, but don't pop */ assert(mach->ContStackTop > 0); mach->ContMask = mach->ContStack[mach->ContStackTop - 1]; UPDATE_EXEC_MASK(mach); if (mach->ExecMask) { /* repeat loop: jump to instruction just past BGNLOOP */ - *pc = inst->InstructionExtLabel.Label + 1; + assert(mach->LoopLabelStackTop > 0); + *pc = mach->LoopLabelStack[mach->LoopLabelStackTop - 1] + 1; } else { /* exit loop: pop LoopMask */ @@ -3147,6 +3195,8 @@ exec_instruction( /* pop ContMask */ assert(mach->ContStackTop > 0); mach->ContMask = mach->ContStack[--mach->ContStackTop]; + assert(mach->LoopLabelStackTop > 0); + --mach->LoopLabelStackTop; } UPDATE_EXEC_MASK(mach); break; @@ -3214,7 +3264,6 @@ tgsi_exec_machine_run( struct tgsi_exec_machine *mach ) mach->FuncMask = 0xf; mach->ExecMask = 0xf; - mach->CondStackTop = 0; /* temporarily subvert this assertion */ assert(mach->CondStackTop == 0); assert(mach->LoopStackTop == 0); assert(mach->ContStackTop == 0); diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h index 182e5e228b..c72f76809d 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.h +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.h @@ -29,6 +29,7 @@ #define TGSI_EXEC_H #include "pipe/p_compiler.h" +#include "pipe/p_state.h" #if defined __cplusplus extern "C" { @@ -94,7 +95,6 @@ struct tgsi_exec_labels #define TGSI_EXEC_NUM_TEMPS 128 -#define TGSI_EXEC_NUM_TEMP_EXTRAS 6 #define TGSI_EXEC_NUM_IMMEDIATES 256 /* @@ -162,9 +162,14 @@ struct tgsi_exec_labels #define TGSI_EXEC_MASK_I (TGSI_EXEC_NUM_TEMPS + 3) #define TGSI_EXEC_MASK_C 2 +/* 4 register buffer for various purposes */ #define TGSI_EXEC_TEMP_R0 (TGSI_EXEC_NUM_TEMPS + 4) +#define TGSI_EXEC_NUM_TEMP_R 4 + +#define TGSI_EXEC_TEMP_ADDR (TGSI_EXEC_NUM_TEMPS + 8) +#define TGSI_EXEC_NUM_ADDRS 1 +#define TGSI_EXEC_NUM_TEMP_EXTRAS 9 -#define TGSI_EXEC_TEMP_ADDR (TGSI_EXEC_NUM_TEMPS + 5) #define TGSI_EXEC_MAX_COND_NESTING 20 @@ -181,30 +186,38 @@ struct tgsi_exec_labels */ #define TGSI_EXEC_MAX_CONST_BUFFER 4096 + +/** function call/activation record */ +struct tgsi_call_record +{ + uint CondStackTop; + uint LoopStackTop; + uint ContStackTop; + uint ReturnAddr; +}; + + /** * Run-time virtual machine state for executing TGSI shader. */ struct tgsi_exec_machine { /* Total = program temporaries + internal temporaries - * + 1 padding to align to 16 bytes */ - struct tgsi_exec_vector _Temps[TGSI_EXEC_NUM_TEMPS + - TGSI_EXEC_NUM_TEMP_EXTRAS + 1]; + struct tgsi_exec_vector Temps[TGSI_EXEC_NUM_TEMPS + + TGSI_EXEC_NUM_TEMP_EXTRAS]; + + float Imms[TGSI_EXEC_NUM_IMMEDIATES][4]; + + struct tgsi_exec_vector Inputs[PIPE_MAX_ATTRIBS]; + struct tgsi_exec_vector Outputs[PIPE_MAX_ATTRIBS]; - /* - * This will point to _Temps after aligning to 16B boundary. - */ - struct tgsi_exec_vector *Temps; struct tgsi_exec_vector *Addrs; struct tgsi_sampler **Samplers; - float Imms[TGSI_EXEC_NUM_IMMEDIATES][4]; unsigned ImmLimit; const float (*Consts)[4]; - struct tgsi_exec_vector *Inputs; - struct tgsi_exec_vector *Outputs; const struct tgsi_token *Tokens; /**< Declarations, instructions */ unsigned Processor; /**< TGSI_PROCESSOR_x */ @@ -230,6 +243,14 @@ struct tgsi_exec_machine uint LoopStack[TGSI_EXEC_MAX_LOOP_NESTING]; int LoopStackTop; + /** Loop label stack */ + uint LoopLabelStack[TGSI_EXEC_MAX_LOOP_NESTING]; + int LoopLabelStackTop; + + /** Loop counter stack (x = count, y = current, z = step) */ + struct tgsi_exec_vector LoopCounterStack[TGSI_EXEC_MAX_LOOP_NESTING]; + int LoopCounterStackTop; + /** Loop continue mask stack (see comments in tgsi_exec.c) */ uint ContStack[TGSI_EXEC_MAX_LOOP_NESTING]; int ContStackTop; @@ -239,7 +260,7 @@ struct tgsi_exec_machine int FuncStackTop; /** Function call stack for saving/restoring the program counter */ - uint CallStack[TGSI_EXEC_MAX_CALL_NESTING]; + struct tgsi_call_record CallStack[TGSI_EXEC_MAX_CALL_NESTING]; int CallStackTop; struct tgsi_full_instruction *Instructions; @@ -251,9 +272,11 @@ struct tgsi_exec_machine struct tgsi_exec_labels Labels; }; +struct tgsi_exec_machine * +tgsi_exec_machine_create( void ); + void -tgsi_exec_machine_init( - struct tgsi_exec_machine *mach ); +tgsi_exec_machine_destroy(struct tgsi_exec_machine *mach); void diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.c b/src/gallium/auxiliary/tgsi/tgsi_info.c index 37f2b66d1f..17af4cb7ad 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_info.c +++ b/src/gallium/auxiliary/tgsi/tgsi_info.c @@ -26,136 +26,156 @@ **************************************************************************/ #include "util/u_debug.h" +#include "util/u_memory.h" #include "tgsi_info.h" static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] = { - { 1, 1, 0, 0, "ARL", NULL, NULL }, - { 1, 1, 0, 0, "MOV", NULL, NULL }, - { 1, 1, 0, 0, "LIT", NULL, NULL }, - { 1, 1, 0, 0, "RCP", "RECIP", NULL }, - { 1, 1, 0, 0, "RSQ", "RECIPSQRT", NULL }, - { 1, 1, 0, 0, "EXP", "EXPP", NULL }, - { 1, 1, 0, 0, "LOG", NULL, NULL }, - { 1, 2, 0, 0, "MUL", NULL, NULL }, - { 1, 2, 0, 0, "ADD", NULL, NULL }, - { 1, 2, 0, 0, "DP3", "DOT3", NULL }, - { 1, 2, 0, 0, "DP4", "DOT4", NULL }, - { 1, 2, 0, 0, "DST", NULL, NULL }, - { 1, 2, 0, 0, "MIN", NULL, NULL }, - { 1, 2, 0, 0, "MAX", NULL, NULL }, - { 1, 2, 0, 0, "SLT", "SETLT", NULL }, - { 1, 2, 0, 0, "SGE", "SETGE", NULL }, - { 1, 3, 0, 0, "MAD", "MADD", NULL }, - { 1, 2, 0, 0, "SUB", NULL, NULL }, - { 1, 3, 0, 0, "LRP", "LERP", NULL }, - { 1, 3, 0, 0, "CND", NULL, NULL }, - { 1, 3, 0, 0, "CND0", NULL, NULL }, - { 1, 3, 0, 0, "DP2A", "DP2ADD", "DOT2ADD" }, - { 1, 2, 0, 0, "INDEX", NULL, NULL }, - { 1, 1, 0, 0, "NEGATE", NULL, NULL }, - { 1, 1, 0, 0, "FRC", "FRAC", NULL }, - { 1, 3, 0, 0, "CLAMP", NULL, NULL }, - { 1, 1, 0, 0, "FLR", "FLOOR", NULL }, - { 1, 1, 0, 0, "ROUND", NULL, NULL }, - { 1, 1, 0, 0, "EX2", "EXPBASE2", NULL }, - { 1, 1, 0, 0, "LG2", "LOGBASE2", "LOGP" }, - { 1, 2, 0, 0, "POW", "POWER", NULL }, - { 1, 2, 0, 0, "XPD", "CRS", "CROSSPRODUCT" }, - { 1, 2, 0, 0, "M4X4", "MULTIPLYMATRIX", NULL }, - { 1, 1, 0, 0, "ABS", NULL, NULL }, - { 1, 1, 0, 0, "RCC", NULL, NULL }, - { 1, 2, 0, 0, "DPH", NULL, NULL }, - { 1, 1, 0, 0, "COS", NULL, NULL }, - { 1, 1, 0, 0, "DDX", "DSX", NULL }, - { 1, 1, 0, 0, "DDY", "DSY", NULL }, - { 0, 0, 0, 0, "KILP", NULL, NULL }, - { 1, 1, 0, 0, "PK2H", NULL, NULL }, - { 1, 1, 0, 0, "PK2US", NULL, NULL }, - { 1, 1, 0, 0, "PK4B", NULL, NULL }, - { 1, 1, 0, 0, "PK4UB", NULL, NULL }, - { 1, 2, 0, 0, "RFL", NULL, NULL }, - { 1, 2, 0, 0, "SEQ", NULL, NULL }, - { 1, 2, 0, 0, "SFL", NULL, NULL }, - { 1, 2, 0, 0, "SGT", NULL, NULL }, - { 1, 1, 0, 0, "SIN", NULL, NULL }, - { 1, 2, 0, 0, "SLE", NULL, NULL }, - { 1, 2, 0, 0, "SNE", NULL, NULL }, - { 1, 2, 0, 0, "STR", NULL, NULL }, - { 1, 2, 1, 0, "TEX", "TEXLD", NULL }, - { 1, 4, 1, 0, "TXD", "TEXLDD", NULL }, - { 1, 2, 1, 0, "TXP", NULL, NULL }, - { 1, 1, 0, 0, "UP2H", NULL, NULL }, - { 1, 1, 0, 0, "UP2US", NULL, NULL }, - { 1, 1, 0, 0, "UP4B", NULL, NULL }, - { 1, 1, 0, 0, "UP4UB", NULL, NULL }, - { 1, 3, 0, 0, "X2D", NULL, NULL }, - { 1, 1, 0, 0, "ARA", NULL, NULL }, - { 1, 1, 0, 0, "ARR", "MOVA", NULL }, - { 0, 1, 0, 0, "BRA", NULL, NULL }, - { 0, 0, 0, 1, "CAL", "CALL", NULL }, - { 0, 0, 0, 0, "RET", NULL, NULL }, - { 1, 1, 0, 0, "SGN", "SSG", NULL }, - { 1, 3, 0, 0, "CMP", NULL, NULL }, - { 1, 1, 0, 0, "SCS", "SINCOS", NULL }, - { 1, 2, 1, 0, "TXB", "TEXLDB", NULL }, - { 1, 1, 0, 0, "NRM", NULL, NULL }, - { 1, 2, 0, 0, "DIV", NULL, NULL }, - { 1, 2, 0, 0, "DP2", NULL, NULL }, - { 1, 2, 1, 0, "TXL", NULL, NULL }, - { 0, 0, 0, 0, "BRK", "BREAK", NULL }, - { 0, 1, 0, 1, "IF", NULL, NULL }, - { 0, 0, 0, 0, "LOOP", NULL, NULL }, - { 0, 1, 0, 0, "REP", NULL, NULL }, - { 0, 0, 0, 1, "ELSE", NULL, NULL }, - { 0, 0, 0, 0, "ENDIF", NULL, NULL }, - { 0, 0, 0, 0, "ENDLOOP", NULL, NULL }, - { 0, 0, 0, 0, "ENDREP", NULL, NULL }, - { 0, 1, 0, 0, "PUSHA", NULL, NULL }, - { 1, 0, 0, 0, "POPA", NULL, NULL }, - { 1, 1, 0, 0, "CEIL", NULL, NULL }, - { 1, 1, 0, 0, "I2F", NULL, NULL }, - { 1, 1, 0, 0, "NOT", NULL, NULL }, - { 1, 1, 0, 0, "INT", "TRUNC", NULL }, - { 1, 2, 0, 0, "SHL", NULL, NULL }, - { 1, 2, 0, 0, "SHR", NULL, NULL }, - { 1, 2, 0, 0, "AND", NULL, NULL }, - { 1, 2, 0, 0, "OR", NULL, NULL }, - { 1, 2, 0, 0, "MOD", NULL, NULL }, - { 1, 2, 0, 0, "XOR", NULL, NULL }, - { 1, 3, 0, 0, "SAD", NULL, NULL }, - { 1, 2, 1, 0, "TXF", NULL, NULL }, - { 1, 2, 1, 0, "TXQ", NULL, NULL }, - { 0, 0, 0, 0, "CONT", NULL, NULL }, - { 0, 0, 0, 0, "EMIT", NULL, NULL }, - { 0, 0, 0, 0, "ENDPRIM", NULL, NULL }, - { 0, 0, 0, 1, "BGNLOOP2", NULL, NULL }, - { 0, 0, 0, 0, "BGNSUB", NULL, NULL }, - { 0, 0, 0, 1, "ENDLOOP2", NULL, NULL }, - { 0, 0, 0, 0, "ENDSUB", NULL, NULL }, - { 1, 1, 0, 0, "NOISE1", NULL, NULL }, - { 1, 1, 0, 0, "NOISE2", NULL, NULL }, - { 1, 1, 0, 0, "NOISE3", NULL, NULL }, - { 1, 1, 0, 0, "NOISE4", NULL, NULL }, - { 0, 0, 0, 0, "NOP", NULL, NULL }, - { 1, 2, 0, 0, "M4X3", NULL, NULL }, - { 1, 2, 0, 0, "M3X4", NULL, NULL }, - { 1, 2, 0, 0, "M3X3", NULL, NULL }, - { 1, 2, 0, 0, "M3X2", NULL, NULL }, - { 1, 1, 0, 0, "NRM4", NULL, NULL }, - { 0, 1, 0, 0, "CALLNZ", NULL, NULL }, - { 0, 1, 0, 0, "IFC", NULL, NULL }, - { 0, 1, 0, 0, "BREAKC", NULL, NULL }, - { 0, 1, 0, 0, "KIL", "TEXKILL", NULL }, - { 0, 0, 0, 0, "END", NULL, NULL }, - { 1, 1, 0, 0, "SWZ", NULL, NULL } + { 1, 1, 0, 0, 0, 0, "ARL", TGSI_OPCODE_ARL }, + { 1, 1, 0, 0, 0, 0, "MOV", TGSI_OPCODE_MOV }, + { 1, 1, 0, 0, 0, 0, "LIT", TGSI_OPCODE_LIT }, + { 1, 1, 0, 0, 0, 0, "RCP", TGSI_OPCODE_RCP }, + { 1, 1, 0, 0, 0, 0, "RSQ", TGSI_OPCODE_RSQ }, + { 1, 1, 0, 0, 0, 0, "EXP", TGSI_OPCODE_EXP }, + { 1, 1, 0, 0, 0, 0, "LOG", TGSI_OPCODE_LOG }, + { 1, 2, 0, 0, 0, 0, "MUL", TGSI_OPCODE_MUL }, + { 1, 2, 0, 0, 0, 0, "ADD", TGSI_OPCODE_ADD }, + { 1, 2, 0, 0, 0, 0, "DP3", TGSI_OPCODE_DP3 }, + { 1, 2, 0, 0, 0, 0, "DP4", TGSI_OPCODE_DP4 }, + { 1, 2, 0, 0, 0, 0, "DST", TGSI_OPCODE_DST }, + { 1, 2, 0, 0, 0, 0, "MIN", TGSI_OPCODE_MIN }, + { 1, 2, 0, 0, 0, 0, "MAX", TGSI_OPCODE_MAX }, + { 1, 2, 0, 0, 0, 0, "SLT", TGSI_OPCODE_SLT }, + { 1, 2, 0, 0, 0, 0, "SGE", TGSI_OPCODE_SGE }, + { 1, 3, 0, 0, 0, 0, "MAD", TGSI_OPCODE_MAD }, + { 1, 2, 0, 0, 0, 0, "SUB", TGSI_OPCODE_SUB }, + { 1, 3, 0, 0, 0, 0, "LRP", TGSI_OPCODE_LRP }, + { 1, 3, 0, 0, 0, 0, "CND", TGSI_OPCODE_CND }, + { 0, 0, 0, 0, 0, 0, "", 20 }, /* removed */ + { 1, 3, 0, 0, 0, 0, "DP2A", TGSI_OPCODE_DP2A }, + { 0, 0, 0, 0, 0, 0, "", 22 }, /* removed */ + { 0, 0, 0, 0, 0, 0, "", 23 }, /* removed */ + { 1, 1, 0, 0, 0, 0, "FRC", TGSI_OPCODE_FRC }, + { 1, 3, 0, 0, 0, 0, "CLAMP", TGSI_OPCODE_CLAMP }, + { 1, 1, 0, 0, 0, 0, "FLR", TGSI_OPCODE_FLR }, + { 1, 1, 0, 0, 0, 0, "ROUND", TGSI_OPCODE_ROUND }, + { 1, 1, 0, 0, 0, 0, "EX2", TGSI_OPCODE_EX2 }, + { 1, 1, 0, 0, 0, 0, "LG2", TGSI_OPCODE_LG2 }, + { 1, 2, 0, 0, 0, 0, "POW", TGSI_OPCODE_POW }, + { 1, 2, 0, 0, 0, 0, "XPD", TGSI_OPCODE_XPD }, + { 0, 0, 0, 0, 0, 0, "", 32 }, /* removed */ + { 1, 1, 0, 0, 0, 0, "ABS", TGSI_OPCODE_ABS }, + { 1, 1, 0, 0, 0, 0, "RCC", TGSI_OPCODE_RCC }, + { 1, 2, 0, 0, 0, 0, "DPH", TGSI_OPCODE_DPH }, + { 1, 1, 0, 0, 0, 0, "COS", TGSI_OPCODE_COS }, + { 1, 1, 0, 0, 0, 0, "DDX", TGSI_OPCODE_DDX }, + { 1, 1, 0, 0, 0, 0, "DDY", TGSI_OPCODE_DDY }, + { 0, 0, 0, 0, 0, 0, "KILP", TGSI_OPCODE_KILP }, + { 1, 1, 0, 0, 0, 0, "PK2H", TGSI_OPCODE_PK2H }, + { 1, 1, 0, 0, 0, 0, "PK2US", TGSI_OPCODE_PK2US }, + { 1, 1, 0, 0, 0, 0, "PK4B", TGSI_OPCODE_PK4B }, + { 1, 1, 0, 0, 0, 0, "PK4UB", TGSI_OPCODE_PK4UB }, + { 1, 2, 0, 0, 0, 0, "RFL", TGSI_OPCODE_RFL }, + { 1, 2, 0, 0, 0, 0, "SEQ", TGSI_OPCODE_SEQ }, + { 1, 2, 0, 0, 0, 0, "SFL", TGSI_OPCODE_SFL }, + { 1, 2, 0, 0, 0, 0, "SGT", TGSI_OPCODE_SGT }, + { 1, 1, 0, 0, 0, 0, "SIN", TGSI_OPCODE_SIN }, + { 1, 2, 0, 0, 0, 0, "SLE", TGSI_OPCODE_SLE }, + { 1, 2, 0, 0, 0, 0, "SNE", TGSI_OPCODE_SNE }, + { 1, 2, 0, 0, 0, 0, "STR", TGSI_OPCODE_STR }, + { 1, 2, 1, 0, 0, 0, "TEX", TGSI_OPCODE_TEX }, + { 1, 4, 1, 0, 0, 0, "TXD", TGSI_OPCODE_TXD }, + { 1, 2, 1, 0, 0, 0, "TXP", TGSI_OPCODE_TXP }, + { 1, 1, 0, 0, 0, 0, "UP2H", TGSI_OPCODE_UP2H }, + { 1, 1, 0, 0, 0, 0, "UP2US", TGSI_OPCODE_UP2US }, + { 1, 1, 0, 0, 0, 0, "UP4B", TGSI_OPCODE_UP4B }, + { 1, 1, 0, 0, 0, 0, "UP4UB", TGSI_OPCODE_UP4UB }, + { 1, 3, 0, 0, 0, 0, "X2D", TGSI_OPCODE_X2D }, + { 1, 1, 0, 0, 0, 0, "ARA", TGSI_OPCODE_ARA }, + { 1, 1, 0, 0, 0, 0, "ARR", TGSI_OPCODE_ARR }, + { 0, 1, 0, 0, 0, 0, "BRA", TGSI_OPCODE_BRA }, + { 0, 0, 0, 1, 0, 0, "CAL", TGSI_OPCODE_CAL }, + { 0, 0, 0, 0, 0, 0, "RET", TGSI_OPCODE_RET }, + { 1, 1, 0, 0, 0, 0, "SSG", TGSI_OPCODE_SSG }, + { 1, 3, 0, 0, 0, 0, "CMP", TGSI_OPCODE_CMP }, + { 1, 1, 0, 0, 0, 0, "SCS", TGSI_OPCODE_SCS }, + { 1, 2, 1, 0, 0, 0, "TXB", TGSI_OPCODE_TXB }, + { 1, 1, 0, 0, 0, 0, "NRM", TGSI_OPCODE_NRM }, + { 1, 2, 0, 0, 0, 0, "DIV", TGSI_OPCODE_DIV }, + { 1, 2, 0, 0, 0, 0, "DP2", TGSI_OPCODE_DP2 }, + { 1, 2, 1, 0, 0, 0, "TXL", TGSI_OPCODE_TXL }, + { 0, 0, 0, 0, 0, 0, "BRK", TGSI_OPCODE_BRK }, + { 0, 1, 0, 1, 0, 1, "IF", TGSI_OPCODE_IF }, + { 1, 1, 0, 0, 0, 1, "BGNFOR", TGSI_OPCODE_BGNFOR }, + { 0, 1, 0, 0, 0, 1, "REP", TGSI_OPCODE_REP }, + { 0, 0, 0, 1, 1, 1, "ELSE", TGSI_OPCODE_ELSE }, + { 0, 0, 0, 0, 1, 0, "ENDIF", TGSI_OPCODE_ENDIF }, + { 1, 0, 0, 0, 1, 0, "ENDFOR", TGSI_OPCODE_ENDFOR }, + { 0, 0, 0, 0, 1, 0, "ENDREP", TGSI_OPCODE_ENDREP }, + { 0, 1, 0, 0, 0, 0, "PUSHA", TGSI_OPCODE_PUSHA }, + { 1, 0, 0, 0, 0, 0, "POPA", TGSI_OPCODE_POPA }, + { 1, 1, 0, 0, 0, 0, "CEIL", TGSI_OPCODE_CEIL }, + { 1, 1, 0, 0, 0, 0, "I2F", TGSI_OPCODE_I2F }, + { 1, 1, 0, 0, 0, 0, "NOT", TGSI_OPCODE_NOT }, + { 1, 1, 0, 0, 0, 0, "TRUNC", TGSI_OPCODE_TRUNC }, + { 1, 2, 0, 0, 0, 0, "SHL", TGSI_OPCODE_SHL }, + { 1, 2, 0, 0, 0, 0, "SHR", TGSI_OPCODE_SHR }, + { 1, 2, 0, 0, 0, 0, "AND", TGSI_OPCODE_AND }, + { 1, 2, 0, 0, 0, 0, "OR", TGSI_OPCODE_OR }, + { 1, 2, 0, 0, 0, 0, "MOD", TGSI_OPCODE_MOD }, + { 1, 2, 0, 0, 0, 0, "XOR", TGSI_OPCODE_XOR }, + { 1, 3, 0, 0, 0, 0, "SAD", TGSI_OPCODE_SAD }, + { 1, 2, 1, 0, 0, 0, "TXF", TGSI_OPCODE_TXF }, + { 1, 2, 1, 0, 0, 0, "TXQ", TGSI_OPCODE_TXQ }, + { 0, 0, 0, 0, 0, 0, "CONT", TGSI_OPCODE_CONT }, + { 0, 0, 0, 0, 0, 0, "EMIT", TGSI_OPCODE_EMIT }, + { 0, 0, 0, 0, 0, 0, "ENDPRIM", TGSI_OPCODE_ENDPRIM }, + { 0, 0, 0, 1, 0, 1, "BGNLOOP", TGSI_OPCODE_BGNLOOP }, + { 0, 0, 0, 0, 0, 1, "BGNSUB", TGSI_OPCODE_BGNSUB }, + { 0, 0, 0, 1, 1, 0, "ENDLOOP", TGSI_OPCODE_ENDLOOP }, + { 0, 0, 0, 0, 1, 0, "ENDSUB", TGSI_OPCODE_ENDSUB }, + { 1, 1, 0, 0, 0, 0, "NOISE1", TGSI_OPCODE_NOISE1 }, + { 1, 1, 0, 0, 0, 0, "NOISE2", TGSI_OPCODE_NOISE2 }, + { 1, 1, 0, 0, 0, 0, "NOISE3", TGSI_OPCODE_NOISE3 }, + { 1, 1, 0, 0, 0, 0, "NOISE4", TGSI_OPCODE_NOISE4 }, + { 0, 0, 0, 0, 0, 0, "NOP", TGSI_OPCODE_NOP }, + { 0, 0, 0, 0, 0, 0, "", 108 }, /* removed */ + { 0, 0, 0, 0, 0, 0, "", 109 }, /* removed */ + { 0, 0, 0, 0, 0, 0, "", 110 }, /* removed */ + { 0, 0, 0, 0, 0, 0, "", 111 }, /* removed */ + { 1, 1, 0, 0, 0, 0, "NRM4", TGSI_OPCODE_NRM4 }, + { 0, 1, 0, 0, 0, 0, "CALLNZ", TGSI_OPCODE_CALLNZ }, + { 0, 1, 0, 0, 0, 0, "IFC", TGSI_OPCODE_IFC }, + { 0, 1, 0, 0, 0, 0, "BREAKC", TGSI_OPCODE_BREAKC }, + { 0, 1, 0, 0, 0, 0, "KIL", TGSI_OPCODE_KIL }, + { 0, 0, 0, 0, 0, 0, "END", TGSI_OPCODE_END }, + { 1, 1, 0, 0, 0, 0, "SWZ", TGSI_OPCODE_SWZ } }; const struct tgsi_opcode_info * tgsi_get_opcode_info( uint opcode ) { + static boolean firsttime = 1; + + if (firsttime) { + unsigned i; + firsttime = 0; + for (i = 0; i < Elements(opcode_info); i++) + assert(opcode_info[i].opcode == i); + } + if (opcode < TGSI_OPCODE_LAST) return &opcode_info[opcode]; + assert( 0 ); return NULL; } + + +const char * +tgsi_get_opcode_name( uint opcode ) +{ + const struct tgsi_opcode_info *info = tgsi_get_opcode_info(opcode); + return info->mnemonic; +} + diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.h b/src/gallium/auxiliary/tgsi/tgsi_info.h index 077e25acd7..74713c3b98 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_info.h +++ b/src/gallium/auxiliary/tgsi/tgsi_info.h @@ -36,18 +36,23 @@ extern "C" { struct tgsi_opcode_info { - uint num_dst; - uint num_src; - boolean is_tex; - boolean is_branch; + unsigned num_dst:3; + unsigned num_src:3; + unsigned is_tex:1; + unsigned is_branch:1; + int pre_dedent:2; + int post_indent:2; const char *mnemonic; - const char *alt_mnemonic1; - const char *alt_mnemonic2; + uint opcode; }; const struct tgsi_opcode_info * tgsi_get_opcode_info( uint opcode ); +const char * +tgsi_get_opcode_name( uint opcode ); + + #if defined __cplusplus } #endif diff --git a/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h new file mode 100644 index 0000000000..e7bcf4bf75 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_opcode_tmp.h @@ -0,0 +1,172 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * 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 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 TUNGSTEN GRAPHICS AND/OR ITS 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 OP12_TEX +#define OP12_TEX(a) OP12(a) +#endif + +#ifndef OP14_TEX +#define OP14_TEX(a) OP14(a) +#endif + +#ifndef OP00_LBL +#define OP00_LBL(a) OP00(a) +#endif + +#ifndef OP01_LBL +#define OP01_LBL(a) OP01(a) +#endif + +OP11(ARL) +OP11(MOV) +OP11(LIT) +OP11(RCP) +OP11(RSQ) +OP11(EXP) +OP11(LOG) +OP12(MUL) +OP12(ADD) +OP12(DP3) +OP12(DP4) +OP12(DST) +OP12(MIN) +OP12(MAX) +OP12(SLT) +OP12(SGE) +OP13(MAD) +OP12(SUB) +OP13(LRP) +OP13(CND) +OP13(DP2A) +OP11(FRC) +OP13(CLAMP) +OP11(FLR) +OP11(ROUND) +OP11(EX2) +OP11(LG2) +OP12(POW) +OP12(XPD) +OP11(ABS) +OP11(RCC) +OP12(DPH) +OP11(COS) +OP11(DDX) +OP11(DDY) +OP00(KILP) +OP11(PK2H) +OP11(PK2US) +OP11(PK4B) +OP11(PK4UB) +OP12(RFL) +OP12(SEQ) +OP12(SFL) +OP12(SGT) +OP11(SIN) +OP12(SLE) +OP12(SNE) +OP12(STR) +OP12_TEX(TEX) +OP14_TEX(TXD) +OP12_TEX(TXP) +OP11(UP2H) +OP11(UP2US) +OP11(UP4B) +OP11(UP4UB) +OP13(X2D) +OP11(ARA) +OP11(ARR) +OP01(BRA) +OP00_LBL(CAL) +OP00(RET) +OP11(SSG) +OP13(CMP) +OP11(SCS) +OP12_TEX(TXB) +OP11(NRM) +OP12(DIV) +OP12(DP2) +OP12_TEX(TXL) +OP00(BRK) +OP01_LBL(IF) +OP11(BGNFOR) +OP01(REP) +OP00_LBL(ELSE) +OP00(ENDIF) +OP10(ENDFOR) +OP00(ENDREP) +OP01(PUSHA) +OP10(POPA) +OP11(CEIL) +OP11(I2F) +OP11(NOT) +OP11(TRUNC) +OP12(SHL) +OP12(SHR) +OP12(AND) +OP12(OR) +OP12(MOD) +OP12(XOR) +OP13(SAD) +OP12_TEX(TXF) +OP12_TEX(TXQ) +OP00(CONT) +OP00(EMIT) +OP00(ENDPRIM) +OP00_LBL(BGNLOOP) +OP00(BGNSUB) +OP00_LBL(ENDLOOP) +OP00(ENDSUB) +OP11(NOISE1) +OP11(NOISE2) +OP11(NOISE3) +OP11(NOISE4) +OP00(NOP) +OP11(NRM4) +OP01(CALLNZ) +OP01(IFC) +OP01(BREAKC) +OP01(KIL) +OP00(END) +OP11(SWZ) + + +#undef OP00 +#undef OP01 +#undef OP10 +#undef OP11 +#undef OP12 +#undef OP13 + +#ifdef OP14 +#undef OP14 +#endif + +#undef OP00_LBL +#undef OP01_LBL + +#undef OP12_TEX +#undef OP14_TEX + diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.c b/src/gallium/auxiliary/tgsi/tgsi_parse.c index 7f2cfb7988..4870f82b6b 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_parse.c +++ b/src/gallium/auxiliary/tgsi/tgsi_parse.c @@ -42,9 +42,6 @@ void tgsi_full_token_free( union tgsi_full_token *full_token ) { - if( full_token->Token.Type == TGSI_TOKEN_TYPE_IMMEDIATE ) { - FREE( (void *) full_token->FullImmediate.u.Pointer ); - } } unsigned @@ -156,14 +153,8 @@ tgsi_parse_token( case TGSI_IMM_FLOAT32: { uint imm_count = imm->Immediate.NrTokens - 1; - struct tgsi_immediate_float32 *data; - - data = (struct tgsi_immediate_float32 *) MALLOC(sizeof(struct tgsi_immediate_float32) * imm_count); - if (data) { - for (i = 0; i < imm_count; i++) { - next_token(ctx, &data[i]); - } - imm->u.ImmediateFloat32 = data; + for (i = 0; i < imm_count; i++) { + next_token(ctx, &imm->u[i]); } } break; diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.h b/src/gallium/auxiliary/tgsi/tgsi_parse.h index 5268c02900..a26ee5ba86 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_parse.h +++ b/src/gallium/auxiliary/tgsi/tgsi_parse.h @@ -73,11 +73,7 @@ struct tgsi_full_declaration struct tgsi_full_immediate { struct tgsi_immediate Immediate; - union - { - const void *Pointer; - const struct tgsi_immediate_float32 *ImmediateFloat32; - } u; + union tgsi_immediate_data u[4]; }; #define TGSI_FULL_MAX_DST_REGISTERS 2 diff --git a/src/gallium/auxiliary/tgsi/tgsi_ppc.c b/src/gallium/auxiliary/tgsi/tgsi_ppc.c index 8466d9bc22..4b1c7d4e01 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ppc.c +++ b/src/gallium/auxiliary/tgsi/tgsi_ppc.c @@ -38,6 +38,7 @@ #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_sse.h" +#include "tgsi/tgsi_info.h" #include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_util.h" #include "tgsi_dump.h" @@ -619,17 +620,17 @@ emit_unaryop(struct gen_context *gen, struct tgsi_full_instruction *inst) ppc_vandc(gen->f, v1, v0, bit31_vec); /* v1 = v0 & ~bit31 */ } break; - case TGSI_OPCODE_FLOOR: + case TGSI_OPCODE_FLR: ppc_vrfim(gen->f, v1, v0); /* v1 = floor(v0) */ break; - case TGSI_OPCODE_FRAC: + case TGSI_OPCODE_FRC: ppc_vrfim(gen->f, v1, v0); /* tmp = floor(v0) */ ppc_vsubfp(gen->f, v1, v0, v1); /* v1 = v0 - v1 */ break; - case TGSI_OPCODE_EXPBASE2: + case TGSI_OPCODE_EX2: ppc_vexptefp(gen->f, v1, v0); /* v1 = 2^v0 */ break; - case TGSI_OPCODE_LOGBASE2: + case TGSI_OPCODE_LG2: /* XXX this may be broken! */ ppc_vlogefp(gen->f, v1, v0); /* v1 = log2(v0) */ break; @@ -1120,10 +1121,10 @@ emit_instruction(struct gen_context *gen, case TGSI_OPCODE_MOV: case TGSI_OPCODE_SWZ: case TGSI_OPCODE_ABS: - case TGSI_OPCODE_FLOOR: - case TGSI_OPCODE_FRAC: - case TGSI_OPCODE_EXPBASE2: - case TGSI_OPCODE_LOGBASE2: + case TGSI_OPCODE_FLR: + case TGSI_OPCODE_FRC: + case TGSI_OPCODE_EX2: + case TGSI_OPCODE_LG2: emit_unaryop(gen, inst); break; case TGSI_OPCODE_RSQ: @@ -1326,8 +1327,10 @@ tgsi_emit_ppc(const struct tgsi_token *tokens, ok = emit_instruction(&gen, &parse.FullToken.FullInstruction); if (!ok) { - debug_printf("failed to translate tgsi opcode %d to PPC (%s)\n", - parse.FullToken.FullInstruction.Instruction.Opcode, + uint opcode = parse.FullToken.FullInstruction.Instruction.Opcode; + debug_printf("failed to translate tgsi opcode %d (%s) to PPC (%s)\n", + opcode, + tgsi_get_opcode_name(opcode), parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX ? "vertex shader" : "fragment shader"); } @@ -1342,7 +1345,7 @@ tgsi_emit_ppc(const struct tgsi_token *tokens, assert(num_immediates < TGSI_EXEC_NUM_IMMEDIATES); for (i = 0; i < size; i++) { immediates[num_immediates][i] = - parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float; + parse.FullToken.FullImmediate.u[i].Float; } num_immediates++; } diff --git a/src/gallium/auxiliary/tgsi/tgsi_sanity.c b/src/gallium/auxiliary/tgsi/tgsi_sanity.c index 6f1f5c2b4b..8a13885da9 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sanity.c +++ b/src/gallium/auxiliary/tgsi/tgsi_sanity.c @@ -131,7 +131,7 @@ is_register_used( return (ctx->regs_used[file][index / BITS_IN_REG_FLAG] & (1 << (index % BITS_IN_REG_FLAG))) ? TRUE : FALSE; } -static const char *file_names[] = +static const char *file_names[TGSI_FILE_COUNT] = { "NULL", "CONST", @@ -140,7 +140,8 @@ static const char *file_names[] = "TEMP", "SAMP", "ADDR", - "IMM" + "IMM", + "LOOP" }; static boolean @@ -198,10 +199,10 @@ iter_instruction( } if (info->num_dst != inst->Instruction.NumDstRegs) { - report_error( ctx, "Invalid number of destination operands, should be %u", info->num_dst ); + report_error( ctx, "%s: Invalid number of destination operands, should be %u", info->mnemonic, info->num_dst ); } if (info->num_src != inst->Instruction.NumSrcRegs) { - report_error( ctx, "Invalid number of source operands, should be %u", info->num_src ); + report_error( ctx, "%s: Invalid number of source operands, should be %u", info->mnemonic, info->num_src ); } /* Check destination and source registers' validity. @@ -234,9 +235,29 @@ iter_instruction( index, "indirect", FALSE ); - if (file != TGSI_FILE_ADDRESS || index != 0) - report_warning( ctx, "Indirect register not ADDR[0]" ); + if (!(file == TGSI_FILE_ADDRESS || file == TGSI_FILE_LOOP) || index != 0) { + report_warning(ctx, "Indirect register neither ADDR[0] nor LOOP[0]"); + } + } + } + + switch (inst->Instruction.Opcode) { + case TGSI_OPCODE_BGNFOR: + case TGSI_OPCODE_ENDFOR: + if (inst->FullDstRegisters[0].DstRegister.File != TGSI_FILE_LOOP || + inst->FullDstRegisters[0].DstRegister.Index != 0) { + report_error(ctx, "Destination register must be LOOP[0]"); + } + break; + } + + switch (inst->Instruction.Opcode) { + case TGSI_OPCODE_BGNFOR: + if (inst->FullSrcRegisters[0].SrcRegister.File != TGSI_FILE_CONSTANT && + inst->FullSrcRegisters[0].SrcRegister.File != TGSI_FILE_IMMEDIATE) { + report_error(ctx, "Source register file must be either CONST or IMM"); } + break; } ctx->num_instructions++; diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/tgsi_sse2.c index a13368c80c..3cdf8b9f35 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sse2.c +++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.c @@ -32,9 +32,11 @@ #include "util/u_debug.h" #include "pipe/p_shader_tokens.h" #include "util/u_math.h" +#include "util/u_memory.h" #if defined(PIPE_ARCH_SSE) #include "util/u_sse.h" #endif +#include "tgsi/tgsi_info.h" #include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_util.h" #include "tgsi_exec.h" @@ -100,37 +102,55 @@ get_const_base( void ) { return x86_make_reg( file_REG32, - reg_CX ); + reg_AX ); } static struct x86_reg -get_input_base( void ) +get_machine_base( void ) { return x86_make_reg( file_REG32, - reg_AX ); + reg_CX ); +} + +static struct x86_reg +get_input_base( void ) +{ + return x86_make_disp( + get_machine_base(), + Offset(struct tgsi_exec_machine, Inputs) ); } static struct x86_reg get_output_base( void ) { - return x86_make_reg( - file_REG32, - reg_DX ); + return x86_make_disp( + get_machine_base(), + Offset(struct tgsi_exec_machine, Outputs) ); } static struct x86_reg get_temp_base( void ) { + return x86_make_disp( + get_machine_base(), + Offset(struct tgsi_exec_machine, Temps) ); +} + +static struct x86_reg +get_coef_base( void ) +{ return x86_make_reg( file_REG32, reg_BX ); } static struct x86_reg -get_coef_base( void ) +get_sampler_base( void ) { - return get_output_base(); + return x86_make_reg( + file_REG32, + reg_DI ); } static struct x86_reg @@ -138,7 +158,7 @@ get_immediate_base( void ) { return x86_make_reg( file_REG32, - reg_DI ); + reg_DX ); } @@ -168,6 +188,15 @@ get_const( } static struct x86_reg +get_sampler_ptr( + unsigned unit ) +{ + return x86_make_disp( + get_sampler_base(), + unit * sizeof( struct tgsi_sampler * ) ); +} + +static struct x86_reg get_input( unsigned vec, unsigned chan ) @@ -241,12 +270,14 @@ emit_const( /* 'vec' is the offset from the address register's value. * We're loading CONST[ADDR+vec] into an xmm register. */ - struct x86_reg r0 = get_input_base(); - struct x86_reg r1 = get_output_base(); + struct x86_reg r0 = get_immediate_base(); + struct x86_reg r1 = get_coef_base(); uint i; assert( indirectFile == TGSI_FILE_ADDRESS ); assert( indirectIndex == 0 ); + assert( r0.mod == mod_REG ); + assert( r1.mod == mod_REG ); x86_push( func, r0 ); x86_push( func, r1 ); @@ -520,24 +551,15 @@ emit_coef_dady( * that the stack pointer is 16 byte aligned, as expected. */ static void -emit_func_call_dst( +emit_func_call( struct x86_function *func, - unsigned xmm_save, - unsigned xmm_dst, + unsigned xmm_save_mask, + const struct x86_reg *arg, + unsigned nr_args, void (PIPE_CDECL *code)() ) { struct x86_reg ecx = x86_make_reg( file_REG32, reg_CX ); unsigned i, n; - unsigned xmm_mask; - - /* Bitmask of the xmm registers to save */ - xmm_mask = (1 << xmm_save) - 1; - xmm_mask &= ~(1 << xmm_dst); - - sse_movaps( - func, - get_temp( TEMP_R0, 0 ), - make_xmm( xmm_dst ) ); x86_push( func, @@ -549,8 +571,10 @@ emit_func_call_dst( func, x86_make_reg( file_REG32, reg_DX) ); + /* Store XMM regs to the stack + */ for(i = 0, n = 0; i < 8; ++i) - if(xmm_mask & (1 << i)) + if(xmm_save_mask & (1 << i)) ++n; x86_sub_imm( @@ -559,26 +583,42 @@ emit_func_call_dst( n*16); for(i = 0, n = 0; i < 8; ++i) - if(xmm_mask & (1 << i)) { + if(xmm_save_mask & (1 << i)) { sse_movups( func, x86_make_disp( x86_make_reg( file_REG32, reg_SP ), n*16 ), make_xmm( i ) ); ++n; } + + for (i = 0; i < nr_args; i++) { + /* Load the address of the buffer we use for passing arguments and + * receiving results: + */ + x86_lea( + func, + ecx, + arg[i] ); - x86_lea( - func, - ecx, - get_temp( TEMP_R0, 0 ) ); - - x86_push( func, ecx ); + /* Push actual function arguments (currently just the pointer to + * the buffer above), and call the function: + */ + x86_push( func, ecx ); + } + x86_mov_reg_imm( func, ecx, (unsigned long) code ); x86_call( func, ecx ); - x86_pop(func, ecx ); - + + /* Pop the arguments (or just add an immediate to esp) + */ + for (i = 0; i < nr_args; i++) { + x86_pop(func, ecx ); + } + + /* Pop the saved XMM regs: + */ for(i = 0, n = 0; i < 8; ++i) - if(xmm_mask & (1 << i)) { + if(xmm_save_mask & (1 << i)) { sse_movups( func, make_xmm( i ), @@ -602,34 +642,86 @@ emit_func_call_dst( x86_pop( func, x86_make_reg( file_REG32, reg_AX) ); +} + +static void +emit_func_call_dst_src1( + struct x86_function *func, + unsigned xmm_save, + unsigned xmm_dst, + unsigned xmm_src0, + void (PIPE_CDECL *code)() ) +{ + struct x86_reg store = get_temp( TEMP_R0, 0 ); + unsigned xmm_mask = ((1 << xmm_save) - 1) & ~(1 << xmm_dst); + + /* Store our input parameters (in xmm regs) to the buffer we use + * for passing arguments. We will pass a pointer to this buffer as + * the actual function argument. + */ + sse_movaps( + func, + store, + make_xmm( xmm_src0 ) ); + + emit_func_call( func, + xmm_mask, + &store, + 1, + code ); sse_movaps( func, make_xmm( xmm_dst ), - get_temp( TEMP_R0, 0 ) ); + store ); } + static void -emit_func_call_dst_src( +emit_func_call_dst_src2( struct x86_function *func, unsigned xmm_save, unsigned xmm_dst, - unsigned xmm_src, + unsigned xmm_src0, + unsigned xmm_src1, void (PIPE_CDECL *code)() ) { + struct x86_reg store = get_temp( TEMP_R0, 0 ); + unsigned xmm_mask = ((1 << xmm_save) - 1) & ~(1 << xmm_dst); + + /* Store two inputs to parameter buffer. + */ sse_movaps( func, - get_temp( TEMP_R0, 1 ), - make_xmm( xmm_src ) ); + store, + make_xmm( xmm_src0 ) ); - emit_func_call_dst( + sse_movaps( func, - xmm_save, - xmm_dst, - code ); + x86_make_disp( store, 4 * sizeof(float) ), + make_xmm( xmm_src1 ) ); + + + /* Emit the call + */ + emit_func_call( func, + xmm_mask, + &store, + 1, + code ); + + /* Retrieve the results: + */ + sse_movaps( + func, + make_xmm( xmm_dst ), + store ); } + + + #if defined(PIPE_ARCH_SSE) /* @@ -782,10 +874,11 @@ emit_cos( unsigned xmm_save, unsigned xmm_dst ) { - emit_func_call_dst( + emit_func_call_dst_src1( func, xmm_save, xmm_dst, + xmm_dst, cos4f ); } @@ -812,10 +905,11 @@ emit_ex2( unsigned xmm_save, unsigned xmm_dst ) { - emit_func_call_dst( + emit_func_call_dst_src1( func, xmm_save, xmm_dst, + xmm_dst, ex24f ); } @@ -857,10 +951,11 @@ emit_flr( unsigned xmm_save, unsigned xmm_dst ) { - emit_func_call_dst( + emit_func_call_dst_src1( func, xmm_save, xmm_dst, + xmm_dst, flr4f ); } @@ -880,10 +975,11 @@ emit_frc( unsigned xmm_save, unsigned xmm_dst ) { - emit_func_call_dst( + emit_func_call_dst_src1( func, xmm_save, xmm_dst, + xmm_dst, frc4f ); } @@ -910,10 +1006,11 @@ emit_lg2( unsigned xmm_save, unsigned xmm_dst ) { - emit_func_call_dst( + emit_func_call_dst_src1( func, xmm_save, xmm_dst, + xmm_dst, lg24f ); } @@ -975,13 +1072,15 @@ emit_pow( struct x86_function *func, unsigned xmm_save, unsigned xmm_dst, - unsigned xmm_src ) + unsigned xmm_src0, + unsigned xmm_src1 ) { - emit_func_call_dst_src( + emit_func_call_dst_src2( func, xmm_save, xmm_dst, - xmm_src, + xmm_src0, + xmm_src1, pow4f ); } @@ -1017,10 +1116,11 @@ emit_rnd( unsigned xmm_save, unsigned xmm_dst ) { - emit_func_call_dst( + emit_func_call_dst_src1( func, xmm_save, xmm_dst, + xmm_dst, rnd4f ); } @@ -1099,10 +1199,11 @@ emit_sgn( unsigned xmm_save, unsigned xmm_dst ) { - emit_func_call_dst( + emit_func_call_dst_src1( func, xmm_save, xmm_dst, + xmm_dst, sgn4f ); } @@ -1121,10 +1222,11 @@ emit_sin (struct x86_function *func, unsigned xmm_save, unsigned xmm_dst) { - emit_func_call_dst( + emit_func_call_dst_src1( func, xmm_save, xmm_dst, + xmm_dst, sin4f ); } @@ -1140,6 +1242,12 @@ emit_sub( make_xmm( xmm_src ) ); } + + + + + + /** * Register fetch. */ @@ -1298,20 +1406,164 @@ emit_store( #define STORE( FUNC, INST, XMM, INDEX, CHAN )\ emit_store( FUNC, XMM, &(INST).FullDstRegisters[INDEX], &(INST), CHAN ) + +static void PIPE_CDECL +fetch_texel( struct tgsi_sampler **sampler, + float *store ) +{ +#if 0 + uint j; + + debug_printf("%s sampler: %p (%p) store: %p\n", + __FUNCTION__, + sampler, *sampler, + store ); + + debug_printf("lodbias %f\n", store[12]); + + for (j = 0; j < 4; j++) + debug_printf("sample %d texcoord %f %f\n", + j, + store[0+j], + store[4+j]); +#endif + + { + float rgba[NUM_CHANNELS][QUAD_SIZE]; + (*sampler)->get_samples(*sampler, + &store[0], + &store[4], + &store[8], + 0.0f, /*store[12], lodbias */ + rgba); + + memcpy( store, rgba, 16 * sizeof(float)); + } + +#if 0 + for (j = 0; j < 4; j++) + debug_printf("sample %d result %f %f %f %f\n", + j, + store[0+j], + store[4+j], + store[8+j], + store[12+j]); +#endif +} + /** * High-level instruction translators. */ static void +emit_tex( struct x86_function *func, + const struct tgsi_full_instruction *inst, + boolean lodbias, + boolean projected) +{ + const uint unit = inst->FullSrcRegisters[1].SrcRegister.Index; + struct x86_reg args[2]; + unsigned count; + unsigned i; + + switch (inst->InstructionExtTexture.Texture) { + case TGSI_TEXTURE_1D: + count = 1; + break; + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_RECT: + count = 2; + break; + case TGSI_TEXTURE_SHADOW1D: + case TGSI_TEXTURE_SHADOW2D: + case TGSI_TEXTURE_SHADOWRECT: + case TGSI_TEXTURE_3D: + case TGSI_TEXTURE_CUBE: + count = 3; + break; + default: + assert(0); + return; + } + + if (lodbias) { + FETCH( func, *inst, 3, 0, 3 ); + } + else { + emit_tempf( + func, + 3, + TGSI_EXEC_TEMP_00000000_I, + TGSI_EXEC_TEMP_00000000_C ); + + } + + /* store lodbias whether enabled or not -- fetch_texel currently + * respects it always. + */ + sse_movaps( func, + get_temp( TEMP_R0, 3 ), + make_xmm( 3 ) ); + + + if (projected) { + FETCH( func, *inst, 3, 0, 3 ); + + emit_rcp( func, 3, 3 ); + } + + for (i = 0; i < count; i++) { + FETCH( func, *inst, i, 0, i ); + + if (projected) { + sse_mulps( + func, + make_xmm( i ), + make_xmm( 3 ) ); + } + + /* Store in the argument buffer: + */ + sse_movaps( + func, + get_temp( TEMP_R0, i ), + make_xmm( i ) ); + } + + args[0] = get_temp( TEMP_R0, 0 ); + args[1] = get_sampler_ptr( unit ); + + + emit_func_call( func, + 0, + args, + Elements(args), + fetch_texel ); + + /* If all four channels are enabled, could use a pointer to + * dst[0].x instead of TEMP_R0 for store? + */ + FOR_EACH_DST0_ENABLED_CHANNEL( *inst, i ) { + + sse_movaps( + func, + make_xmm( 0 ), + get_temp( TEMP_R0, i ) ); + + STORE( func, *inst, 0, 0, i ); + } +} + + +static void emit_kil( struct x86_function *func, const struct tgsi_full_src_register *reg ) { unsigned uniquemask; - unsigned registers[4]; - unsigned nextregister = 0; - unsigned firstchan = ~0; + unsigned unique_count = 0; unsigned chan_index; + unsigned i; /* This mask stores component bits that were already tested. Note that * we test if the value is less than zero, so 1.0 and 0.0 need not to be @@ -1331,18 +1583,11 @@ emit_kil( uniquemask |= 1 << swizzle; /* allocate register */ - registers[chan_index] = nextregister; emit_fetch( func, - nextregister, + unique_count++, reg, chan_index ); - nextregister++; - - /* mark the first channel used */ - if( firstchan == ~0 ) { - firstchan = chan_index; - } } } @@ -1353,32 +1598,32 @@ emit_kil( func, x86_make_reg( file_REG32, reg_DX ) ); - FOR_EACH_CHANNEL( chan_index ) { - if( uniquemask & (1 << chan_index) ) { - sse_cmpps( + for (i = 0 ; i < unique_count; i++ ) { + struct x86_reg dataXMM = make_xmm(i); + + sse_cmpps( + func, + dataXMM, + get_temp( + TGSI_EXEC_TEMP_00000000_I, + TGSI_EXEC_TEMP_00000000_C ), + cc_LessThan ); + + if( i == 0 ) { + sse_movmskps( func, - make_xmm( registers[chan_index] ), - get_temp( - TGSI_EXEC_TEMP_00000000_I, - TGSI_EXEC_TEMP_00000000_C ), - cc_LessThan ); - - if( chan_index == firstchan ) { - sse_pmovmskb( - func, - x86_make_reg( file_REG32, reg_AX ), - make_xmm( registers[chan_index] ) ); - } - else { - sse_pmovmskb( - func, - x86_make_reg( file_REG32, reg_DX ), - make_xmm( registers[chan_index] ) ); - x86_or( - func, - x86_make_reg( file_REG32, reg_AX ), - x86_make_reg( file_REG32, reg_DX ) ); - } + x86_make_reg( file_REG32, reg_AX ), + dataXMM ); + } + else { + sse_movmskps( + func, + x86_make_reg( file_REG32, reg_DX ), + dataXMM ); + x86_or( + func, + x86_make_reg( file_REG32, reg_AX ), + x86_make_reg( file_REG32, reg_DX ) ); } } @@ -1581,7 +1826,7 @@ emit_instruction( get_temp( TGSI_EXEC_TEMP_MINUS_128_I, TGSI_EXEC_TEMP_MINUS_128_C ) ); - emit_pow( func, 3, 1, 2 ); + emit_pow( func, 3, 1, 1, 2 ); FETCH( func, *inst, 0, 0, CHAN_X ); sse_xorps( func, @@ -1828,8 +2073,7 @@ emit_instruction( } break; - case TGSI_OPCODE_LERP: - /* TGSI_OPCODE_LRP */ + case TGSI_OPCODE_LRP: FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { FETCH( func, *inst, 0, 0, chan_index ); FETCH( func, *inst, 1, 1, chan_index ); @@ -1845,12 +2089,7 @@ emit_instruction( return 0; break; - case TGSI_OPCODE_CND0: - return 0; - break; - - case TGSI_OPCODE_DOT2ADD: - /* TGSI_OPCODE_DP2A */ + case TGSI_OPCODE_DP2A: FETCH( func, *inst, 0, 0, CHAN_X ); /* xmm0 = src[0].x */ FETCH( func, *inst, 1, 1, CHAN_X ); /* xmm1 = src[1].x */ emit_mul( func, 0, 1 ); /* xmm0 = xmm0 * xmm1 */ @@ -1865,16 +2104,7 @@ emit_instruction( } break; - case TGSI_OPCODE_INDEX: - return 0; - break; - - case TGSI_OPCODE_NEGATE: - return 0; - break; - - case TGSI_OPCODE_FRAC: - /* TGSI_OPCODE_FRC */ + case TGSI_OPCODE_FRC: FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { FETCH( func, *inst, 0, 0, chan_index ); emit_frc( func, 0, 0 ); @@ -1886,8 +2116,7 @@ emit_instruction( return 0; break; - case TGSI_OPCODE_FLOOR: - /* TGSI_OPCODE_FLR */ + case TGSI_OPCODE_FLR: FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { FETCH( func, *inst, 0, 0, chan_index ); emit_flr( func, 0, 0 ); @@ -1903,8 +2132,7 @@ emit_instruction( } break; - case TGSI_OPCODE_EXPBASE2: - /* TGSI_OPCODE_EX2 */ + case TGSI_OPCODE_EX2: FETCH( func, *inst, 0, 0, CHAN_X ); emit_ex2( func, 0, 0 ); FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { @@ -1912,8 +2140,7 @@ emit_instruction( } break; - case TGSI_OPCODE_LOGBASE2: - /* TGSI_OPCODE_LG2 */ + case TGSI_OPCODE_LG2: FETCH( func, *inst, 0, 0, CHAN_X ); emit_lg2( func, 0, 0 ); FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { @@ -1921,18 +2148,16 @@ emit_instruction( } break; - case TGSI_OPCODE_POWER: - /* TGSI_OPCODE_POW */ + case TGSI_OPCODE_POW: FETCH( func, *inst, 0, 0, CHAN_X ); FETCH( func, *inst, 1, 1, CHAN_X ); - emit_pow( func, 0, 0, 1 ); + emit_pow( func, 0, 0, 0, 1 ); FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { STORE( func, *inst, 0, 0, chan_index ); } break; - case TGSI_OPCODE_CROSSPRODUCT: - /* TGSI_OPCODE_XPD */ + case TGSI_OPCODE_XPD: if( IS_DST0_CHANNEL_ENABLED( *inst, CHAN_X ) || IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Y ) ) { FETCH( func, *inst, 1, 1, CHAN_Z ); @@ -1978,10 +2203,6 @@ emit_instruction( } break; - case TGSI_OPCODE_MULTIPLYMATRIX: - return 0; - break; - case TGSI_OPCODE_ABS: FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { FETCH( func, *inst, 0, 0, chan_index ); @@ -2094,21 +2315,7 @@ emit_instruction( break; case TGSI_OPCODE_TEX: - if (0) { - /* Disable dummy texture code: - */ - emit_tempf( - func, - 0, - TEMP_ONE_I, - TEMP_ONE_C ); - FOR_EACH_DST0_ENABLED_CHANNEL( *inst, chan_index ) { - STORE( func, *inst, 0, 0, chan_index ); - } - } - else { - return 0; - } + emit_tex( func, inst, FALSE, FALSE ); break; case TGSI_OPCODE_TXD: @@ -2206,7 +2413,7 @@ emit_instruction( break; case TGSI_OPCODE_TXB: - return 0; + emit_tex( func, inst, TRUE, FALSE ); break; case TGSI_OPCODE_NRM: @@ -2314,9 +2521,13 @@ emit_instruction( break; case TGSI_OPCODE_TXL: - return 0; + emit_tex( func, inst, TRUE, FALSE ); break; + case TGSI_OPCODE_TXP: + emit_tex( func, inst, FALSE, TRUE ); + break; + case TGSI_OPCODE_BRK: return 0; break; @@ -2325,7 +2536,7 @@ emit_instruction( return 0; break; - case TGSI_OPCODE_LOOP: + case TGSI_OPCODE_BGNFOR: return 0; break; @@ -2341,7 +2552,7 @@ emit_instruction( return 0; break; - case TGSI_OPCODE_ENDLOOP: + case TGSI_OPCODE_ENDFOR: return 0; break; @@ -2496,7 +2707,7 @@ emit_declaration( static void aos_to_soa( struct x86_function *func, uint arg_aos, - uint arg_soa, + uint arg_machine, uint arg_num, uint arg_stride ) { @@ -2511,7 +2722,10 @@ static void aos_to_soa( struct x86_function *func, x86_push( func, x86_make_reg( file_REG32, reg_BX ) ); x86_mov( func, aos_input, x86_fn_arg( func, arg_aos ) ); - x86_mov( func, soa_input, x86_fn_arg( func, arg_soa ) ); + x86_mov( func, soa_input, x86_fn_arg( func, arg_machine ) ); + x86_lea( func, soa_input, + x86_make_disp( soa_input, + Offset(struct tgsi_exec_machine, Inputs) ) ); x86_mov( func, num_inputs, x86_fn_arg( func, arg_num ) ); x86_mov( func, stride, x86_fn_arg( func, arg_stride ) ); @@ -2553,28 +2767,30 @@ static void aos_to_soa( struct x86_function *func, x86_jcc( func, cc_NE, inner_loop ); /* Restore EBX */ - x86_pop( func, aos_input ); + x86_pop( func, x86_make_reg( file_REG32, reg_BX ) ); } -static void soa_to_aos( struct x86_function *func, uint aos, uint soa, uint num, uint stride ) +static void soa_to_aos( struct x86_function *func, + uint arg_aos, + uint arg_machine, + uint arg_num, + uint arg_stride ) { - struct x86_reg soa_output; - struct x86_reg aos_output; - struct x86_reg num_outputs; - struct x86_reg temp; + struct x86_reg soa_output = x86_make_reg( file_REG32, reg_AX ); + struct x86_reg aos_output = x86_make_reg( file_REG32, reg_BX ); + struct x86_reg num_outputs = x86_make_reg( file_REG32, reg_CX ); + struct x86_reg temp = x86_make_reg( file_REG32, reg_DX ); int inner_loop; - soa_output = x86_make_reg( file_REG32, reg_AX ); - aos_output = x86_make_reg( file_REG32, reg_BX ); - num_outputs = x86_make_reg( file_REG32, reg_CX ); - temp = x86_make_reg( file_REG32, reg_DX ); - /* Save EBX */ - x86_push( func, aos_output ); + x86_push( func, x86_make_reg( file_REG32, reg_BX ) ); - x86_mov( func, soa_output, x86_fn_arg( func, soa ) ); - x86_mov( func, aos_output, x86_fn_arg( func, aos ) ); - x86_mov( func, num_outputs, x86_fn_arg( func, num ) ); + x86_mov( func, aos_output, x86_fn_arg( func, arg_aos ) ); + x86_mov( func, soa_output, x86_fn_arg( func, arg_machine ) ); + x86_lea( func, soa_output, + x86_make_disp( soa_output, + Offset(struct tgsi_exec_machine, Outputs) ) ); + x86_mov( func, num_outputs, x86_fn_arg( func, arg_num ) ); /* do */ inner_loop = x86_get_label( func ); @@ -2591,7 +2807,7 @@ static void soa_to_aos( struct x86_function *func, uint aos, uint soa, uint num, sse_unpcklps( func, make_xmm( 3 ), make_xmm( 4 ) ); sse_unpckhps( func, make_xmm( 5 ), make_xmm( 4 ) ); - x86_mov( func, temp, x86_fn_arg( func, stride ) ); + x86_mov( func, temp, x86_fn_arg( func, arg_stride ) ); x86_push( func, aos_output ); sse_movlps( func, x86_make_disp( aos_output, 0 ), make_xmm( 0 ) ); sse_movlps( func, x86_make_disp( aos_output, 8 ), make_xmm( 3 ) ); @@ -2615,20 +2831,13 @@ static void soa_to_aos( struct x86_function *func, uint aos, uint soa, uint num, x86_jcc( func, cc_NE, inner_loop ); /* Restore EBX */ - x86_pop( func, aos_output ); + x86_pop( func, x86_make_reg( file_REG32, reg_BX ) ); } /** * Translate a TGSI vertex/fragment shader to SSE2 code. * Slightly different things are done for vertex vs. fragment shaders. * - * Note that fragment shaders are responsible for interpolating shader - * inputs. Because on x86 we have only 4 GP registers, and here we - * have 5 shader arguments (input, output, const, temp and coef), the - * code is split into two phases -- DECLARATION and INSTRUCTION phase. - * GP register holding the output argument is aliased with the coeff - * argument, as outputs are not needed in the DECLARATION phase. - * * \param tokens the TGSI input shader * \param func the output SSE code/function * \param immediates buffer to place immediates, later passed to SSE func @@ -2642,7 +2851,6 @@ tgsi_emit_sse2( boolean do_swizzles ) { struct tgsi_parse_context parse; - boolean instruction_phase = FALSE; unsigned ok = 1; uint num_immediates = 0; @@ -2654,74 +2862,48 @@ tgsi_emit_sse2( /* Can't just use EDI, EBX without save/restoring them: */ - x86_push( - func, - get_immediate_base() ); - - x86_push( - func, - get_temp_base() ); - + x86_push( func, x86_make_reg( file_REG32, reg_BX ) ); + x86_push( func, x86_make_reg( file_REG32, reg_DI ) ); /* * Different function args for vertex/fragment shaders: */ - if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_FRAGMENT) { - /* DECLARATION phase, do not load output argument. */ - x86_mov( - func, - get_input_base(), - x86_fn_arg( func, 1 ) ); - /* skipping outputs argument here */ - x86_mov( - func, - get_const_base(), - x86_fn_arg( func, 3 ) ); - x86_mov( - func, - get_temp_base(), - x86_fn_arg( func, 4 ) ); - x86_mov( - func, - get_coef_base(), - x86_fn_arg( func, 5 ) ); - x86_mov( - func, - get_immediate_base(), - x86_fn_arg( func, 6 ) ); - } - else { - assert(parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX); - + if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX) { if (do_swizzles) aos_to_soa( func, - 6, /* aos_input */ - 1, /* machine->input */ - 7, /* num_inputs */ - 8 ); /* input_stride */ + 4, /* aos_input */ + 1, /* machine */ + 5, /* num_inputs */ + 6 ); /* input_stride */ + } + x86_mov( + func, + get_machine_base(), + x86_fn_arg( func, 1 ) ); + x86_mov( + func, + get_const_base(), + x86_fn_arg( func, 2 ) ); + x86_mov( + func, + get_immediate_base(), + x86_fn_arg( func, 3 ) ); + + if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_FRAGMENT) { x86_mov( - func, - get_input_base(), - x86_fn_arg( func, 1 ) ); - x86_mov( - func, - get_output_base(), - x86_fn_arg( func, 2 ) ); - x86_mov( - func, - get_const_base(), - x86_fn_arg( func, 3 ) ); - x86_mov( - func, - get_temp_base(), - x86_fn_arg( func, 4 ) ); - x86_mov( - func, - get_immediate_base(), - x86_fn_arg( func, 5 ) ); + func, + get_coef_base(), + x86_fn_arg( func, 4 ) ); } + x86_mov( + func, + get_sampler_base(), + x86_make_disp( get_machine_base(), + Offset( struct tgsi_exec_machine, Samplers ) ) ); + + while( !tgsi_parse_end_of_tokens( &parse ) && ok ) { tgsi_parse_token( &parse ); @@ -2735,24 +2917,15 @@ tgsi_emit_sse2( break; case TGSI_TOKEN_TYPE_INSTRUCTION: - if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_FRAGMENT) { - if( !instruction_phase ) { - /* INSTRUCTION phase, overwrite coeff with output. */ - instruction_phase = TRUE; - x86_mov( - func, - get_output_base(), - x86_fn_arg( func, 2 ) ); - } - } - ok = emit_instruction( func, &parse.FullToken.FullInstruction ); if (!ok) { - debug_printf("failed to translate tgsi opcode %d to SSE (%s)\n", - parse.FullToken.FullInstruction.Instruction.Opcode, + uint opcode = parse.FullToken.FullInstruction.Instruction.Opcode; + debug_printf("failed to translate tgsi opcode %d (%s) to SSE (%s)\n", + opcode, + tgsi_get_opcode_name(opcode), parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX ? "vertex shader" : "fragment shader"); } @@ -2767,7 +2940,7 @@ tgsi_emit_sse2( assert(num_immediates < TGSI_EXEC_NUM_IMMEDIATES); for( i = 0; i < size; i++ ) { immediates[num_immediates][i] = - parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float; + parse.FullToken.FullImmediate.u[i].Float; } #if 0 debug_printf("SSE FS immediate[%d] = %f %f %f %f\n", @@ -2789,18 +2962,17 @@ tgsi_emit_sse2( if (parse.FullHeader.Processor.Processor == TGSI_PROCESSOR_VERTEX) { if (do_swizzles) - soa_to_aos( func, 9, 2, 10, 11 ); + soa_to_aos( func, + 7, /* aos_output */ + 1, /* machine */ + 8, /* num_outputs */ + 9 ); /* output_stride */ } /* Can't just use EBX, EDI without save/restoring them: */ - x86_pop( - func, - get_temp_base() ); - - x86_pop( - func, - get_immediate_base() ); + x86_pop( func, x86_make_reg( file_REG32, reg_DI ) ); + x86_pop( func, x86_make_reg( file_REG32, reg_BX ) ); emit_ret( func ); diff --git a/src/gallium/auxiliary/tgsi/tgsi_sse2.h b/src/gallium/auxiliary/tgsi/tgsi_sse2.h index af838b2a25..d81ee3d00e 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sse2.h +++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.h @@ -34,6 +34,7 @@ extern "C" { struct tgsi_token; struct x86_function; +struct tgsi_interp_coef; unsigned tgsi_emit_sse2( @@ -42,6 +43,33 @@ tgsi_emit_sse2( float (*immediates)[4], boolean do_swizzles ); + +/* This is the function prototype generated when do_swizzles is false + * -- effectively for fragment shaders. + */ +typedef void (PIPE_CDECL *tgsi_sse2_fs_function) ( + struct tgsi_exec_machine *machine, /* 1 */ + const float (*constant)[4], /* 2 */ + const float (*immediate)[4], /* 3 */ + const struct tgsi_interp_coef *coef /* 4 */ + ); + + +/* This is the function prototype generated when do_swizzles is true + * -- effectively for vertex shaders. + */ +typedef void (PIPE_CDECL *tgsi_sse2_vs_func) ( + struct tgsi_exec_machine *machine, /* 1 */ + const float (*constant)[4], /* 2 */ + const float (*immediate)[4], /* 3 */ + const float (*aos_input)[4], /* 4 */ + uint num_inputs, /* 5 */ + uint input_stride, /* 6 */ + float (*aos_output)[4], /* 7 */ + uint num_outputs, /* 8 */ + uint output_stride ); /* 9 */ + + #if defined __cplusplus } #endif diff --git a/src/gallium/auxiliary/tgsi/tgsi_text.c b/src/gallium/auxiliary/tgsi/tgsi_text.c index a76bbc9140..d438450b1e 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_text.c +++ b/src/gallium/auxiliary/tgsi/tgsi_text.c @@ -231,7 +231,8 @@ static const char *file_names[TGSI_FILE_COUNT] = "TEMP", "SAMP", "ADDR", - "IMM" + "IMM", + "LOOP" }; static boolean @@ -789,16 +790,6 @@ match_inst_mnemonic(const char **pcur, if (str_match_no_case(pcur, info->mnemonic)) { return TRUE; } - if (info->alt_mnemonic1) { - if (str_match_no_case(pcur, info->alt_mnemonic1)) { - return TRUE; - } - if (info->alt_mnemonic2) { - if (str_match_no_case(pcur, info->alt_mnemonic2)) { - return TRUE; - } - } - } return FALSE; } @@ -1091,7 +1082,10 @@ static boolean parse_immediate( struct translate_ctx *ctx ) imm = tgsi_default_full_immediate(); imm.Immediate.NrTokens += 4; imm.Immediate.DataType = TGSI_IMM_FLOAT32; - imm.u.Pointer = values; + imm.u[0].Float = values[0]; + imm.u[1].Float = values[1]; + imm.u[2].Float = values[2]; + imm.u[3].Float = values[3]; advance = tgsi_build_full_immediate( &imm, diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c new file mode 100644 index 0000000000..f7096bd8e2 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c @@ -0,0 +1,938 @@ +/************************************************************************** + * + * 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 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, INC AND/OR ITS 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 "pipe/p_context.h" +#include "pipe/p_state.h" +#include "tgsi/tgsi_ureg.h" +#include "tgsi/tgsi_info.h" +#include "tgsi/tgsi_dump.h" +#include "util/u_memory.h" +#include "util/u_math.h" + +union tgsi_any_token { + struct tgsi_version version; + struct tgsi_header header; + struct tgsi_processor processor; + struct tgsi_token token; + struct tgsi_declaration decl; + struct tgsi_declaration_range decl_range; + struct tgsi_declaration_semantic decl_semantic; + struct tgsi_immediate imm; + union tgsi_immediate_data imm_data; + struct tgsi_instruction insn; + struct tgsi_instruction_ext_nv insn_ext_nv; + struct tgsi_instruction_ext_label insn_ext_label; + struct tgsi_instruction_ext_texture insn_ext_texture; + struct tgsi_instruction_ext_predicate insn_ext_predicate; + struct tgsi_src_register src; + struct tgsi_src_register_ext_swz src_ext_swz; + struct tgsi_src_register_ext_mod src_ext_mod; + struct tgsi_dimension dim; + struct tgsi_dst_register dst; + struct tgsi_dst_register_ext_concode dst_ext_code; + struct tgsi_dst_register_ext_modulate dst_ext_mod; + struct tgsi_dst_register_ext_predicate dst_ext_pred; + unsigned value; +}; + + +struct ureg_tokens { + union tgsi_any_token *tokens; + unsigned size; + unsigned order; + unsigned count; +}; + +#define UREG_MAX_INPUT PIPE_MAX_ATTRIBS +#define UREG_MAX_OUTPUT PIPE_MAX_ATTRIBS +#define UREG_MAX_IMMEDIATE 32 +#define UREG_MAX_TEMP 256 +#define UREG_MAX_ADDR 2 + +#define DOMAIN_DECL 0 +#define DOMAIN_INSN 1 + +struct ureg_program +{ + unsigned processor; + struct pipe_context *pipe; + + struct { + unsigned semantic_name; + unsigned semantic_index; + unsigned interp; + } input[UREG_MAX_INPUT]; + unsigned nr_inputs; + + struct { + unsigned semantic_name; + unsigned semantic_index; + } output[UREG_MAX_OUTPUT]; + unsigned nr_outputs; + + struct { + float v[4]; + unsigned nr; + } immediate[UREG_MAX_IMMEDIATE]; + unsigned nr_immediates; + + struct ureg_src sampler[PIPE_MAX_SAMPLERS]; + unsigned nr_samplers; + + unsigned temps_active[UREG_MAX_TEMP / 32]; + unsigned nr_temps; + + unsigned nr_addrs; + + unsigned nr_constants; + unsigned nr_instructions; + + struct ureg_tokens domain[2]; +}; + +static union tgsi_any_token error_tokens[32]; + +static void tokens_error( struct ureg_tokens *tokens ) +{ + tokens->tokens = error_tokens; + tokens->size = Elements(error_tokens); + tokens->count = 0; +} + + +static void tokens_expand( struct ureg_tokens *tokens, + unsigned count ) +{ + unsigned old_size = tokens->size * sizeof(unsigned); + + if (tokens->tokens == error_tokens) + goto fail; + + while (tokens->count + count > tokens->size) { + tokens->size = (1 << ++tokens->order); + } + + tokens->tokens = REALLOC(tokens->tokens, + old_size, + tokens->size * sizeof(unsigned)); + if (tokens->tokens == NULL) + goto fail; + + return; + +fail: + tokens_error(tokens); +} + +static void set_bad( struct ureg_program *ureg ) +{ + tokens_error(&ureg->domain[0]); +} + + + +static union tgsi_any_token *get_tokens( struct ureg_program *ureg, + unsigned domain, + unsigned count ) +{ + struct ureg_tokens *tokens = &ureg->domain[domain]; + union tgsi_any_token *result; + + if (tokens->count + count > tokens->size) + tokens_expand(tokens, count); + + result = &tokens->tokens[tokens->count]; + tokens->count += count; + return result; +} + + +static union tgsi_any_token *retrieve_token( struct ureg_program *ureg, + unsigned domain, + unsigned nr ) +{ + if (ureg->domain[domain].tokens == error_tokens) + return &error_tokens[0]; + + return &ureg->domain[domain].tokens[nr]; +} + + + +static INLINE struct ureg_dst +ureg_dst_register( unsigned file, + unsigned index ) +{ + struct ureg_dst dst; + + dst.File = file; + dst.WriteMask = TGSI_WRITEMASK_XYZW; + dst.Indirect = 0; + dst.IndirectIndex = 0; + dst.IndirectSwizzle = 0; + dst.Saturate = 0; + dst.Index = index; + dst.Pad1 = 0; + dst.Pad2 = 0; + + return dst; +} + +static INLINE struct ureg_src +ureg_src_register( unsigned file, + unsigned index ) +{ + struct ureg_src src; + + src.File = file; + src.SwizzleX = TGSI_SWIZZLE_X; + src.SwizzleY = TGSI_SWIZZLE_Y; + src.SwizzleZ = TGSI_SWIZZLE_Z; + src.SwizzleW = TGSI_SWIZZLE_W; + src.Pad = 0; + src.Indirect = 0; + src.IndirectIndex = 0; + src.IndirectSwizzle = 0; + src.Absolute = 0; + src.Index = index; + src.Negate = 0; + + return src; +} + + + + +static struct ureg_src +ureg_DECL_input( struct ureg_program *ureg, + unsigned name, + unsigned index, + unsigned interp_mode ) +{ + unsigned i; + + for (i = 0; i < ureg->nr_inputs; i++) { + if (ureg->input[i].semantic_name == name && + ureg->input[i].semantic_index == index) + goto out; + } + + if (ureg->nr_inputs < UREG_MAX_INPUT) { + ureg->input[i].semantic_name = name; + ureg->input[i].semantic_index = index; + ureg->input[i].interp = interp_mode; + ureg->nr_inputs++; + } + else { + set_bad( ureg ); + } + +out: + return ureg_src_register( TGSI_FILE_INPUT, i ); +} + + + +struct ureg_src +ureg_DECL_fs_input( struct ureg_program *ureg, + unsigned name, + unsigned index, + unsigned interp ) +{ + assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT); + return ureg_DECL_input( ureg, name, index, interp ); +} + + +struct ureg_src +ureg_DECL_vs_input( struct ureg_program *ureg, + unsigned name, + unsigned index ) +{ + assert(ureg->processor == TGSI_PROCESSOR_VERTEX); + return ureg_DECL_input( ureg, name, index, TGSI_INTERPOLATE_CONSTANT ); +} + + +struct ureg_dst +ureg_DECL_output( struct ureg_program *ureg, + unsigned name, + unsigned index ) +{ + unsigned i; + + for (i = 0; i < ureg->nr_outputs; i++) { + if (ureg->output[i].semantic_name == name && + ureg->output[i].semantic_index == index) + goto out; + } + + if (ureg->nr_outputs < UREG_MAX_OUTPUT) { + ureg->output[i].semantic_name = name; + ureg->output[i].semantic_index = index; + ureg->nr_outputs++; + } + else { + set_bad( ureg ); + } + +out: + return ureg_dst_register( TGSI_FILE_OUTPUT, i ); +} + + +/* Returns a new constant register. Keep track of which have been + * referred to so that we can emit decls later. + * + * There is nothing in this code to bind this constant to any tracked + * value or manage any constant_buffer contents -- that's the + * resposibility of the calling code. + */ +struct ureg_src ureg_DECL_constant(struct ureg_program *ureg ) +{ + return ureg_src_register( TGSI_FILE_CONSTANT, ureg->nr_constants++ ); +} + + +/* Allocate a new temporary. Temporaries greater than UREG_MAX_TEMP + * are legal, but will not be released. + */ +struct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg ) +{ + unsigned i; + + for (i = 0; i < UREG_MAX_TEMP; i += 32) { + int bit = ffs(~ureg->temps_active[i/32]); + if (bit != 0) { + i += bit - 1; + goto out; + } + } + + /* No reusable temps, so allocate a new one: + */ + i = ureg->nr_temps++; + +out: + if (i < UREG_MAX_TEMP) + ureg->temps_active[i/32] |= 1 << (i % 32); + + if (i >= ureg->nr_temps) + ureg->nr_temps = i + 1; + + return ureg_dst_register( TGSI_FILE_TEMPORARY, i ); +} + + +void ureg_release_temporary( struct ureg_program *ureg, + struct ureg_dst tmp ) +{ + if(tmp.File == TGSI_FILE_TEMPORARY) + if (tmp.Index < UREG_MAX_TEMP) + ureg->temps_active[tmp.Index/32] &= ~(1 << (tmp.Index % 32)); +} + + +/* Allocate a new address register. + */ +struct ureg_dst ureg_DECL_address( struct ureg_program *ureg ) +{ + if (ureg->nr_addrs < UREG_MAX_ADDR) + return ureg_dst_register( TGSI_FILE_ADDRESS, ureg->nr_addrs++ ); + + assert( 0 ); + return ureg_dst_register( TGSI_FILE_ADDRESS, 0 ); +} + +/* Allocate a new sampler. + */ +struct ureg_src ureg_DECL_sampler( struct ureg_program *ureg, + unsigned nr ) +{ + unsigned i; + + for (i = 0; i < ureg->nr_samplers; i++) + if (ureg->sampler[i].Index == nr) + return ureg->sampler[i]; + + if (i < PIPE_MAX_SAMPLERS) { + ureg->sampler[i] = ureg_src_register( TGSI_FILE_SAMPLER, nr ); + ureg->nr_samplers++; + return ureg->sampler[i]; + } + + assert( 0 ); + return ureg->sampler[0]; +} + + + + +static int match_or_expand_immediate( const float *v, + unsigned nr, + float *v2, + unsigned *nr2, + unsigned *swizzle ) +{ + unsigned i, j; + + *swizzle = 0; + + for (i = 0; i < nr; i++) { + boolean found = FALSE; + + for (j = 0; j < *nr2 && !found; j++) { + if (v[i] == v2[j]) { + *swizzle |= j << (i * 2); + found = TRUE; + } + } + + if (!found) { + if (*nr2 >= 4) + return FALSE; + + v2[*nr2] = v[i]; + *swizzle |= *nr2 << (i * 2); + (*nr2)++; + } + } + + return TRUE; +} + + + + +struct ureg_src ureg_DECL_immediate( struct ureg_program *ureg, + const float *v, + unsigned nr ) +{ + unsigned i, j; + unsigned swizzle; + + /* Could do a first pass where we examine all existing immediates + * without expanding. + */ + + for (i = 0; i < ureg->nr_immediates; i++) { + if (match_or_expand_immediate( v, + nr, + ureg->immediate[i].v, + &ureg->immediate[i].nr, + &swizzle )) + goto out; + } + + if (ureg->nr_immediates < UREG_MAX_IMMEDIATE) { + i = ureg->nr_immediates++; + if (match_or_expand_immediate( v, + nr, + ureg->immediate[i].v, + &ureg->immediate[i].nr, + &swizzle )) + goto out; + } + + set_bad( ureg ); + +out: + /* Make sure that all referenced elements are from this immediate. + * Has the effect of making size-one immediates into scalars. + */ + for (j = nr; j < 4; j++) + swizzle |= (swizzle & 0x3) << (j * 2); + + return ureg_swizzle( ureg_src_register( TGSI_FILE_IMMEDIATE, i ), + (swizzle >> 0) & 0x3, + (swizzle >> 2) & 0x3, + (swizzle >> 4) & 0x3, + (swizzle >> 6) & 0x3); +} + + +void +ureg_emit_src( struct ureg_program *ureg, + struct ureg_src src ) +{ + unsigned size = (1 + + (src.Absolute ? 1 : 0) + + (src.Indirect ? 1 : 0)); + + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size ); + unsigned n = 0; + + assert(src.File != TGSI_FILE_NULL); + assert(src.File != TGSI_FILE_OUTPUT); + assert(src.File < TGSI_FILE_COUNT); + + out[n].value = 0; + out[n].src.File = src.File; + out[n].src.SwizzleX = src.SwizzleX; + out[n].src.SwizzleY = src.SwizzleY; + out[n].src.SwizzleZ = src.SwizzleZ; + out[n].src.SwizzleW = src.SwizzleW; + out[n].src.Index = src.Index; + out[n].src.Negate = src.Negate; + n++; + + if (src.Absolute) { + out[0].src.Extended = 1; + out[0].src.Negate = 0; + out[n].value = 0; + out[n].src_ext_mod.Type = TGSI_SRC_REGISTER_EXT_TYPE_MOD; + out[n].src_ext_mod.Absolute = 1; + out[n].src_ext_mod.Negate = src.Negate; + n++; + } + + if (src.Indirect) { + out[0].src.Indirect = 1; + out[n].value = 0; + out[n].src.File = TGSI_FILE_ADDRESS; + out[n].src.SwizzleX = src.IndirectSwizzle; + out[n].src.SwizzleY = src.IndirectSwizzle; + out[n].src.SwizzleZ = src.IndirectSwizzle; + out[n].src.SwizzleW = src.IndirectSwizzle; + out[n].src.Index = src.IndirectIndex; + n++; + } + + assert(n == size); +} + + +void +ureg_emit_dst( struct ureg_program *ureg, + struct ureg_dst dst ) +{ + unsigned size = (1 + + (dst.Indirect ? 1 : 0)); + + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size ); + unsigned n = 0; + + assert(dst.File != TGSI_FILE_NULL); + assert(dst.File != TGSI_FILE_CONSTANT); + assert(dst.File != TGSI_FILE_INPUT); + assert(dst.File != TGSI_FILE_SAMPLER); + assert(dst.File != TGSI_FILE_IMMEDIATE); + assert(dst.File < TGSI_FILE_COUNT); + + out[n].value = 0; + out[n].dst.File = dst.File; + out[n].dst.WriteMask = dst.WriteMask; + out[n].dst.Indirect = dst.Indirect; + out[n].dst.Index = dst.Index; + n++; + + if (dst.Indirect) { + out[n].value = 0; + out[n].src.File = TGSI_FILE_ADDRESS; + out[n].src.SwizzleX = dst.IndirectSwizzle; + out[n].src.SwizzleY = dst.IndirectSwizzle; + out[n].src.SwizzleZ = dst.IndirectSwizzle; + out[n].src.SwizzleW = dst.IndirectSwizzle; + out[n].src.Index = dst.IndirectIndex; + n++; + } + + assert(n == size); +} + + + +unsigned +ureg_emit_insn(struct ureg_program *ureg, + unsigned opcode, + boolean saturate, + unsigned num_dst, + unsigned num_src ) +{ + union tgsi_any_token *out; + + out = get_tokens( ureg, DOMAIN_INSN, 1 ); + out[0].value = 0; + out[0].insn.Type = TGSI_TOKEN_TYPE_INSTRUCTION; + out[0].insn.NrTokens = 0; + out[0].insn.Opcode = opcode; + out[0].insn.Saturate = saturate; + out[0].insn.NumDstRegs = num_dst; + out[0].insn.NumSrcRegs = num_src; + out[0].insn.Padding = 0; + out[0].insn.Extended = 0; + + ureg->nr_instructions++; + + return ureg->domain[DOMAIN_INSN].count - 1; +} + + +void +ureg_emit_label(struct ureg_program *ureg, + unsigned insn_token, + unsigned *label_token ) +{ + union tgsi_any_token *out, *insn; + + if(!label_token) + return; + + out = get_tokens( ureg, DOMAIN_INSN, 1 ); + insn = retrieve_token( ureg, DOMAIN_INSN, insn_token ); + + insn->insn.Extended = 1; + + out[0].value = 0; + out[0].insn_ext_label.Type = TGSI_INSTRUCTION_EXT_TYPE_LABEL; + + *label_token = ureg->domain[DOMAIN_INSN].count - 1; +} + +/* Will return a number which can be used in a label to point to the + * next instruction to be emitted. + */ +unsigned +ureg_get_instruction_number( struct ureg_program *ureg ) +{ + return ureg->nr_instructions; +} + +/* Patch a given label (expressed as a token number) to point to a + * given instruction (expressed as an instruction number). + */ +void +ureg_fixup_label(struct ureg_program *ureg, + unsigned label_token, + unsigned instruction_number ) +{ + union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, label_token ); + + assert(out->insn_ext_label.Type == TGSI_INSTRUCTION_EXT_TYPE_LABEL); + out->insn_ext_label.Label = instruction_number; +} + + +void +ureg_emit_texture(struct ureg_program *ureg, + unsigned insn_token, + unsigned target ) +{ + union tgsi_any_token *out, *insn; + + out = get_tokens( ureg, DOMAIN_INSN, 1 ); + insn = retrieve_token( ureg, DOMAIN_INSN, insn_token ); + + insn->insn.Extended = 1; + + out[0].value = 0; + out[0].insn_ext_texture.Type = TGSI_INSTRUCTION_EXT_TYPE_TEXTURE; + out[0].insn_ext_texture.Texture = target; +} + + +void +ureg_fixup_insn_size(struct ureg_program *ureg, + unsigned insn ) +{ + union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, insn ); + + assert(out->insn.Type == TGSI_TOKEN_TYPE_INSTRUCTION); + out->insn.NrTokens = ureg->domain[DOMAIN_INSN].count - insn - 1; +} + + +void +ureg_insn(struct ureg_program *ureg, + unsigned opcode, + const struct ureg_dst *dst, + unsigned nr_dst, + const struct ureg_src *src, + unsigned nr_src ) +{ + unsigned insn, i; + boolean saturate; + +#ifdef DEBUG + { + const struct tgsi_opcode_info *info = tgsi_get_opcode_info( opcode ); + assert(info); + if(info) { + assert(nr_dst == info->num_dst); + assert(nr_src == info->num_src); + } + } +#endif + + saturate = nr_dst ? dst[0].Saturate : FALSE; + + insn = ureg_emit_insn( ureg, opcode, saturate, nr_dst, nr_src ); + + for (i = 0; i < nr_dst; i++) + ureg_emit_dst( ureg, dst[i] ); + + for (i = 0; i < nr_src; i++) + ureg_emit_src( ureg, src[i] ); + + ureg_fixup_insn_size( ureg, insn ); +} + + + +static void emit_decl( struct ureg_program *ureg, + unsigned file, + unsigned index, + unsigned semantic_name, + unsigned semantic_index, + unsigned interp ) +{ + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 3 ); + + out[0].value = 0; + out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; + out[0].decl.NrTokens = 3; + out[0].decl.File = file; + out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; /* FIXME! */ + out[0].decl.Interpolate = interp; + out[0].decl.Semantic = 1; + + out[1].value = 0; + out[1].decl_range.First = + out[1].decl_range.Last = index; + + out[2].value = 0; + out[2].decl_semantic.SemanticName = semantic_name; + out[2].decl_semantic.SemanticIndex = semantic_index; + +} + + +static void emit_decl_range( struct ureg_program *ureg, + unsigned file, + unsigned first, + unsigned count ) +{ + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 ); + + out[0].value = 0; + out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; + out[0].decl.NrTokens = 2; + out[0].decl.File = file; + out[0].decl.UsageMask = 0xf; + out[0].decl.Interpolate = TGSI_INTERPOLATE_CONSTANT; + out[0].decl.Semantic = 0; + + out[1].value = 0; + out[1].decl_range.First = first; + out[1].decl_range.Last = first + count - 1; +} + +static void emit_immediate( struct ureg_program *ureg, + const float *v ) +{ + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 5 ); + + out[0].value = 0; + out[0].imm.Type = TGSI_TOKEN_TYPE_IMMEDIATE; + out[0].imm.NrTokens = 5; + out[0].imm.DataType = TGSI_IMM_FLOAT32; + out[0].imm.Padding = 0; + out[0].imm.Extended = 0; + + out[1].imm_data.Float = v[0]; + out[2].imm_data.Float = v[1]; + out[3].imm_data.Float = v[2]; + out[4].imm_data.Float = v[3]; +} + + + + +static void emit_decls( struct ureg_program *ureg ) +{ + unsigned i; + + for (i = 0; i < ureg->nr_inputs; i++) { + emit_decl( ureg, + TGSI_FILE_INPUT, + i, + ureg->input[i].semantic_name, + ureg->input[i].semantic_index, + ureg->input[i].interp ); + } + + for (i = 0; i < ureg->nr_outputs; i++) { + emit_decl( ureg, + TGSI_FILE_OUTPUT, + i, + ureg->output[i].semantic_name, + ureg->output[i].semantic_index, + TGSI_INTERPOLATE_CONSTANT ); + } + + for (i = 0; i < ureg->nr_samplers; i++) { + emit_decl_range( ureg, + TGSI_FILE_SAMPLER, + ureg->sampler[i].Index, 1 ); + } + + if (ureg->nr_constants) { + emit_decl_range( ureg, + TGSI_FILE_CONSTANT, + 0, ureg->nr_constants ); + } + + if (ureg->nr_temps) { + emit_decl_range( ureg, + TGSI_FILE_TEMPORARY, + 0, ureg->nr_temps ); + } + + if (ureg->nr_addrs) { + emit_decl_range( ureg, + TGSI_FILE_ADDRESS, + 0, ureg->nr_addrs ); + } + + for (i = 0; i < ureg->nr_immediates; i++) { + emit_immediate( ureg, + ureg->immediate[i].v ); + } +} + +/* Append the instruction tokens onto the declarations to build a + * contiguous stream suitable to send to the driver. + */ +static void copy_instructions( struct ureg_program *ureg ) +{ + unsigned nr_tokens = ureg->domain[DOMAIN_INSN].count; + union tgsi_any_token *out = get_tokens( ureg, + DOMAIN_DECL, + nr_tokens ); + + memcpy(out, + ureg->domain[DOMAIN_INSN].tokens, + nr_tokens * sizeof out[0] ); +} + + +static void +fixup_header_size(struct ureg_program *ureg) +{ + union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_DECL, 1 ); + + out->header.BodySize = ureg->domain[DOMAIN_DECL].count - 3; +} + + +static void +emit_header( struct ureg_program *ureg ) +{ + union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 3 ); + + out[0].version.MajorVersion = 1; + out[0].version.MinorVersion = 1; + out[0].version.Padding = 0; + + out[1].header.HeaderSize = 2; + out[1].header.BodySize = 0; + + out[2].processor.Processor = ureg->processor; + out[2].processor.Padding = 0; +} + + +const struct tgsi_token *ureg_finalize( struct ureg_program *ureg ) +{ + const struct tgsi_token *tokens; + + emit_header( ureg ); + emit_decls( ureg ); + copy_instructions( ureg ); + fixup_header_size( ureg ); + + if (ureg->domain[0].tokens == error_tokens || + ureg->domain[1].tokens == error_tokens) { + debug_printf("%s: error in generated shader\n", __FUNCTION__); + assert(0); + return NULL; + } + + tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token; + + if (0) { + debug_printf("%s: emitted shader %d tokens:\n", __FUNCTION__, + ureg->domain[DOMAIN_DECL].count); + tgsi_dump( tokens, 0 ); + } + + return tokens; +} + + +void *ureg_create_shader( struct ureg_program *ureg, + struct pipe_context *pipe ) +{ + struct pipe_shader_state state; + + state.tokens = ureg_finalize(ureg); + if(!state.tokens) + return NULL; + + if (ureg->processor == TGSI_PROCESSOR_VERTEX) + return pipe->create_vs_state( pipe, &state ); + else + return pipe->create_fs_state( pipe, &state ); +} + + + + +struct ureg_program *ureg_create( unsigned processor ) +{ + struct ureg_program *ureg = CALLOC_STRUCT( ureg_program ); + if (ureg == NULL) + return NULL; + + ureg->processor = processor; + return ureg; +} + + +void ureg_destroy( struct ureg_program *ureg ) +{ + unsigned i; + + for (i = 0; i < Elements(ureg->domain); i++) { + if (ureg->domain[i].tokens && + ureg->domain[i].tokens != error_tokens) + FREE(ureg->domain[i].tokens); + } + + FREE(ureg); +} diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.h b/src/gallium/auxiliary/tgsi/tgsi_ureg.h new file mode 100644 index 0000000000..acbca59040 --- /dev/null +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.h @@ -0,0 +1,590 @@ +/************************************************************************** + * + * 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 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, INC AND/OR ITS 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 TGSI_UREG_H +#define TGSI_UREG_H + +#include "pipe/p_compiler.h" +#include "pipe/p_shader_tokens.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ureg_program; + +/* Almost a tgsi_src_register, but we need to pull in the Absolute + * flag from the _ext token. Indirect flag always implies ADDR[0]. + */ +struct ureg_src +{ + unsigned File : 4; /* TGSI_FILE_ */ + unsigned SwizzleX : 2; /* TGSI_SWIZZLE_ */ + unsigned SwizzleY : 2; /* TGSI_SWIZZLE_ */ + unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_ */ + unsigned SwizzleW : 2; /* TGSI_SWIZZLE_ */ + unsigned Pad : 1; /* BOOL */ + unsigned Indirect : 1; /* BOOL */ + unsigned Absolute : 1; /* BOOL */ + int Index : 16; /* SINT */ + unsigned Negate : 1; /* BOOL */ + int IndirectIndex : 16; /* SINT */ + int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */ +}; + +/* Very similar to a tgsi_dst_register, removing unsupported fields + * and adding a Saturate flag. It's easier to push saturate into the + * destination register than to try and create a _SAT varient of each + * instruction function. + */ +struct ureg_dst +{ + unsigned File : 4; /* TGSI_FILE_ */ + unsigned WriteMask : 4; /* TGSI_WRITEMASK_ */ + unsigned Indirect : 1; /* BOOL */ + unsigned Saturate : 1; /* BOOL */ + int Index : 16; /* SINT */ + unsigned Pad1 : 5; + unsigned Pad2 : 1; /* BOOL */ + int IndirectIndex : 16; /* SINT */ + int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */ +}; + +struct pipe_context; + +struct ureg_program * +ureg_create( unsigned processor ); + +const struct tgsi_token * +ureg_finalize( struct ureg_program * ); + +void * +ureg_create_shader( struct ureg_program *, + struct pipe_context *pipe ); + +void +ureg_destroy( struct ureg_program * ); + + +/*********************************************************************** + * Convenience routine: + */ +static INLINE void * +ureg_create_shader_and_destroy( struct ureg_program *p, + struct pipe_context *pipe ) +{ + void *result = ureg_create_shader( p, pipe ); + ureg_destroy( p ); + return result; +} + + + +/*********************************************************************** + * Build shader declarations: + */ + +struct ureg_src +ureg_DECL_fs_input( struct ureg_program *, + unsigned semantic_name, + unsigned semantic_index, + unsigned interp_mode ); + +struct ureg_src +ureg_DECL_vs_input( struct ureg_program *, + unsigned semantic_name, + unsigned semantic_index ); + +struct ureg_dst +ureg_DECL_output( struct ureg_program *, + unsigned semantic_name, + unsigned semantic_index ); + +struct ureg_src +ureg_DECL_immediate( struct ureg_program *, + const float *v, + unsigned nr ); + +struct ureg_src +ureg_DECL_constant( struct ureg_program * ); + +struct ureg_dst +ureg_DECL_temporary( struct ureg_program * ); + +void +ureg_release_temporary( struct ureg_program *ureg, + struct ureg_dst tmp ); + +struct ureg_dst +ureg_DECL_address( struct ureg_program * ); + +/* Supply an index to the sampler declaration as this is the hook to + * the external pipe_sampler state. Users of this function probably + * don't want just any sampler, but a specific one which they've set + * up state for in the context. + */ +struct ureg_src +ureg_DECL_sampler( struct ureg_program *, + unsigned index ); + + +static INLINE struct ureg_src +ureg_imm4f( struct ureg_program *ureg, + float a, float b, + float c, float d) +{ + float v[4]; + v[0] = a; + v[1] = b; + v[2] = c; + v[3] = d; + return ureg_DECL_immediate( ureg, v, 4 ); +} + +static INLINE struct ureg_src +ureg_imm3f( struct ureg_program *ureg, + float a, float b, + float c) +{ + float v[3]; + v[0] = a; + v[1] = b; + v[2] = c; + return ureg_DECL_immediate( ureg, v, 3 ); +} + +static INLINE struct ureg_src +ureg_imm2f( struct ureg_program *ureg, + float a, float b) +{ + float v[2]; + v[0] = a; + v[1] = b; + return ureg_DECL_immediate( ureg, v, 2 ); +} + +static INLINE struct ureg_src +ureg_imm1f( struct ureg_program *ureg, + float a) +{ + float v[1]; + v[0] = a; + return ureg_DECL_immediate( ureg, v, 1 ); +} + +/*********************************************************************** + * Functions for patching up labels + */ + + +/* Will return a number which can be used in a label to point to the + * next instruction to be emitted. + */ +unsigned +ureg_get_instruction_number( struct ureg_program *ureg ); + + +/* Patch a given label (expressed as a token number) to point to a + * given instruction (expressed as an instruction number). + * + * Labels are obtained from instruction emitters, eg ureg_CAL(). + * Instruction numbers are obtained from ureg_get_instruction_number(), + * above. + */ +void +ureg_fixup_label(struct ureg_program *ureg, + unsigned label_token, + unsigned instruction_number ); + + +/* Generic instruction emitter. Use if you need to pass the opcode as + * a parameter, rather than using the emit_OP() varients below. + */ +void +ureg_insn(struct ureg_program *ureg, + unsigned opcode, + const struct ureg_dst *dst, + unsigned nr_dst, + const struct ureg_src *src, + unsigned nr_src ); + + +/*********************************************************************** + * Internal instruction helpers, don't call these directly: + */ + +unsigned +ureg_emit_insn(struct ureg_program *ureg, + unsigned opcode, + boolean saturate, + unsigned num_dst, + unsigned num_src ); + +void +ureg_emit_label(struct ureg_program *ureg, + unsigned insn_token, + unsigned *label_token ); + +void +ureg_emit_texture(struct ureg_program *ureg, + unsigned insn_token, + unsigned target ); + +void +ureg_emit_dst( struct ureg_program *ureg, + struct ureg_dst dst ); + +void +ureg_emit_src( struct ureg_program *ureg, + struct ureg_src src ); + +void +ureg_fixup_insn_size(struct ureg_program *ureg, + unsigned insn ); + + +#define OP00( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + +#define OP01( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_src src ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \ + ureg_emit_src( ureg, src ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + +#define OP00_LBL( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + unsigned *label_token ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 0 ); \ + ureg_emit_label( ureg, insn, label_token ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + +#define OP01_LBL( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_src src, \ + unsigned *label_token ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, FALSE, 0, 1 ); \ + ureg_emit_label( ureg, insn, label_token ); \ + ureg_emit_src( ureg, src ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + +#define OP10( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 0 ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + + +#define OP11( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + struct ureg_src src ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 1 ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + +#define OP12( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + struct ureg_src src0, \ + struct ureg_src src1 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + +#define OP12_TEX( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + unsigned target, \ + struct ureg_src src0, \ + struct ureg_src src1 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 2 ); \ + ureg_emit_texture( ureg, insn, target ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + +#define OP13( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + struct ureg_src src0, \ + struct ureg_src src1, \ + struct ureg_src src2 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 3 ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_emit_src( ureg, src2 ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + +#define OP14_TEX( op ) \ +static INLINE void ureg_##op( struct ureg_program *ureg, \ + struct ureg_dst dst, \ + unsigned target, \ + struct ureg_src src0, \ + struct ureg_src src1, \ + struct ureg_src src2, \ + struct ureg_src src3 ) \ +{ \ + unsigned opcode = TGSI_OPCODE_##op; \ + unsigned insn = ureg_emit_insn( ureg, opcode, dst.Saturate, 1, 4 ); \ + ureg_emit_texture( ureg, insn, target ); \ + ureg_emit_dst( ureg, dst ); \ + ureg_emit_src( ureg, src0 ); \ + ureg_emit_src( ureg, src1 ); \ + ureg_emit_src( ureg, src2 ); \ + ureg_emit_src( ureg, src3 ); \ + ureg_fixup_insn_size( ureg, insn ); \ +} + + +/* Use a template include to generate a correctly-typed ureg_OP() + * function for each TGSI opcode: + */ +#include "tgsi_opcode_tmp.h" + + +/*********************************************************************** + * Inline helpers for manipulating register structs: + */ +static INLINE struct ureg_src +ureg_negate( struct ureg_src reg ) +{ + assert(reg.File != TGSI_FILE_NULL); + reg.Negate ^= 1; + return reg; +} + +static INLINE struct ureg_src +ureg_abs( struct ureg_src reg ) +{ + assert(reg.File != TGSI_FILE_NULL); + reg.Absolute = 1; + reg.Negate = 0; + return reg; +} + +static INLINE struct ureg_src +ureg_swizzle( struct ureg_src reg, + int x, int y, int z, int w ) +{ + unsigned swz = ( (reg.SwizzleX << 0) | + (reg.SwizzleY << 2) | + (reg.SwizzleZ << 4) | + (reg.SwizzleW << 6)); + + assert(reg.File != TGSI_FILE_NULL); + assert(x < 4); + assert(y < 4); + assert(z < 4); + assert(w < 4); + + reg.SwizzleX = (swz >> (x*2)) & 0x3; + reg.SwizzleY = (swz >> (y*2)) & 0x3; + reg.SwizzleZ = (swz >> (z*2)) & 0x3; + reg.SwizzleW = (swz >> (w*2)) & 0x3; + return reg; +} + +static INLINE struct ureg_src +ureg_scalar( struct ureg_src reg, int x ) +{ + return ureg_swizzle(reg, x, x, x, x); +} + +static INLINE struct ureg_dst +ureg_writemask( struct ureg_dst reg, + unsigned writemask ) +{ + assert(reg.File != TGSI_FILE_NULL); + reg.WriteMask &= writemask; + return reg; +} + +static INLINE struct ureg_dst +ureg_saturate( struct ureg_dst reg ) +{ + assert(reg.File != TGSI_FILE_NULL); + reg.Saturate = 1; + return reg; +} + +static INLINE struct ureg_dst +ureg_dst_indirect( struct ureg_dst reg, struct ureg_src addr ) +{ + assert(reg.File != TGSI_FILE_NULL); + assert(addr.File == TGSI_FILE_ADDRESS); + reg.Indirect = 1; + reg.IndirectIndex = addr.Index; + reg.IndirectSwizzle = addr.SwizzleX; + return reg; +} + +static INLINE struct ureg_src +ureg_src_indirect( struct ureg_src reg, struct ureg_src addr ) +{ + assert(reg.File != TGSI_FILE_NULL); + assert(addr.File == TGSI_FILE_ADDRESS); + reg.Indirect = 1; + reg.IndirectIndex = addr.Index; + reg.IndirectSwizzle = addr.SwizzleX; + return reg; +} + +static INLINE struct ureg_dst +ureg_dst( struct ureg_src src ) +{ + struct ureg_dst dst; + + dst.File = src.File; + dst.WriteMask = TGSI_WRITEMASK_XYZW; + dst.Indirect = src.Indirect; + dst.IndirectIndex = src.IndirectIndex; + dst.IndirectSwizzle = src.IndirectSwizzle; + dst.Saturate = 0; + dst.Index = src.Index; + dst.Pad1 = 0; + dst.Pad2 = 0; + + return dst; +} + +static INLINE struct ureg_src +ureg_src( struct ureg_dst dst ) +{ + struct ureg_src src; + + src.File = dst.File; + src.SwizzleX = TGSI_SWIZZLE_X; + src.SwizzleY = TGSI_SWIZZLE_Y; + src.SwizzleZ = TGSI_SWIZZLE_Z; + src.SwizzleW = TGSI_SWIZZLE_W; + src.Pad = 0; + src.Indirect = dst.Indirect; + src.IndirectIndex = dst.IndirectIndex; + src.IndirectSwizzle = dst.IndirectSwizzle; + src.Absolute = 0; + src.Index = dst.Index; + src.Negate = 0; + + return src; +} + + + +static INLINE struct ureg_dst +ureg_dst_undef( void ) +{ + struct ureg_dst dst; + + dst.File = TGSI_FILE_NULL; + dst.WriteMask = 0; + dst.Indirect = 0; + dst.IndirectIndex = 0; + dst.IndirectSwizzle = 0; + dst.Saturate = 0; + dst.Index = 0; + dst.Pad1 = 0; + dst.Pad2 = 0; + + return dst; +} + +static INLINE struct ureg_src +ureg_src_undef( void ) +{ + struct ureg_src src; + + src.File = TGSI_FILE_NULL; + src.SwizzleX = 0; + src.SwizzleY = 0; + src.SwizzleZ = 0; + src.SwizzleW = 0; + src.Pad = 0; + src.Indirect = 0; + src.IndirectIndex = 0; + src.IndirectSwizzle = 0; + src.Absolute = 0; + src.Index = 0; + src.Negate = 0; + + return src; +} + +static INLINE boolean +ureg_src_is_undef( struct ureg_src src ) +{ + return src.File == TGSI_FILE_NULL; +} + +static INLINE boolean +ureg_dst_is_undef( struct ureg_dst dst ) +{ + return dst.File == TGSI_FILE_NULL; +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/gallium/auxiliary/tgsi/tgsi_util.h b/src/gallium/auxiliary/tgsi/tgsi_util.h index 7877f34558..21eb656327 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_util.h +++ b/src/gallium/auxiliary/tgsi/tgsi_util.h @@ -32,6 +32,10 @@ extern "C" { #endif +struct tgsi_src_register; +struct tgsi_src_register_ext_swz; +struct tgsi_full_src_register; + void * tgsi_align_128bit( void *unaligned ); diff --git a/src/gallium/auxiliary/util/.gitignore b/src/gallium/auxiliary/util/.gitignore new file mode 100644 index 0000000000..29c586c9b5 --- /dev/null +++ b/src/gallium/auxiliary/util/.gitignore @@ -0,0 +1,2 @@ +u_format_access.c +u_format_table.c diff --git a/src/gallium/auxiliary/util/Makefile b/src/gallium/auxiliary/util/Makefile index 2995aba1b9..ae8d330a78 100644 --- a/src/gallium/auxiliary/util/Makefile +++ b/src/gallium/auxiliary/util/Makefile @@ -5,17 +5,22 @@ LIBNAME = util C_SOURCES = \ u_debug.c \ + u_debug_dump.c \ u_debug_symbol.c \ u_debug_stack.c \ u_blit.c \ u_cache.c \ u_draw_quad.c \ + u_format.c \ + u_format_access.c \ + u_format_table.c \ u_gen_mipmap.c \ u_handle_table.c \ u_hash_table.c \ u_hash.c \ u_keymap.c \ u_linear.c \ + u_network.c \ u_math.c \ u_mm.c \ u_rect.c \ @@ -31,3 +36,9 @@ C_SOURCES = \ u_simple_screen.c include ../../Makefile.template + +u_format_table.c: u_format_table.py u_format_parse.py u_format.csv + python u_format_table.py u_format.csv > $@ + +u_format_access.c: u_format_access.py u_format_parse.py u_format.csv + python u_format_access.py u_format.csv > $@ diff --git a/src/gallium/auxiliary/util/SConscript b/src/gallium/auxiliary/util/SConscript index d3ac7f747f..28a5ab4256 100644 --- a/src/gallium/auxiliary/util/SConscript +++ b/src/gallium/auxiliary/util/SConscript @@ -1,5 +1,23 @@ Import('*') +env.Clone() + +env.Append(CPPPATH = ['.']) + +env.CodeGenerate( + target = 'u_format_table.c', + script = 'u_format_table.py', + source = ['u_format.csv'], + command = 'python $SCRIPT $SOURCE > $TARGET' +) + +env.CodeGenerate( + target = 'u_format_access.c', + script = 'u_format_access.py', + source = ['u_format.csv'], + command = 'python $SCRIPT $SOURCE > $TARGET' +) + util = env.ConvenienceLibrary( target = 'util', source = [ @@ -7,16 +25,21 @@ util = env.ConvenienceLibrary( 'u_blit.c', 'u_cache.c', 'u_debug.c', + 'u_debug_dump.c', 'u_debug_memory.c', 'u_debug_profile.c', 'u_debug_stack.c', 'u_debug_symbol.c', 'u_draw_quad.c', + 'u_format.c', + 'u_format_access.c', + 'u_format_table.c', 'u_gen_mipmap.c', 'u_handle_table.c', 'u_hash.c', 'u_hash_table.c', 'u_keymap.c', + 'u_network.c', 'u_math.c', 'u_mm.c', 'u_rect.c', diff --git a/src/gallium/auxiliary/util/u_cache.c b/src/gallium/auxiliary/util/u_cache.c index 41cd38171f..47c16b1c92 100644 --- a/src/gallium/auxiliary/util/u_cache.c +++ b/src/gallium/auxiliary/util/u_cache.c @@ -137,6 +137,8 @@ util_cache_set(struct util_cache *cache, struct util_cache_entry *entry; assert(cache); + if (!cache) + return; entry = util_cache_entry_get(cache, key); util_cache_entry_destroy(cache, entry); @@ -158,6 +160,8 @@ util_cache_get(struct util_cache *cache, struct util_cache_entry *entry; assert(cache); + if (!cache) + return NULL; entry = util_cache_entry_get(cache, key); if(!entry->key && !entry->value) @@ -176,7 +180,9 @@ util_cache_clear(struct util_cache *cache) uint32_t i; assert(cache); - + if (!cache) + return; + for(i = 0; i < cache->size; ++i) util_cache_entry_destroy(cache, &cache->entries[i]); } @@ -186,6 +192,8 @@ void util_cache_destroy(struct util_cache *cache) { assert(cache); + if (!cache) + return; #ifdef DEBUG if(cache->count >= 20*cache->size) { diff --git a/src/gallium/auxiliary/util/u_debug.h b/src/gallium/auxiliary/util/u_debug.h index d42b65ce28..1380d98d7e 100644 --- a/src/gallium/auxiliary/util/u_debug.h +++ b/src/gallium/auxiliary/util/u_debug.h @@ -88,6 +88,7 @@ _debug_printf(const char *format, ...) * - avoid outputing large strings (512 bytes is the current maximum length * that is guaranteed to be printed in all platforms) */ +#if !defined(PIPE_OS_HAIKU) static INLINE void debug_printf(const char *format, ...) { @@ -101,6 +102,7 @@ debug_printf(const char *format, ...) #endif } +#endif /* !PIPE_OS_HAIKU */ /* * ... isn't portable so we need to pass arguments in parentheses. diff --git a/src/gallium/auxiliary/util/u_debug_dump.c b/src/gallium/auxiliary/util/u_debug_dump.c new file mode 100644 index 0000000000..6bdecde048 --- /dev/null +++ b/src/gallium/auxiliary/util/u_debug_dump.c @@ -0,0 +1,189 @@ +/************************************************************************** + * + * 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 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 ITS 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 "util/u_memory.h" +#include "util/u_debug.h" +#include "util/u_debug_dump.h" + + +#define DEBUG_DUMP_INVALID_NAME "<invalid>" + + +#if 0 +static const char * +debug_dump_strip_prefix(const char *name, + const char *prefix) +{ + const char *stripped; + assert(name); + assert(prefix); + stripped = name; + while(*prefix) { + if(*stripped != *prefix) + return name; + + ++stripped; + ++prefix; + } + return stripped; +} +#endif + +static const char * +debug_dump_enum_continuous(unsigned value, + unsigned num_names, + const char **names) +{ + if (value >= num_names) + return DEBUG_DUMP_INVALID_NAME; + return names[value]; +} + + +#define DEFINE_DEBUG_DUMP_CONTINUOUS(_name) \ + const char * \ + debug_dump_##_name(unsigned value, boolean shortened) \ + { \ + if(shortened) \ + return debug_dump_enum_continuous(value, Elements(debug_dump_##_name##_short_names), debug_dump_##_name##_short_names); \ + else \ + return debug_dump_enum_continuous(value, Elements(debug_dump_##_name##_names), debug_dump_##_name##_names); \ + } + + +static const char * +debug_dump_blend_factor_names[] = { + DEBUG_DUMP_INVALID_NAME, /* 0x0 */ + "PIPE_BLENDFACTOR_ONE", + "PIPE_BLENDFACTOR_SRC_COLOR", + "PIPE_BLENDFACTOR_SRC_ALPHA", + "PIPE_BLENDFACTOR_DST_ALPHA", + "PIPE_BLENDFACTOR_DST_COLOR", + "PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE", + "PIPE_BLENDFACTOR_CONST_COLOR", + "PIPE_BLENDFACTOR_CONST_ALPHA", + "PIPE_BLENDFACTOR_SRC1_COLOR", + "PIPE_BLENDFACTOR_SRC1_ALPHA", + DEBUG_DUMP_INVALID_NAME, /* 0x0b */ + DEBUG_DUMP_INVALID_NAME, /* 0x0c */ + DEBUG_DUMP_INVALID_NAME, /* 0x0d */ + DEBUG_DUMP_INVALID_NAME, /* 0x0e */ + DEBUG_DUMP_INVALID_NAME, /* 0x0f */ + DEBUG_DUMP_INVALID_NAME, /* 0x10 */ + "PIPE_BLENDFACTOR_ZERO", + "PIPE_BLENDFACTOR_INV_SRC_COLOR", + "PIPE_BLENDFACTOR_INV_SRC_ALPHA", + "PIPE_BLENDFACTOR_INV_DST_ALPHA", + "PIPE_BLENDFACTOR_INV_DST_COLOR", + DEBUG_DUMP_INVALID_NAME, /* 0x16 */ + "PIPE_BLENDFACTOR_INV_CONST_COLOR", + "PIPE_BLENDFACTOR_INV_CONST_ALPHA", + "PIPE_BLENDFACTOR_INV_SRC1_COLOR", + "PIPE_BLENDFACTOR_INV_SRC1_ALPHA" +}; + +static const char * +debug_dump_blend_factor_short_names[] = { + DEBUG_DUMP_INVALID_NAME, /* 0x0 */ + "one", + "src_color", + "src_alpha", + "dst_alpha", + "dst_color", + "src_alpha_saturate", + "const_color", + "const_alpha", + "src1_color", + "src1_alpha", + DEBUG_DUMP_INVALID_NAME, /* 0x0b */ + DEBUG_DUMP_INVALID_NAME, /* 0x0c */ + DEBUG_DUMP_INVALID_NAME, /* 0x0d */ + DEBUG_DUMP_INVALID_NAME, /* 0x0e */ + DEBUG_DUMP_INVALID_NAME, /* 0x0f */ + DEBUG_DUMP_INVALID_NAME, /* 0x10 */ + "zero", + "inv_src_color", + "inv_src_alpha", + "inv_dst_alpha", + "inv_dst_color", + DEBUG_DUMP_INVALID_NAME, /* 0x16 */ + "inv_const_color", + "inv_const_alpha", + "inv_src1_color", + "inv_src1_alpha" +}; + +DEFINE_DEBUG_DUMP_CONTINUOUS(blend_factor) + + +static const char * +debug_dump_blend_func_names[] = { + "PIPE_BLEND_ADD", + "PIPE_BLEND_SUBTRACT", + "PIPE_BLEND_REVERSE_SUBTRACT", + "PIPE_BLEND_MIN", + "PIPE_BLEND_MAX" +}; + +static const char * +debug_dump_blend_func_short_names[] = { + "add", + "sub", + "rev_sub", + "min", + "max" +}; + +DEFINE_DEBUG_DUMP_CONTINUOUS(blend_func) + + +static const char * +debug_dump_func_names[] = { + "PIPE_FUNC_NEVER", + "PIPE_FUNC_LESS", + "PIPE_FUNC_EQUAL", + "PIPE_FUNC_LEQUAL", + "PIPE_FUNC_GREATER", + "PIPE_FUNC_NOTEQUAL", + "PIPE_FUNC_GEQUAL", + "PIPE_FUNC_ALWAYS" +}; + +static const char * +debug_dump_func_short_names[] = { + "never", + "less", + "equal", + "less_equal", + "greater", + "not_equal", + "greater_equal", + "always" +}; + +DEFINE_DEBUG_DUMP_CONTINUOUS(func) diff --git a/src/gallium/auxiliary/util/u_debug_dump.h b/src/gallium/auxiliary/util/u_debug_dump.h new file mode 100644 index 0000000000..102935559c --- /dev/null +++ b/src/gallium/auxiliary/util/u_debug_dump.h @@ -0,0 +1,65 @@ +/************************************************************************** + * + * 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 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 ITS 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. + * + **************************************************************************/ + +/** + * @file + * Dump data in human/machine readable format. + * + * @author Jose Fonseca <jfonseca@vmware.com> + */ + +#ifndef U_DEBUG_DUMP_H_ +#define U_DEBUG_DUMP_H_ + + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + +const char * +debug_dump_blend_factor(unsigned value, boolean shortened); + +const char * +debug_dump_blend_func(unsigned value, boolean shortened); + +const char * +debug_dump_func(unsigned value, boolean shortened); + + +/* FIXME: Move the other debug_dump_xxx functions out of u_debug.h into here. */ + + +#ifdef __cplusplus +} +#endif + +#endif /* U_DEBUG_H_ */ diff --git a/src/gallium/auxiliary/util/u_format.c b/src/gallium/auxiliary/util/u_format.c new file mode 100644 index 0000000000..98ea13b60b --- /dev/null +++ b/src/gallium/auxiliary/util/u_format.c @@ -0,0 +1,46 @@ +/************************************************************************** + * + * 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 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 ITS 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_format.h" + + +const struct util_format_description * +util_format_description(enum pipe_format format) +{ + const struct util_format_description *desc = util_format_description_table; + + while(TRUE) { + if(desc->format == format) + return desc; + + if(desc->format == PIPE_FORMAT_NONE) + return NULL; + + ++desc; + }; +} diff --git a/src/gallium/auxiliary/util/u_format.csv b/src/gallium/auxiliary/util/u_format.csv new file mode 100644 index 0000000000..00a46d0cc4 --- /dev/null +++ b/src/gallium/auxiliary/util/u_format.csv @@ -0,0 +1,99 @@ +PIPE_FORMAT_A8R8G8B8_UNORM , arith , 1, 1, un8 , un8 , un8 , un8 , zyxw, rgb +PIPE_FORMAT_X8R8G8B8_UNORM , arith , 1, 1, un8 , un8 , un8 , un8 , zyx1, rgb +PIPE_FORMAT_B8G8R8A8_UNORM , arith , 1, 1, un8 , un8 , un8 , un8 , yzwx, rgb +PIPE_FORMAT_B8G8R8X8_UNORM , arith , 1, 1, un8 , un8 , un8 , un8 , yzw1, rgb +PIPE_FORMAT_A1R5G5B5_UNORM , arith , 1, 1, un1 , un5 , un5 , un5 , zyxw, rgb +PIPE_FORMAT_A4R4G4B4_UNORM , arith , 1, 1, un4 , un4 , un4 , un4 , zyxw, rgb +PIPE_FORMAT_R5G6B5_UNORM , arith , 1, 1, un5 , un6 , un5 , , zyx1, rgb +PIPE_FORMAT_A2B10G10R10_UNORM , arith , 1, 1, un10, un10, un10, un2 , xyzw, rgb +PIPE_FORMAT_L8_UNORM , arith , 1, 1, un8 , , , , xxx1, rgb +PIPE_FORMAT_A8_UNORM , arith , 1, 1, un8 , , , , 000x, rgb +PIPE_FORMAT_I8_UNORM , arith , 1, 1, un8 , , , , xxxx, rgb +PIPE_FORMAT_A8L8_UNORM , arith , 1, 1, un8 , un8 , , , xxxy, rgb +PIPE_FORMAT_L16_UNORM , arith , 1, 1, un16, , , , xxx1, rgb +PIPE_FORMAT_Z16_UNORM , array , 1, 1, un16, , , , x___, zs +PIPE_FORMAT_Z32_UNORM , array , 1, 1, un32, , , , x___, zs +PIPE_FORMAT_Z32_FLOAT , array , 1, 1, f32 , , , , x___, zs +PIPE_FORMAT_S8Z24_UNORM , arith , 1, 1, un8 , un24, , , yx__, zs +PIPE_FORMAT_Z24S8_UNORM , arith , 1, 1, un24, un8 , , , xy__, zs +PIPE_FORMAT_X8Z24_UNORM , arith , 1, 1, un8 , un24, , , y___, zs +PIPE_FORMAT_Z24X8_UNORM , arith , 1, 1, un24, un8 , , , x___, zs +PIPE_FORMAT_S8_UNORM , array , 1, 1, un8 , , , , _x__, zs +PIPE_FORMAT_R64_FLOAT , array , 1, 1, f64 , , , , x001, rgb +PIPE_FORMAT_R64G64_FLOAT , array , 1, 1, f64 , f64 , , , xy01, rgb +PIPE_FORMAT_R64G64B64_FLOAT , array , 1, 1, f64 , f64 , f64 , , xyz1, rgb +PIPE_FORMAT_R64G64B64A64_FLOAT , array , 1, 1, f64 , f64 , f64 , f64 , xyzw, rgb +PIPE_FORMAT_R32_FLOAT , array , 1, 1, f32 , , , , x001, rgb +PIPE_FORMAT_R32G32_FLOAT , array , 1, 1, f32 , f32 , , , xy01, rgb +PIPE_FORMAT_R32G32B32_FLOAT , array , 1, 1, f32 , f32 , f32 , , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_FLOAT , array , 1, 1, f32 , f32 , f32 , f32 , xyzw, rgb +PIPE_FORMAT_R32_UNORM , array , 1, 1, un32, , , , x001, rgb +PIPE_FORMAT_R32G32_UNORM , array , 1, 1, un32, un32, , , xy01, rgb +PIPE_FORMAT_R32G32B32_UNORM , array , 1, 1, un32, un32, un32, , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_UNORM , array , 1, 1, un32, un32, un32, un32, xyzw, rgb +PIPE_FORMAT_R32_USCALED , array , 1, 1, u32 , , , , x001, rgb +PIPE_FORMAT_R32G32_USCALED , array , 1, 1, u32 , u32 , , , xy01, rgb +PIPE_FORMAT_R32G32B32_USCALED , array , 1, 1, u32 , u32 , u32 , , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_USCALED , array , 1, 1, u32 , u32 , u32 , u32 , xyzw, rgb +PIPE_FORMAT_R32_SNORM , array , 1, 1, sn32, , , , x001, rgb +PIPE_FORMAT_R32G32_SNORM , array , 1, 1, sn32, sn32, , , xy01, rgb +PIPE_FORMAT_R32G32B32_SNORM , array , 1, 1, sn32, sn32, sn32, , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_SNORM , array , 1, 1, sn32, sn32, sn32, sn32, xyzw, rgb +PIPE_FORMAT_R32_SSCALED , array , 1, 1, s32 , , , , x001, rgb +PIPE_FORMAT_R32G32_SSCALED , array , 1, 1, s32 , s32 , , , xy01, rgb +PIPE_FORMAT_R32G32B32_SSCALED , array , 1, 1, s32 , s32 , s32 , , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_SSCALED , array , 1, 1, s32 , s32 , s32 , s32 , xyzw, rgb +PIPE_FORMAT_R16_UNORM , array , 1, 1, un16, , , , x001, rgb +PIPE_FORMAT_R16G16_UNORM , array , 1, 1, un16, un16, , , xy01, rgb +PIPE_FORMAT_R16G16B16_UNORM , array , 1, 1, un16, un16, un16, , xyz1, rgb +PIPE_FORMAT_R16G16B16A16_UNORM , array , 1, 1, un16, un16, un16, un16, xyzw, rgb +PIPE_FORMAT_R16_USCALED , array , 1, 1, u16 , , , , x001, rgb +PIPE_FORMAT_R16G16_USCALED , array , 1, 1, u16 , u16 , , , xy01, rgb +PIPE_FORMAT_R16G16B16_USCALED , array , 1, 1, u16 , u16 , u16 , , xyz1, rgb +PIPE_FORMAT_R16G16B16A16_USCALED , array , 1, 1, u16 , u16 , u16 , u16 , xyzw, rgb +PIPE_FORMAT_R16_SNORM , array , 1, 1, sn16, , , , x001, rgb +PIPE_FORMAT_R16G16_SNORM , array , 1, 1, sn16, sn16, , , xy01, rgb +PIPE_FORMAT_R16G16B16_SNORM , array , 1, 1, sn16, sn16, sn16, , xyz1, rgb +PIPE_FORMAT_R16G16B16A16_SNORM , array , 1, 1, sn16, sn16, sn16, sn16, xyzw, rgb +PIPE_FORMAT_R16_SSCALED , array , 1, 1, s16 , , , , x001, rgb +PIPE_FORMAT_R16G16_SSCALED , array , 1, 1, s16 , s16 , , , xy01, rgb +PIPE_FORMAT_R16G16B16_SSCALED , array , 1, 1, s16 , s16 , s16 , , xyz1, rgb +PIPE_FORMAT_R16G16B16A16_SSCALED , array , 1, 1, s16 , s16 , s16 , s16 , xyzw, rgb +PIPE_FORMAT_R8_UNORM , array , 1, 1, un8 , , , , x001, rgb +PIPE_FORMAT_R8G8_UNORM , array , 1, 1, un8 , un8 , , , xy01, rgb +PIPE_FORMAT_R8G8B8_UNORM , array , 1, 1, un8 , un8 , un8 , , xyz1, rgb +PIPE_FORMAT_R8G8B8A8_UNORM , array , 1, 1, un8 , un8 , un8 , un8 , xyzw, rgb +PIPE_FORMAT_R8G8B8X8_UNORM , array , 1, 1, un8 , un8 , un8 , un8 , xyz1, rgb +PIPE_FORMAT_R8_USCALED , array , 1, 1, u8 , , , , x001, rgb +PIPE_FORMAT_R8G8_USCALED , array , 1, 1, u8 , u8 , , , xy01, rgb +PIPE_FORMAT_R8G8B8_USCALED , array , 1, 1, u8 , u8 , u8 , , xyz1, rgb +PIPE_FORMAT_R8G8B8A8_USCALED , array , 1, 1, u8 , u8 , u8 , u8 , xyzw, rgb +PIPE_FORMAT_R8G8B8X8_USCALED , array , 1, 1, u8 , u8 , u8 , u8 , xyz1, rgb +PIPE_FORMAT_R8_SNORM , array , 1, 1, sn8 , , , , x001, rgb +PIPE_FORMAT_R8G8_SNORM , array , 1, 1, sn8 , sn8 , , , xy01, rgb +PIPE_FORMAT_R8G8B8_SNORM , array , 1, 1, sn8 , sn8 , sn8 , , xyz1, rgb +PIPE_FORMAT_R8G8B8A8_SNORM , array , 1, 1, sn8 , sn8 , sn8 , sn8 , xyzw, rgb +PIPE_FORMAT_R8G8B8X8_SNORM , array , 1, 1, sn8 , sn8 , sn8 , sn8 , xyz1, rgb +PIPE_FORMAT_B6G5R5_SNORM , arith , 1, 1, sn5 , sn5 , sn6 , , zyx1, rgb +PIPE_FORMAT_A8B8G8R8_SNORM , arith , 1, 1, sn8 , sn8 , sn8 , sn8 , zyxw, rgb +PIPE_FORMAT_X8B8G8R8_SNORM , arith , 1, 1, sn8 , sn8 , sn8 , sn8 , zyx1, rgb +PIPE_FORMAT_R8_SSCALED , array , 1, 1, s8 , , , , x001, rgb +PIPE_FORMAT_R8G8_SSCALED , array , 1, 1, s8 , s8 , , , xy01, rgb +PIPE_FORMAT_R8G8B8_SSCALED , array , 1, 1, s8 , s8 , s8 , , xyz1, rgb +PIPE_FORMAT_R8G8B8A8_SSCALED , array , 1, 1, s8 , s8 , s8 , s8 , xyzw, rgb +PIPE_FORMAT_R8G8B8X8_SSCALED , array , 1, 1, s8 , s8 , s8 , s8 , xyz1, rgb +PIPE_FORMAT_R32_FIXED , array , 1, 1, h32 , , , , x001, rgb +PIPE_FORMAT_R32G32_FIXED , array , 1, 1, h32 , h32 , , , xy01, rgb +PIPE_FORMAT_R32G32B32_FIXED , array , 1, 1, h32 , h32 , h32 , , xyz1, rgb +PIPE_FORMAT_R32G32B32A32_FIXED , array , 1, 1, h32 , h32 , h32 , h32 , xyzw, rgb +PIPE_FORMAT_L8_SRGB , arith , 1, 1, u8 , , , , xxx1, srgb +PIPE_FORMAT_A8L8_SRGB , arith , 1, 1, u8 , u8 , , , xxxy, srgb +PIPE_FORMAT_R8G8B8_SRGB , arith , 1, 1, u8 , u8 , u8 , , xyz1, srgb +PIPE_FORMAT_R8G8B8A8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , xyzw, srgb +PIPE_FORMAT_R8G8B8X8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , xyz1, srgb +PIPE_FORMAT_A8R8G8B8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , wxyz, srgb +PIPE_FORMAT_X8R8G8B8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , 1xyz, srgb +PIPE_FORMAT_B8G8R8A8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , zyxw, srgb +PIPE_FORMAT_B8G8R8X8_SRGB , arith , 1, 1, u8 , u8 , u8 , u8 , zyx1, srgb +PIPE_FORMAT_X8UB8UG8SR8S_NORM , arith , 1, 1, sn8 , sn8 , un8 , x8 , 1zyx, rgb +PIPE_FORMAT_B6UG5SR5S_NORM , arith , 1, 1, sn5 , sn5 , un6 , , xyz1, rgb diff --git a/src/gallium/auxiliary/util/u_format.h b/src/gallium/auxiliary/util/u_format.h new file mode 100644 index 0000000000..7b5b7fcda5 --- /dev/null +++ b/src/gallium/auxiliary/util/u_format.h @@ -0,0 +1,138 @@ +/************************************************************************** + * + * 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 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 ITS 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_FORMAT_H +#define U_FORMAT_H + + +#include "pipe/p_format.h" + + +enum util_format_layout { + UTIL_FORMAT_LAYOUT_SCALAR = 0, + UTIL_FORMAT_LAYOUT_ARITH = 1, + UTIL_FORMAT_LAYOUT_ARRAY = 2, + UTIL_FORMAT_LAYOUT_YUV = 3, + UTIL_FORMAT_LAYOUT_DXT = 4 +}; + + +struct util_format_block +{ + /** Block width in pixels */ + unsigned width; + + /** Block height in pixels */ + unsigned height; + + /** Block size in bytes */ + unsigned bits; +}; + + +enum util_format_type { + UTIL_FORMAT_TYPE_VOID = 0, + UTIL_FORMAT_TYPE_UNSIGNED = 1, + UTIL_FORMAT_TYPE_SIGNED = 2, + UTIL_FORMAT_TYPE_FIXED = 3, + UTIL_FORMAT_TYPE_FLOAT = 4 +}; + + +enum util_format_swizzle { + UTIL_FORMAT_SWIZZLE_X = 0, + UTIL_FORMAT_SWIZZLE_Y = 1, + UTIL_FORMAT_SWIZZLE_Z = 2, + UTIL_FORMAT_SWIZZLE_W = 3, + UTIL_FORMAT_SWIZZLE_0 = 4, + UTIL_FORMAT_SWIZZLE_1 = 5, + UTIL_FORMAT_SWIZZLE_NONE = 6 +}; + + +enum util_format_colorspace { + UTIL_FORMAT_COLORSPACE_RGB = 0, + UTIL_FORMAT_COLORSPACE_SRGB = 1, + UTIL_FORMAT_COLORSPACE_YUV = 2, + UTIL_FORMAT_COLORSPACE_ZS = 3, +}; + + +struct util_format_channel_description +{ + unsigned type:6; + unsigned normalized:1; + unsigned size:9; +}; + + +struct util_format_description +{ + enum pipe_format format; + const char *name; + struct util_format_block block; + enum util_format_layout layout; + struct util_format_channel_description channel[4]; + unsigned char swizzle[4]; + enum util_format_colorspace colorspace; +}; + + +extern const struct util_format_description +util_format_description_table[]; + + +const struct util_format_description * +util_format_description(enum pipe_format format); + + +void +util_format_read_4f(enum pipe_format format, + float *dst, unsigned dst_stride, + const void *src, unsigned src_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_write_4f(enum pipe_format format, + const float *src, unsigned src_stride, + void *dst, unsigned dst_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_read_4ub(enum pipe_format format, + uint8_t *dst, unsigned dst_stride, + const void *src, unsigned src_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +void +util_format_write_4ub(enum pipe_format format, + const uint8_t *src, unsigned src_stride, + void *dst, unsigned dst_stride, + unsigned x, unsigned y, unsigned w, unsigned h); + +#endif /* ! U_FORMAT_H */ diff --git a/src/gallium/auxiliary/util/u_format_access.py b/src/gallium/auxiliary/util/u_format_access.py new file mode 100644 index 0000000000..eeb1a9657f --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_access.py @@ -0,0 +1,498 @@ +#!/usr/bin/env python + +''' +/************************************************************************** + * + * 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 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 ITS 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. + * + **************************************************************************/ + +/** + * @file + * Pixel format accessor functions. + * + * @author Jose Fonseca <jfonseca@vmware.com> + */ +''' + + +import sys + +from u_format_parse import * + + +def short_name(format): + '''Make up a short norm for a format, suitable to be used as suffix in + function names.''' + + name = format.name + if name.startswith('PIPE_FORMAT_'): + name = name[len('PIPE_FORMAT_'):] + name = name.lower() + return name + + +def is_format_supported(format): + '''Determines whether we actually have the plumbing necessary to generate the + to read/write to/from this format.''' + + # FIXME: Ideally we would support any format combination here. + + # XXX: It should be straightforward to support srgb + if format.colorspace not in ('rgb', 'zs'): + return False + + if format.layout not in (ARITH, ARRAY): + return False + + for i in range(4): + type = format.in_types[i] + if type.kind not in (VOID, UNSIGNED, FLOAT): + return False + + # We can only read a color from a depth/stencil format if the depth channel is present + if format.colorspace == 'zs' and format.out_swizzle[0] == SWIZZLE_NONE: + return False + + return True + + +def native_type(format): + '''Get the native appropriate for a format.''' + + if format.layout == ARITH: + # For arithmetic pixel formats return the integer type that matches the whole pixel + return 'uint%u_t' % format.block_size() + elif format.layout == ARRAY: + # For array pixel formats return the integer type that matches the color channel + type = format.in_types[0] + if type.kind == UNSIGNED: + return 'uint%u_t' % type.size + elif type.kind == SIGNED: + return 'int%u_t' % type.size + elif type.kind == FLOAT: + if type.size == 32: + return 'float' + elif type.size == 64: + return 'double' + else: + assert False + else: + assert False + else: + assert False + + +def intermediate_native_type(bits, sign): + '''Find a native type adequate to hold intermediate results of the request bit size.''' + + bytes = 4 # don't use anything smaller than 32bits + while bytes * 8 < bits: + bytes *= 2 + bits = bytes*8 + + if sign: + return 'int%u_t' % bits + else: + return 'uint%u_t' % bits + + +def get_one_shift(type): + '''Get the number of the bit that matches unity for this type.''' + if type.kind == 'FLOAT': + assert False + if not type.norm: + return 0 + if type.kind == UNSIGNED: + return type.size + if type.kind == SIGNED: + return type.size - 1 + if type.kind == FIXED: + return type.size / 2 + assert False + + +def get_one(type): + '''Get the value of unity for this type.''' + if type.kind == 'FLOAT' or not type.norm: + return 1 + else: + return (1 << get_one_shift(type)) - 1 + + +def generate_clamp(): + '''Code generate the clamping functions for each type. + + We don't use a macro so that arguments with side effects, + like *src_pixel++ are correctly handled. + ''' + + for suffix, native_type in [ + ('', 'double'), + ('f', 'float'), + ('ui', 'unsigned int'), + ('si', 'int'), + ]: + print 'static INLINE %s' % native_type + print 'clamp%s(%s value, %s lbound, %s ubound)' % (suffix, native_type, native_type, native_type) + print '{' + print ' if(value < lbound)' + print ' return lbound;' + print ' if(value > ubound)' + print ' return ubound;' + print ' return value;' + print '}' + print + + +def clamp_expr(src_type, dst_type, dst_native_type, value): + '''Generate the expression to clamp the value in the source type to the + destination type range.''' + + if src_type == dst_type: + return value + + # Pick the approriate clamp function + if src_type.kind == FLOAT: + if src_type.size == 32: + func = 'clampf' + elif src_type.size == 64: + func = 'clamp' + else: + assert False + elif src_type.kind == UNSIGNED: + func = 'clampui' + elif src_type.kind == SIGNED: + func = 'clampsi' + else: + assert False + + # Clamp floats to [-1, 1] or [0, 1] range + if src_type.kind == FLOAT and dst_type.norm: + max = 1 + if src_type.sign and dst_type.sign: + min = -1 + else: + min = 0 + return '%s(%s, %s, %s)' % (func, value, min, max) + + # FIXME: Also clamp scaled values + + return value + + +def conversion_expr(src_type, dst_type, dst_native_type, value): + '''Generate the expression to convert a value between two types.''' + + if src_type == dst_type: + return value + + if src_type.kind == FLOAT and dst_type.kind == FLOAT: + return '(%s)%s' % (dst_native_type, value) + + if not src_type.norm and not dst_type.norm: + return '(%s)%s' % (dst_native_type, value) + + value = clamp_expr(src_type, dst_type, dst_native_type, value) + + if dst_type.kind == FLOAT: + if src_type.norm: + one = get_one(src_type) + if src_type.size <= 23: + scale = '(1.0f/0x%x)' % one + else: + # bigger than single precision mantissa, use double + scale = '(1.0/0x%x)' % one + value = '(%s * %s)' % (value, scale) + return '(%s)%s' % (dst_native_type, value) + + if src_type.kind == FLOAT: + if dst_type.norm: + dst_one = get_one(dst_type) + if dst_type.size <= 23: + scale = '0x%x' % dst_one + else: + # bigger than single precision mantissa, use double + scale = '(double)0x%x' % dst_one + value = '(%s * %s)' % (value, scale) + return '(%s)%s' % (dst_native_type, value) + + if src_type.kind == dst_type.kind: + src_one = get_one(src_type) + dst_one = get_one(dst_type) + + if src_one > dst_one and src_type.norm and dst_type.norm: + # We can just bitshift + src_shift = get_one_shift(src_type) + dst_shift = get_one_shift(dst_type) + value = '(%s >> %s)' % (value, src_shift - dst_shift) + else: + # We need to rescale using an intermediate type big enough to hold the multiplication of both + tmp_native_type = intermediate_native_type(src_type.size + dst_type.size, src_type.sign and dst_type.sign) + value = '(%s)%s' % (tmp_native_type, value) + value = '%s * 0x%x / 0x%x' % (value, dst_one, src_one) + value = '(%s)%s' % (dst_native_type, value) + return value + + assert False + + +def generate_format_read(format, dst_type, dst_native_type, dst_suffix): + '''Generate the function to read pixels from a particular format''' + + name = short_name(format) + + src_native_type = native_type(format) + + print 'static void' + print 'util_format_%s_read_%s(%s *dst, unsigned dst_stride, const uint8_t *src, unsigned src_stride, unsigned x0, unsigned y0, unsigned w, unsigned h)' % (name, dst_suffix, dst_native_type) + print '{' + print ' unsigned x, y;' + print ' const uint8_t *src_row = src + y0*src_stride;' + print ' %s *dst_row = dst;' % dst_native_type + print ' for (y = 0; y < h; ++y) {' + print ' const %s *src_pixel = (const %s *)(src_row + x0*%u);' % (src_native_type, src_native_type, format.stride()) + print ' %s *dst_pixel = dst_row;' %dst_native_type + print ' for (x = 0; x < w; ++x) {' + + names = ['']*4 + if format.colorspace == 'rgb': + for i in range(4): + swizzle = format.out_swizzle[i] + if swizzle < 4: + names[swizzle] += 'rgba'[i] + elif format.colorspace == 'zs': + swizzle = format.out_swizzle[0] + if swizzle < 4: + names[swizzle] = 'z' + else: + assert False + else: + assert False + + if format.layout == ARITH: + print ' %s pixel = *src_pixel++;' % src_native_type + shift = 0; + for i in range(4): + src_type = format.in_types[i] + width = src_type.size + if names[i]: + value = 'pixel' + mask = (1 << width) - 1 + if shift: + value = '(%s >> %u)' % (value, shift) + if shift + width < format.block_size(): + value = '(%s & 0x%x)' % (value, mask) + value = conversion_expr(src_type, dst_type, dst_native_type, value) + print ' %s %s = %s;' % (dst_native_type, names[i], value) + shift += width + elif format.layout == ARRAY: + for i in range(4): + src_type = format.in_types[i] + if names[i]: + value = '(*src_pixel++)' + value = conversion_expr(src_type, dst_type, dst_native_type, value) + print ' %s %s = %s;' % (dst_native_type, names[i], value) + else: + assert False + + for i in range(4): + if format.colorspace == 'rgb': + swizzle = format.out_swizzle[i] + if swizzle < 4: + value = names[swizzle] + elif swizzle == SWIZZLE_0: + value = '0' + elif swizzle == SWIZZLE_1: + value = '1' + else: + assert False + elif format.colorspace == 'zs': + if i < 3: + value = 'z' + else: + value = '1' + else: + assert False + print ' *dst_pixel++ = %s; /* %s */' % (value, 'rgba'[i]) + + print ' }' + print ' src_row += src_stride;' + print ' dst_row += dst_stride/sizeof(%s);' % dst_native_type + print ' }' + print '}' + print + + +def generate_format_write(format, src_type, src_native_type, src_suffix): + '''Generate the function to write pixels to a particular format''' + + name = short_name(format) + + dst_native_type = native_type(format) + + print 'static void' + print 'util_format_%s_write_%s(const %s *src, unsigned src_stride, uint8_t *dst, unsigned dst_stride, unsigned x0, unsigned y0, unsigned w, unsigned h)' % (name, src_suffix, src_native_type) + print '{' + print ' unsigned x, y;' + print ' uint8_t *dst_row = dst + y0*dst_stride;' + print ' const %s *src_row = src;' % src_native_type + print ' for (y = 0; y < h; ++y) {' + print ' %s *dst_pixel = (%s *)(dst_row + x0*%u);' % (dst_native_type, dst_native_type, format.stride()) + print ' const %s *src_pixel = src_row;' %src_native_type + print ' for (x = 0; x < w; ++x) {' + + inv_swizzle = [None]*4 + if format.colorspace == 'rgb': + for i in range(4): + swizzle = format.out_swizzle[i] + if swizzle < 4: + inv_swizzle[swizzle] = i + elif format.colorspace == 'zs': + swizzle = format.out_swizzle[0] + if swizzle < 4: + inv_swizzle[swizzle] = 0 + else: + assert False + + if format.layout == ARITH: + print ' %s pixel = 0;' % dst_native_type + shift = 0; + for i in range(4): + dst_type = format.in_types[i] + width = dst_type.size + if inv_swizzle[i] is not None: + value = 'src_pixel[%u]' % inv_swizzle[i] + value = conversion_expr(src_type, dst_type, dst_native_type, value) + if shift: + value = '(%s << %u)' % (value, shift) + print ' pixel |= %s;' % value + shift += width + print ' *dst_pixel++ = pixel;' + elif format.layout == ARRAY: + for i in range(4): + dst_type = format.in_types[i] + if inv_swizzle[i] is not None: + value = 'src_pixel[%u]' % inv_swizzle[i] + value = conversion_expr(src_type, dst_type, dst_native_type, value) + print ' *dst_pixel++ = %s;' % value + else: + assert False + print ' src_pixel += 4;' + + print ' }' + print ' dst_row += dst_stride;' + print ' src_row += src_stride/sizeof(%s);' % src_native_type + print ' }' + print '}' + print + + +def generate_read(formats, dst_type, dst_native_type, dst_suffix): + '''Generate the dispatch function to read pixels from any format''' + + for format in formats: + if is_format_supported(format): + generate_format_read(format, dst_type, dst_native_type, dst_suffix) + + print 'void' + print 'util_format_read_%s(enum pipe_format format, %s *dst, unsigned dst_stride, const void *src, unsigned src_stride, unsigned x, unsigned y, unsigned w, unsigned h)' % (dst_suffix, dst_native_type) + print '{' + print ' void (*func)(%s *dst, unsigned dst_stride, const uint8_t *src, unsigned src_stride, unsigned x0, unsigned y0, unsigned w, unsigned h);' % dst_native_type + print ' switch(format) {' + for format in formats: + if is_format_supported(format): + print ' case %s:' % format.name + print ' func = &util_format_%s_read_%s;' % (short_name(format), dst_suffix) + print ' break;' + print ' default:' + print ' debug_printf("unsupported format\\n");' + print ' return;' + print ' }' + print ' func(dst, dst_stride, (const uint8_t *)src, src_stride, x, y, w, h);' + print '}' + print + + +def generate_write(formats, src_type, src_native_type, src_suffix): + '''Generate the dispatch function to write pixels to any format''' + + for format in formats: + if is_format_supported(format): + generate_format_write(format, src_type, src_native_type, src_suffix) + + print 'void' + print 'util_format_write_%s(enum pipe_format format, const %s *src, unsigned src_stride, void *dst, unsigned dst_stride, unsigned x, unsigned y, unsigned w, unsigned h)' % (src_suffix, src_native_type) + + print '{' + print ' void (*func)(const %s *src, unsigned src_stride, uint8_t *dst, unsigned dst_stride, unsigned x0, unsigned y0, unsigned w, unsigned h);' % src_native_type + print ' switch(format) {' + for format in formats: + if is_format_supported(format): + print ' case %s:' % format.name + print ' func = &util_format_%s_write_%s;' % (short_name(format), src_suffix) + print ' break;' + print ' default:' + print ' debug_printf("unsupported format\\n");' + print ' return;' + print ' }' + print ' func(src, src_stride, (uint8_t *)dst, dst_stride, x, y, w, h);' + print '}' + print + + +def main(): + formats = [] + for arg in sys.argv[1:]: + formats.extend(parse(arg)) + + print '/* This file is autogenerated by u_format_access.py from u_format.csv. Do not edit directly. */' + print + # This will print the copyright message on the top of this file + print __doc__.strip() + print + print '#include "pipe/p_compiler.h"' + print '#include "u_format.h"' + print '#include "u_math.h"' + print + + generate_clamp() + + type = Type(FLOAT, False, 32) + native_type = 'float' + suffix = '4f' + + generate_read(formats, type, native_type, suffix) + generate_write(formats, type, native_type, suffix) + + type = Type(UNSIGNED, True, 8) + native_type = 'uint8_t' + suffix = '4ub' + + generate_read(formats, type, native_type, suffix) + generate_write(formats, type, native_type, suffix) + + +if __name__ == '__main__': + main() diff --git a/src/gallium/auxiliary/util/u_format_parse.py b/src/gallium/auxiliary/util/u_format_parse.py new file mode 100755 index 0000000000..493aff7112 --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_parse.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python + +''' +/************************************************************************** + * + * 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 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 ITS 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. + * + **************************************************************************/ +''' + + +import sys + + +VOID, UNSIGNED, SIGNED, FIXED, FLOAT = range(5) + +SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_0, SWIZZLE_1, SWIZZLE_NONE, = range(7) + +ARITH = 'arith' +ARRAY = 'array' + + +class Type: + '''Describe the type of a color channel.''' + + def __init__(self, kind, norm, size): + self.kind = kind + self.norm = norm + self.size = size + self.sign = kind in (SIGNED, FIXED, FLOAT) + + def __str__(self): + s = str(self.kind) + if self.norm: + s += 'n' + s += str(self.size) + return s + + def __eq__(self, other): + return self.kind == other.kind and self.norm == other.norm and self.size == other.size + + +class Format: + '''Describe a pixel format.''' + + def __init__(self, name, layout, block_width, block_height, in_types, out_swizzle, colorspace): + self.name = name + self.layout = layout + self.block_width = block_width + self.block_height = block_height + self.in_types = in_types + self.out_swizzle = out_swizzle + self.name = name + self.colorspace = colorspace + + def __str__(self): + return self.name + + def block_size(self): + size = 0 + for type in self.in_types: + size += type.size + return size + + def stride(self): + return self.block_size()/8 + + +_kind_parse_map = { + '': VOID, + 'x': VOID, + 'u': UNSIGNED, + 's': SIGNED, + 'h': FIXED, + 'f': FLOAT, +} + +_swizzle_parse_map = { + 'x': SWIZZLE_X, + 'y': SWIZZLE_Y, + 'z': SWIZZLE_Z, + 'w': SWIZZLE_W, + '0': SWIZZLE_0, + '1': SWIZZLE_1, + '_': SWIZZLE_NONE, +} + +def parse(filename): + '''Parse the format descrition in CSV format in terms of the + Type and Format classes above.''' + + stream = open(filename) + formats = [] + for line in stream: + line = line.rstrip() + fields = [field.strip() for field in line.split(',')] + name = fields[0] + layout = fields[1] + block_width, block_height = map(int, fields[2:4]) + in_types = [] + for field in fields[4:8]: + if field: + kind = _kind_parse_map[field[0]] + if field[1] == 'n': + norm = True + size = int(field[2:]) + else: + norm = False + size = int(field[1:]) + else: + kind = VOID + norm = False + size = 0 + in_type = Type(kind, norm, size) + in_types.append(in_type) + out_swizzle = [_swizzle_parse_map[swizzle] for swizzle in fields[8]] + colorspace = fields[9] + formats.append(Format(name, layout, block_width, block_height, in_types, out_swizzle, colorspace)) + return formats + diff --git a/src/gallium/auxiliary/util/u_format_table.py b/src/gallium/auxiliary/util/u_format_table.py new file mode 100755 index 0000000000..8834568e8e --- /dev/null +++ b/src/gallium/auxiliary/util/u_format_table.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python + +''' +/************************************************************************** + * + * 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 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 ITS 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. + * + **************************************************************************/ +''' + + +import sys + +from u_format_parse import * + + +def layout_map(layout): + return 'UTIL_FORMAT_LAYOUT_' + str(layout).upper() + + +def colorspace_map(colorspace): + return 'UTIL_FORMAT_COLORSPACE_' + str(colorspace).upper() + + +colorspace_channels_map = { + 'rgb': 'rgba', + 'rgba': 'rgba', + 'zs': 'zs', + 'yuv': ['y1', 'y2', 'u', 'v'], + 'dxt': [] +} + + +kind_map = { + VOID: "UTIL_FORMAT_TYPE_VOID", + UNSIGNED: "UTIL_FORMAT_TYPE_UNSIGNED", + SIGNED: "UTIL_FORMAT_TYPE_SIGNED", + FIXED: "UTIL_FORMAT_TYPE_FIXED", + FLOAT: "UTIL_FORMAT_TYPE_FLOAT", +} + + +def bool_map(value): + if value: + return "TRUE" + else: + return "FALSE" + + +swizzle_map = { + SWIZZLE_X: "UTIL_FORMAT_SWIZZLE_X", + SWIZZLE_Y: "UTIL_FORMAT_SWIZZLE_Y", + SWIZZLE_Z: "UTIL_FORMAT_SWIZZLE_Z", + SWIZZLE_W: "UTIL_FORMAT_SWIZZLE_W", + SWIZZLE_0: "UTIL_FORMAT_SWIZZLE_0", + SWIZZLE_1: "UTIL_FORMAT_SWIZZLE_1", + SWIZZLE_NONE: "UTIL_FORMAT_SWIZZLE_NONE", +} + + +def write_format_table(formats): + print '/* This file is autogenerated by u_format_table.py from u_format.csv. Do not edit directly. */' + print + # This will print the copyright message on the top of this file + print __doc__.strip() + print + print '#include "u_format.h"' + print + print 'const struct util_format_description' + print 'util_format_description_table[] = ' + print "{" + for format in formats: + print " {" + print " %s," % (format.name,) + print " \"%s\"," % (format.name,) + print " {%u, %u, %u}, /* block */" % (format.block_width, format.block_height, format.block_size()) + print " %s," % (layout_map(format.layout),) + print " {" + for i in range(4): + type = format.in_types[i] + if i < 3: + sep = "," + else: + sep = "" + print " {%s, %s, %u}%s /* %s */" % (kind_map[type.kind], bool_map(type.norm), type.size, sep, "xyzw"[i]) + print " }," + print " {" + for i in range(4): + swizzle = format.out_swizzle[i] + if i < 3: + sep = "," + else: + sep = "" + try: + comment = layout_channels_map[format.layout][i] + except: + comment = 'ignored' + print " %s%s /* %s */" % (swizzle_map[swizzle], sep, comment) + print " }," + print " %s," % (colorspace_map(format.colorspace),) + print " }," + print " {" + print " PIPE_FORMAT_NONE," + print " \"PIPE_FORMAT_NONE\"," + print " {0, 0, 0}," + print " 0," + print " {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}," + print " {0, 0, 0, 0}," + print " 0" + print " }," + print "};" + + +def main(): + + formats = [] + for arg in sys.argv[1:]: + formats.extend(parse(arg)) + write_format_table(formats) + + +if __name__ == '__main__': + main() diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c index 833c0b8338..f06c0e463d 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -46,10 +46,6 @@ #include "util/u_gen_mipmap.h" #include "util/u_simple_shaders.h" -#include "tgsi/tgsi_build.h" -#include "tgsi/tgsi_dump.h" -#include "tgsi/tgsi_parse.h" - #include "cso_cache/cso_context.h" diff --git a/src/gallium/auxiliary/util/u_handle_table.c b/src/gallium/auxiliary/util/u_handle_table.c index 6da7353e25..3703718a62 100644 --- a/src/gallium/auxiliary/util/u_handle_table.c +++ b/src/gallium/auxiliary/util/u_handle_table.c @@ -87,6 +87,8 @@ handle_table_set_destroy(struct handle_table *ht, void (*destroy)(void *object)) { assert(ht); + if (!ht) + return; ht->destroy = destroy; } @@ -155,7 +157,7 @@ handle_table_add(struct handle_table *ht, assert(ht); assert(object); - if(!object) + if(!object || !ht) return 0; /* linear search for an empty handle */ @@ -193,7 +195,7 @@ handle_table_set(struct handle_table *ht, assert(ht); assert(handle); - if(!handle) + if(!handle || !ht) return 0; assert(object); @@ -222,7 +224,7 @@ handle_table_get(struct handle_table *ht, assert(ht); assert(handle); - if(!handle || handle > ht->size) + if(!handle || !ht || handle > ht->size) return NULL; object = ht->objects[handle - 1]; @@ -240,7 +242,7 @@ handle_table_remove(struct handle_table *ht, assert(ht); assert(handle); - if(!handle || handle > ht->size) + if(!handle || !ht || handle > ht->size) return; index = handle - 1; @@ -283,6 +285,9 @@ handle_table_destroy(struct handle_table *ht) unsigned index; assert(ht); + if (!ht) + return; + if(ht->destroy) for(index = 0; index < ht->size; ++index) handle_table_clear(ht, index); diff --git a/src/gallium/auxiliary/util/u_hash_table.c b/src/gallium/auxiliary/util/u_hash_table.c index 2f83e318e4..8c2a8f454c 100644 --- a/src/gallium/auxiliary/util/u_hash_table.c +++ b/src/gallium/auxiliary/util/u_hash_table.c @@ -148,6 +148,8 @@ hash_table_set(struct hash_table *ht, struct cso_hash_iter iter; assert(ht); + if (!ht) + return PIPE_ERROR_BAD_INPUT; key_hash = ht->hash(key); @@ -183,6 +185,8 @@ hash_table_get(struct hash_table *ht, struct hash_table_item *item; assert(ht); + if (!ht) + return NULL; key_hash = ht->hash(key); @@ -203,6 +207,8 @@ hash_table_remove(struct hash_table *ht, struct hash_table_item *item; assert(ht); + if (!ht) + return; key_hash = ht->hash(key); @@ -225,7 +231,9 @@ hash_table_clear(struct hash_table *ht) struct hash_table_item *item; assert(ht); - + if (!ht) + return; + iter = cso_hash_first_node(ht->cso); while (!cso_hash_iter_is_null(iter)) { item = (struct hash_table_item *)cso_hash_take(ht->cso, cso_hash_iter_key(iter)); @@ -243,9 +251,11 @@ hash_table_foreach(struct hash_table *ht, struct cso_hash_iter iter; struct hash_table_item *item; enum pipe_error result; - + assert(ht); - + if (!ht) + return PIPE_ERROR_BAD_INPUT; + iter = cso_hash_first_node(ht->cso); while (!cso_hash_iter_is_null(iter)) { item = (struct hash_table_item *)cso_hash_iter_data(iter); @@ -264,9 +274,11 @@ hash_table_destroy(struct hash_table *ht) { struct cso_hash_iter iter; struct hash_table_item *item; - + assert(ht); - + if (!ht) + return; + iter = cso_hash_first_node(ht->cso); while (!cso_hash_iter_is_null(iter)) { item = (struct hash_table_item *)cso_hash_iter_data(iter); diff --git a/src/gallium/auxiliary/util/u_keymap.c b/src/gallium/auxiliary/util/u_keymap.c index 3f70809efd..508a2ee063 100644 --- a/src/gallium/auxiliary/util/u_keymap.c +++ b/src/gallium/auxiliary/util/u_keymap.c @@ -194,6 +194,8 @@ util_keymap_insert(struct keymap *map, const void *key, struct cso_hash_iter iter; assert(map); + if (!map) + return FALSE; key_hash = hash(key, map->key_size); @@ -234,6 +236,8 @@ util_keymap_lookup(const struct keymap *map, const void *key) struct keymap_item *item; assert(map); + if (!map) + return NULL; key_hash = hash(key, map->key_size); @@ -258,6 +262,8 @@ util_keymap_remove(struct keymap *map, const void *key, void *user) struct keymap_item *item; assert(map); + if (!map) + return; key_hash = hash(key, map->key_size); @@ -267,6 +273,8 @@ util_keymap_remove(struct keymap *map, const void *key, void *user) item = hash_table_item(iter); assert(item); + if (!item) + return; map->delete_func(map, item->key, item->value, user); FREE(item->key); FREE(item); @@ -288,7 +296,9 @@ util_keymap_remove_all(struct keymap *map, void *user) struct keymap_item *item; assert(map); - + if (!map) + return; + iter = cso_hash_first_node(map->cso); while (!cso_hash_iter_is_null(iter)) { item = (struct keymap_item *) diff --git a/src/gallium/auxiliary/util/u_math.h b/src/gallium/auxiliary/util/u_math.h index e5003af01d..4c6c2bc00e 100644 --- a/src/gallium/auxiliary/util/u_math.h +++ b/src/gallium/auxiliary/util/u_math.h @@ -53,11 +53,11 @@ __inline double ceil(double val) { double ceil_val; - if((val - (long) val) == 0) { + if ((val - (long) val) == 0) { ceil_val = val; } else { - if(val > 0) { + if (val > 0) { ceil_val = (long) val + 1; } else { @@ -73,11 +73,11 @@ __inline double floor(double val) { double floor_val; - if((val - (long) val) == 0) { + if ((val - (long) val) == 0) { floor_val = val; } else { - if(val > 0) { + if (val > 0) { floor_val = (long) val; } else { @@ -189,7 +189,10 @@ static INLINE double log2( double x ) extern float pow2_table[POW2_TABLE_SIZE]; - +/** + * Initialize math module. This should be called before using any + * other functions in this module. + */ extern void util_init_math(void); @@ -216,23 +219,24 @@ util_fast_exp2(float x) int32_t ipart; float fpart, mpart; union fi epart; - + if(x > 129.00000f) return 3.402823466e+38f; - - if(x < -126.99999f) + + if (x < -126.99999f) return 0.0f; ipart = (int32_t) x; fpart = x - (float) ipart; - + /* same as * epart.f = (float) (1 << ipart) - * but faster and without integer overflow for ipart > 31 */ + * but faster and without integer overflow for ipart > 31 + */ epart.i = (ipart + 127 ) << 23; - + mpart = pow2_table[POW2_TABLE_OFFSET + (int)(fpart * POW2_TABLE_SCALE)]; - + return epart.f * mpart; } @@ -254,6 +258,9 @@ util_fast_exp(float x) extern float log2_table[LOG2_TABLE_SIZE]; +/** + * Fast approximation to log2(x). + */ static INLINE float util_fast_log2(float x) { @@ -267,6 +274,9 @@ util_fast_log2(float x) } +/** + * Fast approximation to x^y. + */ static INLINE float util_fast_pow(float x, float y) { @@ -274,7 +284,6 @@ util_fast_pow(float x, float y) } - /** * Floor(x), returned as int. */ @@ -284,8 +293,8 @@ util_ifloor(float f) int ai, bi; double af, bf; union fi u; - af = (3 << 22) + 0.5 + (double)f; - bf = (3 << 22) + 0.5 - (double)f; + af = (3 << 22) + 0.5 + (double) f; + bf = (3 << 22) + 0.5 - (double) f; u.f = (float) af; ai = u.i; u.f = (float) bf; bi = u.i; return (ai - bi) >> 1; @@ -305,9 +314,9 @@ util_iround(float f) #elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86) int r; _asm { - fld f - fistp r - } + fld f + fistp r + } return r; #else if (f >= 0.0f) @@ -340,7 +349,7 @@ static INLINE unsigned long ffs( unsigned long u ) { unsigned long i; - if(_BitScanForward(&i, u)) + if (_BitScanForward(&i, u)) return i + 1; else return 0; @@ -351,7 +360,7 @@ unsigned ffs( unsigned u ) { unsigned i; - if( u == 0 ) { + if (u == 0) { return 0; } @@ -365,6 +374,22 @@ unsigned ffs( unsigned u ) #define ffs __builtin_ffs #endif +#ifdef __MINGW32__ +#define ffs __builtin_ffs +#endif + + +/* Could also binary search for the highest bit. + */ +static INLINE unsigned +util_unsigned_logbase2(unsigned n) +{ + unsigned log2 = 0; + while (n >>= 1) + ++log2; + return log2; +} + /** * Return float bits. @@ -378,7 +403,10 @@ fui( float f ) } - +/** + * Convert ubyte to float in [0, 1]. + * XXX a 256-entry lookup table would be slightly faster. + */ static INLINE float ubyte_to_float(ubyte ub) { @@ -409,7 +437,23 @@ float_to_ubyte(float f) } +/** + * Calc log base 2 + */ +static INLINE unsigned +util_logbase2(unsigned n) +{ + unsigned log2 = 0; + while (n >>= 1) + ++log2; + return log2; +} + +/** + * Clamp X to [MIN, MAX]. + * This is a macro to allow float, int, uint, etc. types. + */ #define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) ) #define MIN2( A, B ) ( (A)<(B) ? (A) : (B) ) @@ -422,6 +466,11 @@ align(int value, int alignment) return (value + alignment - 1) & ~(alignment - 1); } +static INLINE unsigned +minify(unsigned value) +{ + return MAX2(1, value >> 1); +} #ifndef COPY_4V #define COPY_4V( DST, SRC ) \ diff --git a/src/gallium/auxiliary/util/u_memory.h b/src/gallium/auxiliary/util/u_memory.h index 0b18d043ad..c3f8c91833 100644 --- a/src/gallium/auxiliary/util/u_memory.h +++ b/src/gallium/auxiliary/util/u_memory.h @@ -100,8 +100,14 @@ ExFreePool(void *P); #define MALLOC( SIZE ) malloc( SIZE ) #define CALLOC( COUNT, SIZE ) calloc( COUNT, SIZE ) #define FREE( PTR ) free( PTR ) -#define REALLOC( OLDPTR, OLDSIZE, NEWSIZE ) realloc( OLDPTR, NEWSIZE ) +static INLINE void * +_REALLOC( void *old_ptr, unsigned old_size, unsigned new_size ) +{ + (void) old_size; + return realloc(old_ptr, new_size); +} +#define REALLOC( a, b, c ) _REALLOC( a, b, c ) #endif diff --git a/src/gallium/auxiliary/util/u_mm.c b/src/gallium/auxiliary/util/u_mm.c index 151a480d34..4b75d4ba1d 100644 --- a/src/gallium/auxiliary/util/u_mm.c +++ b/src/gallium/auxiliary/util/u_mm.c @@ -33,30 +33,32 @@ void u_mmDumpMemInfo(const struct mem_block *heap) { - debug_printf("Memory heap %p:\n", (void *)heap); + debug_printf("Memory heap %p:\n", (void *) heap); if (heap == 0) { debug_printf(" heap == 0\n"); - } else { + } + else { const struct mem_block *p; - for(p = heap->next; p != heap; p = p->next) { - debug_printf(" Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size, - p->free ? 'F':'.', - p->reserved ? 'R':'.'); + for (p = heap->next; p != heap; p = p->next) { + debug_printf(" Offset:%08x, Size:%08x, %c%c\n", p->ofs, p->size, + p->free ? 'F':'.', + p->reserved ? 'R':'.'); } debug_printf("\nFree list:\n"); - for(p = heap->next_free; p != heap; p = p->next_free) { - debug_printf(" FREE Offset:%08x, Size:%08x, %c%c\n",p->ofs,p->size, - p->free ? 'F':'.', - p->reserved ? 'R':'.'); + for (p = heap->next_free; p != heap; p = p->next_free) { + debug_printf(" FREE Offset:%08x, Size:%08x, %c%c\n", p->ofs, p->size, + p->free ? 'F':'.', + p->reserved ? 'R':'.'); } } debug_printf("End of memory blocks\n"); } + struct mem_block * u_mmInit(int ofs, int size) { diff --git a/src/gallium/auxiliary/util/u_mm.h b/src/gallium/auxiliary/util/u_mm.h index ce20e48763..6b158aae6e 100644 --- a/src/gallium/auxiliary/util/u_mm.h +++ b/src/gallium/auxiliary/util/u_mm.h @@ -84,7 +84,7 @@ extern struct mem_block *u_mmFindBlock(struct mem_block *heap, int start); extern void u_mmDestroy(struct mem_block *mmInit); /** - * For debuging purpose. + * For debugging purposes. */ extern void u_mmDumpMemInfo(const struct mem_block *mmInit); diff --git a/src/gallium/auxiliary/util/u_network.c b/src/gallium/auxiliary/util/u_network.c new file mode 100644 index 0000000000..bc4b758406 --- /dev/null +++ b/src/gallium/auxiliary/util/u_network.c @@ -0,0 +1,188 @@ + +#include "pipe/p_compiler.h" +#include "util/u_network.h" +#include "util/u_debug.h" + +#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) +# include <winsock2.h> +# include <windows.h> +#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) +# include <sys/socket.h> +# include <netinet/in.h> +# include <unistd.h> +# include <fcntl.h> +# include <netdb.h> +#else +# warning "No socket implementation" +#endif + +boolean +u_socket_init() +{ +#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) + WORD wVersionRequested; + WSADATA wsaData; + int err; + + /* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */ + wVersionRequested = MAKEWORD(1, 1); + + err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) { + debug_printf("WSAStartup failed with error: %d\n", err); + return FALSE; + } + return TRUE; +#elif defined(PIPE_HAVE_SOCKETS) + return TRUE; +#else + return FALSE; +#endif +} + +void +u_socket_stop() +{ +#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) + WSACleanup(); +#endif +} + +void +u_socket_close(int s) +{ + if (s < 0) + return; + +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) + shutdown(s, SHUT_RDWR); + close(s); +#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) + shutdown(s, SD_BOTH); + closesocket(s); +#else + assert(0); +#endif +} + +int u_socket_accept(int s) +{ +#if defined(PIPE_HAVE_SOCKETS) + return accept(s, NULL, NULL); +#else + return -1; +#endif +} + +int +u_socket_send(int s, void *data, size_t size) +{ +#if defined(PIPE_HAVE_SOCKETS) + return send(s, data, size, 0); +#else + return -1; +#endif +} + +int +u_socket_peek(int s, void *data, size_t size) +{ +#if defined(PIPE_HAVE_SOCKETS) + return recv(s, data, size, MSG_PEEK); +#else + return -1; +#endif +} + +int +u_socket_recv(int s, void *data, size_t size) +{ +#if defined(PIPE_HAVE_SOCKETS) + return recv(s, data, size, 0); +#else + return -1; +#endif +} + +int +u_socket_connect(const char *hostname, uint16_t port) +{ +#if defined(PIPE_HAVE_SOCKETS) + int s; + struct sockaddr_in sa; + struct hostent *host = NULL; + + memset(&sa, 0, sizeof(struct sockaddr_in)); + host = gethostbyname(hostname); + if (!host) + return -1; + + memcpy((char *)&sa.sin_addr,host->h_addr,host->h_length); + sa.sin_family= host->h_addrtype; + sa.sin_port = htons(port); + + s = socket(host->h_addrtype, SOCK_STREAM, IPPROTO_TCP); + if (s < 0) + return -1; + + if (connect(s, (struct sockaddr *)&sa, sizeof(sa))) { + u_socket_close(s); + return -1; + } + + return s; +#else + assert(0); + return -1; +#endif +} + +int +u_socket_listen_on_port(uint16_t portnum) +{ +#if defined(PIPE_HAVE_SOCKETS) + int s; + struct sockaddr_in sa; + memset(&sa, 0, sizeof(struct sockaddr_in)); + + sa.sin_family = AF_INET; + sa.sin_port = htons(portnum); + + s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (s < 0) + return -1; + + if (bind(s, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) == -1) { + u_socket_close(s); + return -1; + } + + listen(s, 0); + + return s; +#else + assert(0); + return -1; +#endif +} + +void +u_socket_block(int s, boolean block) +{ +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) + int old = fcntl(s, F_GETFL, 0); + if (old == -1) + return; + + /* TODO obey block */ + if (block) + fcntl(s, F_SETFL, old & ~O_NONBLOCK); + else + fcntl(s, F_SETFL, old | O_NONBLOCK); +#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER) + u_long iMode = block ? 0 : 1; + ioctlsocket(s, FIONBIO, &iMode); +#else + assert(0); +#endif +} diff --git a/src/gallium/auxiliary/util/u_network.h b/src/gallium/auxiliary/util/u_network.h new file mode 100644 index 0000000000..8c778f492c --- /dev/null +++ b/src/gallium/auxiliary/util/u_network.h @@ -0,0 +1,24 @@ + +#ifndef _U_NETWORK_H_ +#define _U_NETWORK_H_ + +#include "pipe/p_compiler.h" + +#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) +# define PIPE_HAVE_SOCKETS +#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) +# define PIPE_HAVE_SOCKETS +#endif + +boolean u_socket_init(void); +void u_socket_stop(void); +void u_socket_close(int s); +int u_socket_listen_on_port(uint16_t portnum); +int u_socket_accept(int s); +int u_socket_connect(const char *host, uint16_t port); +int u_socket_send(int s, void *data, size_t size); +int u_socket_peek(int s, void *data, size_t size); +int u_socket_recv(int s, void *data, size_t size); +void u_socket_block(int s, boolean block); + +#endif diff --git a/src/gallium/auxiliary/util/u_prim.h b/src/gallium/auxiliary/util/u_prim.h index d7c3995dbf..a9b533eea7 100644 --- a/src/gallium/auxiliary/util/u_prim.h +++ b/src/gallium/auxiliary/util/u_prim.h @@ -119,7 +119,7 @@ static INLINE boolean u_trim_pipe_prim( unsigned pipe_prim, unsigned *nr ) } -static INLINE boolean u_reduced_prim( unsigned pipe_prim ) +static INLINE unsigned u_reduced_prim( unsigned pipe_prim ) { switch (pipe_prim) { case PIPE_PRIM_POINTS: diff --git a/src/gallium/auxiliary/util/u_rect.c b/src/gallium/auxiliary/util/u_rect.c index 74259d453b..9866b6fc8a 100644 --- a/src/gallium/auxiliary/util/u_rect.c +++ b/src/gallium/auxiliary/util/u_rect.c @@ -43,7 +43,7 @@ * src_pitch may be negative to do vertical flip of pixels from source. */ void -pipe_copy_rect(ubyte * dst, +util_copy_rect(ubyte * dst, const struct pipe_format_block *block, unsigned dst_stride, unsigned dst_x, @@ -91,7 +91,7 @@ pipe_copy_rect(ubyte * dst, } void -pipe_fill_rect(ubyte * dst, +util_fill_rect(ubyte * dst, const struct pipe_format_block *block, unsigned dst_stride, unsigned dst_x, @@ -204,7 +204,7 @@ util_surface_copy(struct pipe_context *pipe, if (src_map && dst_map) { /* If do_flip, invert src_y position and pass negative src stride */ - pipe_copy_rect(dst_map, + util_copy_rect(dst_map, &dst_trans->block, dst_trans->stride, 0, 0, @@ -263,7 +263,7 @@ util_surface_fill(struct pipe_context *pipe, case 1: case 2: case 4: - pipe_fill_rect(dst_map, &dst_trans->block, dst_trans->stride, + util_fill_rect(dst_map, &dst_trans->block, dst_trans->stride, 0, 0, width, height, value); break; case 8: diff --git a/src/gallium/auxiliary/util/u_rect.h b/src/gallium/auxiliary/util/u_rect.h index 59e842e16d..daa50834d3 100644 --- a/src/gallium/auxiliary/util/u_rect.h +++ b/src/gallium/auxiliary/util/u_rect.h @@ -42,13 +42,13 @@ struct pipe_surface; extern void -pipe_copy_rect(ubyte * dst, const struct pipe_format_block *block, +util_copy_rect(ubyte * dst, const struct pipe_format_block *block, unsigned dst_stride, unsigned dst_x, unsigned dst_y, unsigned width, unsigned height, const ubyte * src, int src_stride, unsigned src_x, int src_y); extern void -pipe_fill_rect(ubyte * dst, const struct pipe_format_block *block, +util_fill_rect(ubyte * dst, const struct pipe_format_block *block, unsigned dst_stride, unsigned dst_x, unsigned dst_y, unsigned width, unsigned height, uint32_t value); diff --git a/src/gallium/auxiliary/util/u_simple_screen.c b/src/gallium/auxiliary/util/u_simple_screen.c index 8114b53cd0..f01296b40f 100644 --- a/src/gallium/auxiliary/util/u_simple_screen.c +++ b/src/gallium/auxiliary/util/u_simple_screen.c @@ -65,12 +65,13 @@ pass_surface_buffer_create(struct pipe_screen *screen, unsigned width, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride) { struct pipe_buffer *buffer = screen->winsys->surface_buffer_create(screen->winsys, width, height, - format, usage, stride); + format, usage, tex_usage, stride); buffer->screen = screen; diff --git a/src/gallium/auxiliary/util/u_simple_shaders.c b/src/gallium/auxiliary/util/u_simple_shaders.c index acc5b83c62..ab754296fa 100644 --- a/src/gallium/auxiliary/util/u_simple_shaders.c +++ b/src/gallium/auxiliary/util/u_simple_shaders.c @@ -42,9 +42,7 @@ #include "util/u_memory.h" #include "util/u_simple_shaders.h" -#include "tgsi/tgsi_build.h" -#include "tgsi/tgsi_dump.h" -#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_ureg.h" @@ -58,93 +56,31 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe, const uint *semantic_indexes) { - struct pipe_shader_state shader; - struct tgsi_token tokens[100]; - struct tgsi_header *header; - struct tgsi_processor *processor; - struct tgsi_full_declaration decl; - struct tgsi_full_instruction inst; - const uint procType = TGSI_PROCESSOR_VERTEX; - uint ti, i; + struct ureg_program *ureg; + uint i; - /* shader header - */ - *(struct tgsi_version *) &tokens[0] = tgsi_build_version(); + ureg = ureg_create( TGSI_PROCESSOR_VERTEX ); + if (ureg == NULL) + return NULL; - header = (struct tgsi_header *) &tokens[1]; - *header = tgsi_build_header(); - - processor = (struct tgsi_processor *) &tokens[2]; - *processor = tgsi_build_processor( procType, header ); - - ti = 3; - - /* declare inputs */ - for (i = 0; i < num_attribs; i++) { - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_INPUT; - - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = semantic_names[i]; - decl.Semantic.SemanticIndex = semantic_indexes[i]; - - decl.DeclarationRange.First = - decl.DeclarationRange.Last = i; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); - } - - /* declare outputs */ for (i = 0; i < num_attribs; i++) { - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_OUTPUT; - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = semantic_names[i]; - decl.Semantic.SemanticIndex = semantic_indexes[i]; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = i; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); + struct ureg_src src; + struct ureg_dst dst; + + src = ureg_DECL_vs_input( ureg, + semantic_names[i], + semantic_indexes[i]); + + dst = ureg_DECL_output( ureg, + semantic_names[i], + semantic_indexes[i]); + + ureg_MOV( ureg, dst, src ); } - /* emit MOV instructions */ - for (i = 0; i < num_attribs; i++) { - /* MOVE out[i], in[i]; */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_MOV; - inst.Instruction.NumDstRegs = 1; - inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT; - inst.FullDstRegisters[0].DstRegister.Index = i; - inst.Instruction.NumSrcRegs = 1; - inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; - inst.FullSrcRegisters[0].SrcRegister.Index = i; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); - } - - /* END instruction */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_END; - inst.Instruction.NumDstRegs = 0; - inst.Instruction.NumSrcRegs = 0; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); + ureg_END( ureg ); -#if 0 /*debug*/ - tgsi_dump(tokens, 0); -#endif - - shader.tokens = tokens; - - return pipe->create_vs_state(pipe, &shader); + return ureg_create_shader_and_destroy( ureg, pipe ); } @@ -161,130 +97,29 @@ void * util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, unsigned writemask ) { - struct pipe_shader_state shader; - struct tgsi_token tokens[100]; - struct tgsi_header *header; - struct tgsi_processor *processor; - struct tgsi_full_declaration decl; - struct tgsi_full_instruction inst; - const uint procType = TGSI_PROCESSOR_FRAGMENT; - uint ti; - - /* shader header - */ - *(struct tgsi_version *) &tokens[0] = tgsi_build_version(); - - header = (struct tgsi_header *) &tokens[1]; - *header = tgsi_build_header(); - - processor = (struct tgsi_processor *) &tokens[2]; - *processor = tgsi_build_processor( procType, header ); - - ti = 3; - - /* declare TEX[0] input */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_INPUT; - /* XXX this could be linear... */ - decl.Declaration.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE; - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = TGSI_SEMANTIC_GENERIC; - decl.Semantic.SemanticIndex = 0; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = 0; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); - - /* declare color[0] output */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_OUTPUT; - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR; - decl.Semantic.SemanticIndex = 0; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = 0; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); - - /* declare sampler */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_SAMPLER; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = 0; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); - - - if (writemask != TGSI_WRITEMASK_XYZW) { - struct tgsi_full_immediate imm; - static const float value[4] = { 0, 0, 0, 1 }; - - imm = tgsi_default_full_immediate(); - imm.Immediate.NrTokens += 4; - imm.Immediate.DataType = TGSI_IMM_FLOAT32; - imm.u.Pointer = value; - - ti += tgsi_build_full_immediate(&imm, - &tokens[ti], - header, - Elements(tokens) - ti ); - - /* MOV instruction */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_MOV; - inst.Instruction.NumDstRegs = 1; - inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT; - inst.FullDstRegisters[0].DstRegister.Index = 0; - inst.Instruction.NumSrcRegs = 1; - inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_IMMEDIATE; - inst.FullSrcRegisters[0].SrcRegister.Index = 0; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); - } + struct ureg_program *ureg; + struct ureg_src sampler; + struct ureg_src tex; + struct ureg_dst out; - /* TEX instruction */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_TEX; - inst.Instruction.NumDstRegs = 1; - inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT; - inst.FullDstRegisters[0].DstRegister.Index = 0; - inst.FullDstRegisters[0].DstRegister.WriteMask = writemask; - inst.Instruction.NumSrcRegs = 2; - inst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D; - inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; - inst.FullSrcRegisters[0].SrcRegister.Index = 0; - inst.FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER; - inst.FullSrcRegisters[1].SrcRegister.Index = 0; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); - - /* END instruction */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_END; - inst.Instruction.NumDstRegs = 0; - inst.Instruction.NumSrcRegs = 0; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); - -#if 0 /*debug*/ - tgsi_dump(tokens, 0); -#endif - - shader.tokens = tokens; - - return pipe->create_fs_state(pipe, &shader); + ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + if (ureg == NULL) + return NULL; + + sampler = ureg_DECL_sampler( ureg, 0 ); + + tex = ureg_DECL_fs_input( ureg, + TGSI_SEMANTIC_GENERIC, 0, + TGSI_INTERPOLATE_PERSPECTIVE ); + + out = ureg_DECL_output( ureg, + TGSI_SEMANTIC_COLOR, + 0 ); + + ureg_TEX( ureg, out, TGSI_TEXTURE_2D, tex, sampler ); + ureg_END( ureg ); + + return ureg_create_shader_and_destroy( ureg, pipe ); } void * @@ -296,95 +131,29 @@ util_make_fragment_tex_shader(struct pipe_context *pipe ) - - /** * Make simple fragment color pass-through shader. */ void * util_make_fragment_passthrough_shader(struct pipe_context *pipe) { - struct pipe_shader_state shader; - struct tgsi_token tokens[40]; - struct tgsi_header *header; - struct tgsi_processor *processor; - struct tgsi_full_declaration decl; - struct tgsi_full_instruction inst; - const uint procType = TGSI_PROCESSOR_FRAGMENT; - uint ti; - - /* shader header - */ - *(struct tgsi_version *) &tokens[0] = tgsi_build_version(); - - header = (struct tgsi_header *) &tokens[1]; - *header = tgsi_build_header(); - - processor = (struct tgsi_processor *) &tokens[2]; - *processor = tgsi_build_processor( procType, header ); - - ti = 3; - - /* declare input */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_INPUT; - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR; - decl.Semantic.SemanticIndex = 0; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = 0; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); - - /* declare output */ - decl = tgsi_default_full_declaration(); - decl.Declaration.File = TGSI_FILE_OUTPUT; - decl.Declaration.Semantic = 1; - decl.Semantic.SemanticName = TGSI_SEMANTIC_COLOR; - decl.Semantic.SemanticIndex = 0; - decl.DeclarationRange.First = - decl.DeclarationRange.Last = 0; - ti += tgsi_build_full_declaration(&decl, - &tokens[ti], - header, - Elements(tokens) - ti); - - - /* MOVE out[0], in[0]; */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_MOV; - inst.Instruction.NumDstRegs = 1; - inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT; - inst.FullDstRegisters[0].DstRegister.Index = 0; - inst.Instruction.NumSrcRegs = 1; - inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT; - inst.FullSrcRegisters[0].SrcRegister.Index = 0; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); - - /* END instruction */ - inst = tgsi_default_full_instruction(); - inst.Instruction.Opcode = TGSI_OPCODE_END; - inst.Instruction.NumDstRegs = 0; - inst.Instruction.NumSrcRegs = 0; - ti += tgsi_build_full_instruction(&inst, - &tokens[ti], - header, - Elements(tokens) - ti ); - - assert(ti < Elements(tokens)); - -#if 0 /*debug*/ - tgsi_dump(tokens, 0); -#endif - - shader.tokens = tokens; - - return pipe->create_fs_state(pipe, &shader); + struct ureg_program *ureg; + struct ureg_src src; + struct ureg_dst dst; + + ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + if (ureg == NULL) + return NULL; + + src = ureg_DECL_fs_input( ureg, TGSI_SEMANTIC_COLOR, 0, + TGSI_INTERPOLATE_PERSPECTIVE ); + + dst = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, 0 ); + + ureg_MOV( ureg, dst, src ); + ureg_END( ureg ); + + return ureg_create_shader_and_destroy( ureg, pipe ); } diff --git a/src/gallium/auxiliary/util/u_stream_stdc.c b/src/gallium/auxiliary/util/u_stream_stdc.c index d8f648e5dd..5cd05b2904 100644 --- a/src/gallium/auxiliary/util/u_stream_stdc.c +++ b/src/gallium/auxiliary/util/u_stream_stdc.c @@ -32,7 +32,7 @@ #include "pipe/p_config.h" -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HAIKU) #include <stdio.h> diff --git a/src/gallium/auxiliary/util/u_tile.c b/src/gallium/auxiliary/util/u_tile.c index aa16fe771f..1235a67d26 100644 --- a/src/gallium/auxiliary/util/u_tile.c +++ b/src/gallium/auxiliary/util/u_tile.c @@ -62,7 +62,7 @@ pipe_get_tile_raw(struct pipe_transfer *pt, if(!src) return; - pipe_copy_rect(dst, &pt->block, dst_stride, 0, 0, w, h, src, pt->stride, x, y); + util_copy_rect(dst, &pt->block, dst_stride, 0, 0, w, h, src, pt->stride, x, y); screen->transfer_unmap(screen, pt); } @@ -90,7 +90,7 @@ pipe_put_tile_raw(struct pipe_transfer *pt, if(!dst) return; - pipe_copy_rect(dst, &pt->block, pt->stride, x, y, w, h, src, src_stride, 0, 0); + util_copy_rect(dst, &pt->block, pt->stride, x, y, w, h, src, src_stride, 0, 0); screen->transfer_unmap(screen, pt); } diff --git a/src/gallium/auxiliary/util/u_time.c b/src/gallium/auxiliary/util/u_time.c index 5268cbf79c..b958a98635 100644 --- a/src/gallium/auxiliary/util/u_time.c +++ b/src/gallium/auxiliary/util/u_time.c @@ -35,7 +35,7 @@ #include "pipe/p_config.h" -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) #include <sys/time.h> #elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) #include <windows.h> @@ -77,7 +77,7 @@ util_time_get_frequency(void) void util_time_get(struct util_time *t) { -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) gettimeofday(&t->tv, NULL); #elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) LONGLONG temp; @@ -102,7 +102,7 @@ util_time_add(const struct util_time *t1, int64_t usecs, struct util_time *t2) { -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) t2->tv.tv_sec = t1->tv.tv_sec + usecs / 1000000; t2->tv.tv_usec = t1->tv.tv_usec + usecs % 1000000; #elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE) @@ -124,7 +124,7 @@ int64_t util_time_diff(const struct util_time *t1, const struct util_time *t2) { -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) return (t2->tv.tv_usec - t1->tv.tv_usec) + (t2->tv.tv_sec - t1->tv.tv_sec)*1000000; #elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE) @@ -144,7 +144,7 @@ util_time_micros( void ) util_time_get(&t1); -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) return t1.tv.tv_usec + t1.tv.tv_sec*1000000LL; #elif defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_USER) || defined(PIPE_SUBSYSTEM_WINDOWS_CE) util_time_get_frequency(); @@ -166,7 +166,7 @@ static INLINE int util_time_compare(const struct util_time *t1, const struct util_time *t2) { -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) if (t1->tv.tv_sec < t2->tv.tv_sec) return -1; else if(t1->tv.tv_sec > t2->tv.tv_sec) diff --git a/src/gallium/auxiliary/util/u_time.h b/src/gallium/auxiliary/util/u_time.h index 6bca6077a2..a6189a247b 100644 --- a/src/gallium/auxiliary/util/u_time.h +++ b/src/gallium/auxiliary/util/u_time.h @@ -38,11 +38,16 @@ #include "pipe/p_config.h" -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) #include <time.h> /* timeval */ #include <unistd.h> /* usleep */ #endif +#if defined(PIPE_OS_HAIKU) +#include <sys/time.h> /* timeval */ +#include <unistd.h> +#endif + #include "pipe/p_compiler.h" @@ -58,7 +63,7 @@ extern "C" { */ struct util_time { -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) struct timeval tv; #else int64_t counter; @@ -89,7 +94,7 @@ util_time_timeout(const struct util_time *start, const struct util_time *end, const struct util_time *curr); -#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) +#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) #define util_time_sleep usleep #else void diff --git a/src/gallium/auxiliary/util/u_timed_winsys.c b/src/gallium/auxiliary/util/u_timed_winsys.c index 77b2a3a1c8..178acdca4d 100644 --- a/src/gallium/auxiliary/util/u_timed_winsys.c +++ b/src/gallium/auxiliary/util/u_timed_winsys.c @@ -212,13 +212,14 @@ timed_surface_buffer_create(struct pipe_winsys *winsys, unsigned width, unsigned height, enum pipe_format format, unsigned usage, + unsigned tex_usage, unsigned *stride) { struct pipe_winsys *backend = timed_winsys(winsys)->backend; uint64_t start = time_start(); struct pipe_buffer *ret = backend->surface_buffer_create( backend, width, height, - format, usage, stride ); + format, usage, tex_usage, stride ); time_finish(winsys, start, 7, __FUNCTION__); |