diff options
Diffstat (limited to 'src/gallium')
341 files changed, 33340 insertions, 5544 deletions
diff --git a/src/gallium/SConscript b/src/gallium/SConscript index b6ceaf3edf9..32b7c2980ab 100644 --- a/src/gallium/SConscript +++ b/src/gallium/SConscript @@ -22,6 +22,7 @@ SConscript([ 'auxiliary/draw/SConscript', 'auxiliary/pipebuffer/SConscript', 'auxiliary/indices/SConscript', + 'auxiliary/rbug/SConscript', ]) for driver in env['drivers']: diff --git a/src/gallium/auxiliary/cso_cache/cso_cache.c b/src/gallium/auxiliary/cso_cache/cso_cache.c index 0bc77a57287..e6dce3f0e5b 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 f388bf5d951..36c882acb75 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 3cde9d36d3a..2e3f5b2fc07 100644 --- a/src/gallium/auxiliary/draw/draw_pipe.c +++ b/src/gallium/auxiliary/draw/draw_pipe.c @@ -216,22 +216,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 30a6d2919d9..283502cdf3e 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 a5d840b96ea..1a5269c0de9 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 d84bab9eaae..014d8c7346d 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c +++ b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c @@ -181,6 +181,16 @@ static void widepoint_point( struct draw_stage *stage, } +static int +find_fog_input_attrib(struct draw_context *draw) +{ + /* Scan the fragment program's input decls to find the fogcoord + * attribute. The z/w components will store the point coord. + */ + return 0; /* XXX fix this */ +} + + static void widepoint_first_point( struct draw_stage *stage, struct prim_header *header ) { @@ -220,7 +230,7 @@ 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! */ + wide->point_coord_fs_input = find_fog_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 81e4eae401c..41fcb16a0a5 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 9ea0cbe5990..dbb5ac71821 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 8ef0ea8011f..7a17a9fb6b2 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 3fb06956878..4ca5b520204 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 6b7d02a19bc..e7fe6b3b768 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 3bc7939c556..b61fa291436 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 5d268a22264..1a0527be63a 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 ec05bbeab40..62822a3d562 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 c057cd67fde..790e89ed820 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 9e37a26c1e2..62e04a65f30 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 dbbc33fffa7..41cc8026131 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 727977bc3af..b3535c0e48e 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 d35db57d571..ad184bd696d 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 77ba5152f9f..702051387ac 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 925e948763e..721b7d2d833 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 5b08200d142..8d885e48be6 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]); } @@ -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]); } @@ -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 0760d607161..6bdce5fcb06 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 bc3093f620f..cb32d251367 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 00000000000..cd12e8468fc --- /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 00000000000..33d76371de4 --- /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 <[email protected]> diff --git a/src/gallium/auxiliary/rbug/SConscript b/src/gallium/auxiliary/rbug/SConscript new file mode 100644 index 00000000000..4a9afb45d3c --- /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 00000000000..259bfc6c79c --- /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 00000000000..52acb700af9 --- /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 00000000000..1f2c9ff347c --- /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 00000000000..1832425658f --- /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 00000000000..da61c2365b0 --- /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 00000000000..876ae5a0ce6 --- /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 00000000000..99a36a0163e --- /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 00000000000..47390fbcee7 --- /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 00000000000..4aba1a810f6 --- /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 00000000000..d273be0166d --- /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 00000000000..fccd2f55efd --- /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 00000000000..b5d886781d8 --- /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 00000000000..5a918fe6bc0 --- /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 00000000000..fbb247e1d4f --- /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 57fcf6de2ab..1acf3c373eb 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 1b5eaaca850..731a6517968 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/tgsi-instruction-set.txt b/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt index a3f4947c734..5f88cc2acac 100644 --- a/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt +++ b/src/gallium/auxiliary/tgsi/tgsi-instruction-set.txt @@ -667,7 +667,16 @@ TGSI Instruction Specification 1.9.8 LOOP - Loop - TBD + dst.x = floor(src.x) + dst.y = floor(src.y) + dst.z = floor(src.z) + + if (dst.y <= 0) + pc = [matching ENDLOOP] + 1 + endif + + Note: The destination must be a loop register. + The source must be a constant register. 1.9.9 REP - Repeat @@ -687,7 +696,14 @@ TGSI Instruction Specification 1.9.12 ENDLOOP - End Loop - TBD + dst.x = dst.x + dst.z + dst.y = dst.y - 1.0 + + if (dst.y > 0) + pc = [matching LOOP instruction] + 1 + endif + + Note: The destination must be a loop register. 1.9.13 ENDREP - End Repeat diff --git a/src/gallium/auxiliary/tgsi/tgsi_build.c b/src/gallium/auxiliary/tgsi/tgsi_build.c index d272533d63c..010d501c601 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 9a3a077cf2b..17d977b0597 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 a6994ecd48b..4ca3a16b8ae 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_dump.c +++ b/src/gallium/auxiliary/tgsi/tgsi_dump.c @@ -82,7 +82,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 +91,8 @@ static const char *file_names[] = "TEMP", "SAMP", "ADDR", - "IMM" + "IMM", + "LOOP" }; static const char *interpolate_names[] = @@ -295,10 +296,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 ); diff --git a/src/gallium/auxiliary/tgsi/tgsi_dump_c.c b/src/gallium/auxiliary/tgsi/tgsi_dump_c.c index 3dc61c48ca3..4a9c02b1413 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 5cb322a5fa2..0179bba5a21 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c @@ -301,14 +301,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; @@ -365,15 +365,26 @@ 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; + mach->Addrs = &mach->Temps[TGSI_EXEC_TEMP_ADDR]; + mach->Samplers = NULL; + mach->Consts = NULL; + mach->Tokens = NULL; + mach->Primitives = NULL; + mach->InterpCoefs = NULL; + mach->Instructions = NULL; + mach->Declarations = NULL; + /* Setup constants. */ for( i = 0; i < 4; i++ ) { mach->Temps[TEMP_0_I].xyzw[TEMP_0_C].u[i] = 0x00000000; @@ -393,22 +404,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); } @@ -2007,8 +2020,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] ); @@ -2277,8 +2289,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); @@ -2312,8 +2323,7 @@ exec_instruction( } 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] ); @@ -2331,18 +2341,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] ); @@ -2370,8 +2369,7 @@ exec_instruction( } break; - case TGSI_OPCODE_EXPBASE2: - /* TGSI_OPCODE_EX2 */ + case TGSI_OPCODE_EX2: FETCH(&r[0], 0, CHAN_X); #if FAST_MATH @@ -2385,8 +2383,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 ) { @@ -2394,8 +2391,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); @@ -2406,8 +2402,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); @@ -2449,11 +2444,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); diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.h b/src/gallium/auxiliary/tgsi/tgsi_exec.h index da22baad3ef..8a9100f4c3e 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 @@ -187,24 +192,21 @@ struct tgsi_exec_labels 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 */ @@ -251,9 +253,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 @@ -268,10 +272,6 @@ tgsi_exec_machine_run( struct tgsi_exec_machine *mach ); -void -tgsi_exec_machine_free_data(struct tgsi_exec_machine *mach); - - static INLINE void tgsi_set_kill_mask(struct tgsi_exec_machine *mach, unsigned mask) { diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.c b/src/gallium/auxiliary/tgsi/tgsi_info.c index 37f2b66d1f6..3a47e9b84df 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_info.c +++ b/src/gallium/auxiliary/tgsi/tgsi_info.c @@ -26,136 +26,147 @@ **************************************************************************/ #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, "ARL", TGSI_OPCODE_ARL }, + { 1, 1, 0, 0, "MOV", TGSI_OPCODE_MOV }, + { 1, 1, 0, 0, "LIT", TGSI_OPCODE_LIT }, + { 1, 1, 0, 0, "RCP", TGSI_OPCODE_RCP }, + { 1, 1, 0, 0, "RSQ", TGSI_OPCODE_RSQ }, + { 1, 1, 0, 0, "EXP", TGSI_OPCODE_EXP }, + { 1, 1, 0, 0, "LOG", TGSI_OPCODE_LOG }, + { 1, 2, 0, 0, "MUL", TGSI_OPCODE_MUL }, + { 1, 2, 0, 0, "ADD", TGSI_OPCODE_ADD }, + { 1, 2, 0, 0, "DP3", TGSI_OPCODE_DP3 }, + { 1, 2, 0, 0, "DP4", TGSI_OPCODE_DP4 }, + { 1, 2, 0, 0, "DST", TGSI_OPCODE_DST }, + { 1, 2, 0, 0, "MIN", TGSI_OPCODE_MIN }, + { 1, 2, 0, 0, "MAX", TGSI_OPCODE_MAX }, + { 1, 2, 0, 0, "SLT", TGSI_OPCODE_SLT }, + { 1, 2, 0, 0, "SGE", TGSI_OPCODE_SGE }, + { 1, 3, 0, 0, "MAD", TGSI_OPCODE_MAD }, + { 1, 2, 0, 0, "SUB", TGSI_OPCODE_SUB }, + { 1, 3, 0, 0, "LRP", TGSI_OPCODE_LRP }, + { 1, 3, 0, 0, "CND", TGSI_OPCODE_CND }, + { 1, 3, 0, 0, "CND0", TGSI_OPCODE_CND0 }, + { 1, 3, 0, 0, "DP2A", TGSI_OPCODE_DP2A }, + { 0, 0, 0, 0, "", 22 }, /* removed */ + { 0, 0, 0, 0, "", 23 }, /* removed */ + { 1, 1, 0, 0, "FRC", TGSI_OPCODE_FRC }, + { 1, 3, 0, 0, "CLAMP", TGSI_OPCODE_CLAMP }, + { 1, 1, 0, 0, "FLR", TGSI_OPCODE_FLR }, + { 1, 1, 0, 0, "ROUND", TGSI_OPCODE_ROUND }, + { 1, 1, 0, 0, "EX2", TGSI_OPCODE_EX2 }, + { 1, 1, 0, 0, "LG2", TGSI_OPCODE_LG2 }, + { 1, 2, 0, 0, "POW", TGSI_OPCODE_POW }, + { 1, 2, 0, 0, "XPD", TGSI_OPCODE_XPD }, + { 0, 0, 0, 0, "", 32 }, /* removed */ + { 1, 1, 0, 0, "ABS", TGSI_OPCODE_ABS }, + { 1, 1, 0, 0, "RCC", TGSI_OPCODE_RCC }, + { 1, 2, 0, 0, "DPH", TGSI_OPCODE_DPH }, + { 1, 1, 0, 0, "COS", TGSI_OPCODE_COS }, + { 1, 1, 0, 0, "DDX", TGSI_OPCODE_DDX }, + { 1, 1, 0, 0, "DDY", TGSI_OPCODE_DDY }, + { 0, 0, 0, 0, "KILP", TGSI_OPCODE_KILP }, + { 1, 1, 0, 0, "PK2H", TGSI_OPCODE_PK2H }, + { 1, 1, 0, 0, "PK2US", TGSI_OPCODE_PK2US }, + { 1, 1, 0, 0, "PK4B", TGSI_OPCODE_PK4B }, + { 1, 1, 0, 0, "PK4UB", TGSI_OPCODE_PK4UB }, + { 1, 2, 0, 0, "RFL", TGSI_OPCODE_RFL }, + { 1, 2, 0, 0, "SEQ", TGSI_OPCODE_SEQ }, + { 1, 2, 0, 0, "SFL", TGSI_OPCODE_SFL }, + { 1, 2, 0, 0, "SGT", TGSI_OPCODE_SGT }, + { 1, 1, 0, 0, "SIN", TGSI_OPCODE_SIN }, + { 1, 2, 0, 0, "SLE", TGSI_OPCODE_SLE }, + { 1, 2, 0, 0, "SNE", TGSI_OPCODE_SNE }, + { 1, 2, 0, 0, "STR", TGSI_OPCODE_STR }, + { 1, 2, 1, 0, "TEX", TGSI_OPCODE_TEX }, + { 1, 4, 1, 0, "TXD", TGSI_OPCODE_TXD }, + { 1, 2, 1, 0, "TXP", TGSI_OPCODE_TXP }, + { 1, 1, 0, 0, "UP2H", TGSI_OPCODE_UP2H }, + { 1, 1, 0, 0, "UP2US", TGSI_OPCODE_UP2US }, + { 1, 1, 0, 0, "UP4B", TGSI_OPCODE_UP4B }, + { 1, 1, 0, 0, "UP4UB", TGSI_OPCODE_UP4UB }, + { 1, 3, 0, 0, "X2D", TGSI_OPCODE_X2D }, + { 1, 1, 0, 0, "ARA", TGSI_OPCODE_ARA }, + { 1, 1, 0, 0, "ARR", TGSI_OPCODE_ARR }, + { 0, 1, 0, 0, "BRA", TGSI_OPCODE_BRA }, + { 0, 0, 0, 1, "CAL", TGSI_OPCODE_CAL }, + { 0, 0, 0, 0, "RET", TGSI_OPCODE_RET }, + { 1, 1, 0, 0, "SSG", TGSI_OPCODE_SSG }, + { 1, 3, 0, 0, "CMP", TGSI_OPCODE_CMP }, + { 1, 1, 0, 0, "SCS", TGSI_OPCODE_SCS }, + { 1, 2, 1, 0, "TXB", TGSI_OPCODE_TXB }, + { 1, 1, 0, 0, "NRM", TGSI_OPCODE_NRM }, + { 1, 2, 0, 0, "DIV", TGSI_OPCODE_DIV }, + { 1, 2, 0, 0, "DP2", TGSI_OPCODE_DP2 }, + { 1, 2, 1, 0, "TXL", TGSI_OPCODE_TXL }, + { 0, 0, 0, 0, "BRK", TGSI_OPCODE_BRK }, + { 0, 1, 0, 1, "IF", TGSI_OPCODE_IF }, + { 1, 1, 0, 0, "LOOP", TGSI_OPCODE_LOOP }, + { 0, 1, 0, 0, "REP", TGSI_OPCODE_REP }, + { 0, 0, 0, 1, "ELSE", TGSI_OPCODE_ELSE }, + { 0, 0, 0, 0, "ENDIF", TGSI_OPCODE_ENDIF }, + { 1, 0, 0, 0, "ENDLOOP", TGSI_OPCODE_ENDLOOP }, + { 0, 0, 0, 0, "ENDREP", TGSI_OPCODE_ENDREP }, + { 0, 1, 0, 0, "PUSHA", TGSI_OPCODE_PUSHA }, + { 1, 0, 0, 0, "POPA", TGSI_OPCODE_POPA }, + { 1, 1, 0, 0, "CEIL", TGSI_OPCODE_CEIL }, + { 1, 1, 0, 0, "I2F", TGSI_OPCODE_I2F }, + { 1, 1, 0, 0, "NOT", TGSI_OPCODE_NOT }, + { 1, 1, 0, 0, "TRUNC", TGSI_OPCODE_TRUNC }, + { 1, 2, 0, 0, "SHL", TGSI_OPCODE_SHL }, + { 1, 2, 0, 0, "SHR", TGSI_OPCODE_SHR }, + { 1, 2, 0, 0, "AND", TGSI_OPCODE_AND }, + { 1, 2, 0, 0, "OR", TGSI_OPCODE_OR }, + { 1, 2, 0, 0, "MOD", TGSI_OPCODE_MOD }, + { 1, 2, 0, 0, "XOR", TGSI_OPCODE_XOR }, + { 1, 3, 0, 0, "SAD", TGSI_OPCODE_SAD }, + { 1, 2, 1, 0, "TXF", TGSI_OPCODE_TXF }, + { 1, 2, 1, 0, "TXQ", TGSI_OPCODE_TXQ }, + { 0, 0, 0, 0, "CONT", TGSI_OPCODE_CONT }, + { 0, 0, 0, 0, "EMIT", TGSI_OPCODE_EMIT }, + { 0, 0, 0, 0, "ENDPRIM", TGSI_OPCODE_ENDPRIM }, + { 0, 0, 0, 1, "BGNLOOP2", TGSI_OPCODE_BGNLOOP2 }, + { 0, 0, 0, 0, "BGNSUB", TGSI_OPCODE_BGNSUB }, + { 0, 0, 0, 1, "ENDLOOP2", TGSI_OPCODE_ENDLOOP2 }, + { 0, 0, 0, 0, "ENDSUB", TGSI_OPCODE_ENDSUB }, + { 1, 1, 0, 0, "NOISE1", TGSI_OPCODE_NOISE1 }, + { 1, 1, 0, 0, "NOISE2", TGSI_OPCODE_NOISE2 }, + { 1, 1, 0, 0, "NOISE3", TGSI_OPCODE_NOISE3 }, + { 1, 1, 0, 0, "NOISE4", TGSI_OPCODE_NOISE4 }, + { 0, 0, 0, 0, "NOP", TGSI_OPCODE_NOP }, + { 0, 0, 0, 0, "", 108 }, /* removed */ + { 0, 0, 0, 0, "", 109 }, /* removed */ + { 0, 0, 0, 0, "", 110 }, /* removed */ + { 0, 0, 0, 0, "", 111 }, /* removed */ + { 1, 1, 0, 0, "NRM4", TGSI_OPCODE_NRM4 }, + { 0, 1, 0, 0, "CALLNZ", TGSI_OPCODE_CALLNZ }, + { 0, 1, 0, 0, "IFC", TGSI_OPCODE_IFC }, + { 0, 1, 0, 0, "BREAKC", TGSI_OPCODE_BREAKC }, + { 0, 1, 0, 0, "KIL", TGSI_OPCODE_KIL }, + { 0, 0, 0, 0, "END", TGSI_OPCODE_END }, + { 1, 1, 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; } diff --git a/src/gallium/auxiliary/tgsi/tgsi_info.h b/src/gallium/auxiliary/tgsi/tgsi_info.h index 077e25acd7f..16577598bb0 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_info.h +++ b/src/gallium/auxiliary/tgsi/tgsi_info.h @@ -41,8 +41,7 @@ struct tgsi_opcode_info boolean is_tex; boolean is_branch; const char *mnemonic; - const char *alt_mnemonic1; - const char *alt_mnemonic2; + uint opcode; }; const struct tgsi_opcode_info * diff --git a/src/gallium/auxiliary/tgsi/tgsi_parse.c b/src/gallium/auxiliary/tgsi/tgsi_parse.c index 7f2cfb7988f..4870f82b6bd 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 a289e26e3ac..1035bda1a87 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 0c64ae57131..8fa21f6c408 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ppc.c +++ b/src/gallium/auxiliary/tgsi/tgsi_ppc.c @@ -619,17 +619,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; @@ -1111,10 +1111,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: @@ -1333,7 +1333,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 6f1f5c2b4b0..cb62a95fc0a 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 @@ -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_LOOP: + case TGSI_OPCODE_ENDLOOP: + 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_LOOP: + 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 ba2bfdef062..16848f7cc5e 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_sse2.c +++ b/src/gallium/auxiliary/tgsi/tgsi_sse2.c @@ -32,6 +32,7 @@ #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 @@ -100,37 +101,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 +157,7 @@ get_immediate_base( void ) { return x86_make_reg( file_REG32, - reg_DI ); + reg_DX ); } @@ -168,6 +187,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 +269,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 +550,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 +570,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 +582,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 +641,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 +873,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 +904,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 +950,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 +974,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 +1005,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 +1071,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 +1115,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 +1198,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 +1221,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 +1241,12 @@ emit_sub( make_xmm( xmm_src ) ); } + + + + + + /** * Register fetch. */ @@ -1298,20 +1405,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 +1582,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 +1597,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 ) ); } } @@ -1573,7 +1817,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, @@ -1820,8 +2064,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 ); @@ -1841,8 +2084,7 @@ emit_instruction( 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 */ @@ -1857,16 +2099,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 ); @@ -1878,8 +2111,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 ); @@ -1895,8 +2127,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 ) { @@ -1904,8 +2135,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 ) { @@ -1913,18 +2143,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 ); @@ -1970,10 +2198,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 ); @@ -2086,21 +2310,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: @@ -2198,7 +2408,7 @@ emit_instruction( break; case TGSI_OPCODE_TXB: - return 0; + emit_tex( func, inst, TRUE, FALSE ); break; case TGSI_OPCODE_NRM: @@ -2306,9 +2516,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; @@ -2488,7 +2702,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 ) { @@ -2503,7 +2717,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 ) ); @@ -2545,28 +2762,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 ); @@ -2583,7 +2802,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 ) ); @@ -2607,20 +2826,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 @@ -2634,7 +2846,6 @@ tgsi_emit_sse2( boolean do_swizzles ) { struct tgsi_parse_context parse; - boolean instruction_phase = FALSE; unsigned ok = 1; uint num_immediates = 0; @@ -2646,74 +2857,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 ); @@ -2727,17 +2912,6 @@ 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 ); @@ -2759,7 +2933,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", @@ -2781,18 +2955,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 af838b2a25b..d81ee3d00ec 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 a76bbc91400..d438450b1e4 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/util/Makefile b/src/gallium/auxiliary/util/Makefile index 2995aba1b91..6a8eb73e84a 100644 --- a/src/gallium/auxiliary/util/Makefile +++ b/src/gallium/auxiliary/util/Makefile @@ -16,6 +16,7 @@ C_SOURCES = \ u_hash.c \ u_keymap.c \ u_linear.c \ + u_network.c \ u_math.c \ u_mm.c \ u_rect.c \ diff --git a/src/gallium/auxiliary/util/SConscript b/src/gallium/auxiliary/util/SConscript index d3ac7f747fd..fb142eebca8 100644 --- a/src/gallium/auxiliary/util/SConscript +++ b/src/gallium/auxiliary/util/SConscript @@ -17,6 +17,7 @@ util = env.ConvenienceLibrary( '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 41cd38171fa..47c16b1c927 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_handle_table.c b/src/gallium/auxiliary/util/u_handle_table.c index 6da7353e259..3703718a621 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 2f83e318e44..8c2a8f454cc 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 3f70809efdc..508a2ee0634 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_mm.c b/src/gallium/auxiliary/util/u_mm.c index 151a480d34d..4b75d4ba1d0 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 ce20e487635..6b158aae6e4 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 00000000000..07d804ecdbf --- /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) +# 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) + 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) + 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 00000000000..14d3884427e --- /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) +# 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 d7c3995dbf0..a9b533eea70 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_time.c b/src/gallium/auxiliary/util/u_time.c index 5268cbf79ce..c16cdd0b226 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) #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) 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) 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) 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) 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) 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 6bca6077a2a..7a5c54d9b23 100644 --- a/src/gallium/auxiliary/util/u_time.h +++ b/src/gallium/auxiliary/util/u_time.h @@ -38,7 +38,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) #include <time.h> /* timeval */ #include <unistd.h> /* usleep */ #endif @@ -58,7 +58,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) struct timeval tv; #else int64_t counter; @@ -89,7 +89,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) #define util_time_sleep usleep #else void diff --git a/src/gallium/drivers/cell/ppu/cell_gen_fp.c b/src/gallium/drivers/cell/ppu/cell_gen_fp.c index 5a889a6119d..7cd5656a7e6 100644 --- a/src/gallium/drivers/cell/ppu/cell_gen_fp.c +++ b/src/gallium/drivers/cell/ppu/cell_gen_fp.c @@ -1875,9 +1875,9 @@ emit_immediate(struct codegen *gen, const struct tgsi_full_immediate *immed) assert(gen->num_imm < MAX_TEMPS); for (ch = 0; ch < 4; ch++) { - float val = immed->u.ImmediateFloat32[ch].Float; + float val = immed->u[ch].Float; - if (ch > 0 && val == immed->u.ImmediateFloat32[ch - 1].Float) { + if (ch > 0 && val == immed->u[ch - 1].Float) { /* re-use previous register */ gen->imm_regs[gen->num_imm][ch] = gen->imm_regs[gen->num_imm][ch - 1]; } diff --git a/src/gallium/drivers/cell/spu/spu_exec.c b/src/gallium/drivers/cell/spu/spu_exec.c index e27df2dfb38..570553e1d68 100644 --- a/src/gallium/drivers/cell/spu/spu_exec.c +++ b/src/gallium/drivers/cell/spu/spu_exec.c @@ -952,7 +952,6 @@ exec_instruction( break; case TGSI_OPCODE_RCP: - /* TGSI_OPCODE_RECIP */ FETCH( &r[0], 0, CHAN_X ); r[0].q = micro_div(mach->Temps[TEMP_1_I].xyzw[TEMP_1_C].q, r[0].q); FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { @@ -961,7 +960,6 @@ exec_instruction( break; case TGSI_OPCODE_RSQ: - /* TGSI_OPCODE_RECIPSQRT */ FETCH( &r[0], 0, CHAN_X ); r[0].q = micro_sqrt(r[0].q); r[0].q = micro_div(mach->Temps[TEMP_1_I].xyzw[TEMP_1_C].q, r[0].q); @@ -1115,7 +1113,6 @@ exec_instruction( break; case TGSI_OPCODE_MAD: - /* TGSI_OPCODE_MADD */ FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { FETCH( &r[0], 0, chan_index ); FETCH( &r[1], 1, chan_index ); @@ -1136,8 +1133,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); @@ -1158,21 +1154,11 @@ exec_instruction( ASSERT (0); break; - case TGSI_OPCODE_DOT2ADD: - /* TGSI_OPCODE_DP2A */ + case TGSI_OPCODE_DP2A: ASSERT (0); break; - case TGSI_OPCODE_INDEX: - ASSERT (0); - break; - - case TGSI_OPCODE_NEGATE: - 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 ); r[0].q = micro_frc(r[0].q); @@ -1184,8 +1170,7 @@ exec_instruction( ASSERT (0); break; - case TGSI_OPCODE_FLOOR: - /* TGSI_OPCODE_FLR */ + case TGSI_OPCODE_FLR: FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { FETCH( &r[0], 0, chan_index ); r[0].q = micro_flr(r[0].q); @@ -1201,8 +1186,7 @@ exec_instruction( } break; - case TGSI_OPCODE_EXPBASE2: - /* TGSI_OPCODE_EX2 */ + case TGSI_OPCODE_EX2: FETCH(&r[0], 0, CHAN_X); r[0].q = micro_pow(mach->Temps[TEMP_2_I].xyzw[TEMP_2_C].q, r[0].q); @@ -1212,8 +1196,7 @@ exec_instruction( } break; - case TGSI_OPCODE_LOGBASE2: - /* TGSI_OPCODE_LG2 */ + case TGSI_OPCODE_LG2: FETCH( &r[0], 0, CHAN_X ); r[0].q = micro_lg2(r[0].q); FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { @@ -1221,8 +1204,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); @@ -1233,7 +1215,7 @@ exec_instruction( } break; - case TGSI_OPCODE_CROSSPRODUCT: + case TGSI_OPCODE_XPD: /* TGSI_OPCODE_XPD */ FETCH(&r[0], 0, CHAN_Y); FETCH(&r[1], 1, CHAN_Z); @@ -1275,10 +1257,6 @@ exec_instruction( } break; - case TGSI_OPCODE_MULTIPLYMATRIX: - ASSERT (0); - break; - case TGSI_OPCODE_ABS: FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { FETCH(&r[0], 0, chan_index); diff --git a/src/gallium/drivers/cell/spu/spu_render.c b/src/gallium/drivers/cell/spu/spu_render.c index 7c225e2f27c..5ffb7073abf 100644 --- a/src/gallium/drivers/cell/spu/spu_render.c +++ b/src/gallium/drivers/cell/spu/spu_render.c @@ -32,6 +32,7 @@ #include "spu_main.h" #include "spu_render.h" +#include "spu_shuffle.h" #include "spu_tri.h" #include "spu_tile.h" #include "cell/common.h" @@ -267,15 +268,75 @@ cmd_render(const struct cell_command_render *render, uint *pos_incr) uint drawn = 0; - /* loop over tris */ - for (j = 0; j < render->num_indexes; j += 3) { - const float *v0, *v1, *v2; - - v0 = (const float *) (vertices + indexes[j+0] * vertex_size); - v1 = (const float *) (vertices + indexes[j+1] * vertex_size); - v2 = (const float *) (vertices + indexes[j+2] * vertex_size); - - drawn += tri_draw(v0, v1, v2, tx, ty); + const qword vertex_sizes = (qword)spu_splats(vertex_size); + const qword verticess = (qword)spu_splats((uint)vertices); + + ASSERT_ALIGN16(&indexes[0]); + + const uint num_indexes = render->num_indexes; + + /* loop over tris + * &indexes[0] will be 16 byte aligned. This loop is heavily unrolled + * avoiding variable rotates when extracting vertex indices. + */ + for (j = 0; j < num_indexes; j += 24) { + /* Load three vectors, containing 24 ushort indices */ + const qword* lower_qword = (qword*)&indexes[j]; + const qword indices0 = lower_qword[0]; + const qword indices1 = lower_qword[1]; + const qword indices2 = lower_qword[2]; + + /* stores three indices for each tri n in slots 0, 1 and 2 of vsn */ + /* Straightforward rotates for these */ + qword vs0 = indices0; + qword vs1 = si_shlqbyi(indices0, 6); + qword vs3 = si_shlqbyi(indices1, 2); + qword vs4 = si_shlqbyi(indices1, 8); + qword vs6 = si_shlqbyi(indices2, 4); + qword vs7 = si_shlqbyi(indices2, 10); + + /* For tri 2 and 5, the three indices are split across two machine + * words - rotate and combine */ + const qword tmp2a = si_shlqbyi(indices0, 12); + const qword tmp2b = si_rotqmbyi(indices1, 12|16); + qword vs2 = si_selb(tmp2a, tmp2b, si_fsmh(si_from_uint(0x20))); + + const qword tmp5a = si_shlqbyi(indices1, 14); + const qword tmp5b = si_rotqmbyi(indices2, 14|16); + qword vs5 = si_selb(tmp5a, tmp5b, si_fsmh(si_from_uint(0x60))); + + /* unpack indices from halfword slots to word slots */ + vs0 = si_shufb(vs0, vs0, SHUFB8(0,A,0,B,0,C,0,0)); + vs1 = si_shufb(vs1, vs1, SHUFB8(0,A,0,B,0,C,0,0)); + vs2 = si_shufb(vs2, vs2, SHUFB8(0,A,0,B,0,C,0,0)); + vs3 = si_shufb(vs3, vs3, SHUFB8(0,A,0,B,0,C,0,0)); + vs4 = si_shufb(vs4, vs4, SHUFB8(0,A,0,B,0,C,0,0)); + vs5 = si_shufb(vs5, vs5, SHUFB8(0,A,0,B,0,C,0,0)); + vs6 = si_shufb(vs6, vs6, SHUFB8(0,A,0,B,0,C,0,0)); + vs7 = si_shufb(vs7, vs7, SHUFB8(0,A,0,B,0,C,0,0)); + + /* Calculate address of vertex in vertices[] */ + vs0 = si_mpya(vs0, vertex_sizes, verticess); + vs1 = si_mpya(vs1, vertex_sizes, verticess); + vs2 = si_mpya(vs2, vertex_sizes, verticess); + vs3 = si_mpya(vs3, vertex_sizes, verticess); + vs4 = si_mpya(vs4, vertex_sizes, verticess); + vs5 = si_mpya(vs5, vertex_sizes, verticess); + vs6 = si_mpya(vs6, vertex_sizes, verticess); + vs7 = si_mpya(vs7, vertex_sizes, verticess); + + /* Select the appropriate call based on the number of vertices + * remaining */ + switch(num_indexes - j) { + default: drawn += tri_draw(vs7, tx, ty); + case 21: drawn += tri_draw(vs6, tx, ty); + case 18: drawn += tri_draw(vs5, tx, ty); + case 15: drawn += tri_draw(vs4, tx, ty); + case 12: drawn += tri_draw(vs3, tx, ty); + case 9: drawn += tri_draw(vs2, tx, ty); + case 6: drawn += tri_draw(vs1, tx, ty); + case 3: drawn += tri_draw(vs0, tx, ty); + } } //printf("SPU %u: drew %u of %u\n", spu.init.id, drawn, render->num_indexes/3); diff --git a/src/gallium/drivers/cell/spu/spu_tri.c b/src/gallium/drivers/cell/spu/spu_tri.c index d727268475e..58be001be4c 100644 --- a/src/gallium/drivers/cell/spu/spu_tri.c +++ b/src/gallium/drivers/cell/spu/spu_tri.c @@ -133,7 +133,15 @@ struct setup_stage { uint tx, ty; /**< position of current tile (x, y) */ - int cliprect_minx, cliprect_maxx, cliprect_miny, cliprect_maxy; + union { + struct { + int cliprect_minx; + int cliprect_miny; + int cliprect_maxx; + int cliprect_maxy; + }; + qword cliprect; + }; struct interp_coef coef[PIPE_MAX_SHADER_INPUTS]; @@ -432,6 +440,41 @@ print_vertex(const struct vertex_header *v) } #endif +/* Returns the minimum of each slot of two vec_float4s as qwords. + * i.e. return[n] = min(q0[n],q1[n]); + */ +static qword +minfq(qword q0, qword q1) +{ + const qword q0q1m = si_fcgt(q0, q1); + return si_selb(q0, q1, q0q1m); +} + +/* Returns the minimum of each slot of three vec_float4s as qwords. + * i.e. return[n] = min(q0[n],q1[n],q2[n]); + */ +static qword +min3fq(qword q0, qword q1, qword q2) +{ + return minfq(minfq(q0, q1), q2); +} + +/* Returns the maximum of each slot of two vec_float4s as qwords. + * i.e. return[n] = min(q0[n],q1[n],q2[n]); + */ +static qword +maxfq(qword q0, qword q1) { + const qword q0q1m = si_fcgt(q0, q1); + return si_selb(q1, q0, q0q1m); +} + +/* Returns the maximum of each slot of three vec_float4s as qwords. + * i.e. return[n] = min(q0[n],q1[n],q2[n]); + */ +static qword +max3fq(qword q0, qword q1, qword q2) { + return maxfq(maxfq(q0, q1), q2); +} /** * Sort vertices from top to bottom. @@ -440,9 +483,7 @@ print_vertex(const struct vertex_header *v) * \return FALSE if tri is totally outside tile, TRUE otherwise */ static boolean -setup_sort_vertices(const struct vertex_header *v0, - const struct vertex_header *v1, - const struct vertex_header *v2) +setup_sort_vertices(const qword vs) { float area, sign; @@ -455,57 +496,57 @@ setup_sort_vertices(const struct vertex_header *v0, } #endif - /* determine bottom to top order of vertices */ { + /* Load the float values for various processing... */ + const qword f0 = (qword)(((const struct vertex_header*)si_to_ptr(vs))->data[0]); + const qword f1 = (qword)(((const struct vertex_header*)si_to_ptr(si_rotqbyi(vs, 4)))->data[0]); + const qword f2 = (qword)(((const struct vertex_header*)si_to_ptr(si_rotqbyi(vs, 8)))->data[0]); + + /* Check if triangle is completely outside the tile bounds + * Find the min and max x and y positions of the three poits */ + const qword minf = min3fq(f0, f1, f2); + const qword maxf = max3fq(f0, f1, f2); + + /* Compare min and max against cliprect vals */ + const qword maxsmins = si_shufb(maxf, minf, SHUFB4(A,B,a,b)); + const qword outside = si_fcgt(maxsmins, si_csflt(setup.cliprect, 0)); + + /* Use a little magic to work out of the tri is visible or not */ + if(si_to_uint(si_xori(si_gb(outside), 0xc))) return FALSE; + + /* determine bottom to top order of vertices */ /* A table of shuffle patterns for putting vertex_header pointers into correct order. Quite magical. */ - const vec_uchar16 sort_order_patterns[] = { - SHUFFLE4(A,B,C,C), - SHUFFLE4(C,A,B,C), - SHUFFLE4(A,C,B,C), - SHUFFLE4(B,C,A,C), - SHUFFLE4(B,A,C,C), - SHUFFLE4(C,B,A,C) }; - - /* The vertex_header pointers, packed for easy shuffling later */ - const vec_uint4 vs = {(unsigned)v0, (unsigned)v1, (unsigned)v2}; + const qword sort_order_patterns[] = { + SHUFB4(A,B,C,C), + SHUFB4(C,A,B,C), + SHUFB4(A,C,B,C), + SHUFB4(B,C,A,C), + SHUFB4(B,A,C,C), + SHUFB4(C,B,A,C) }; /* Collate y values into two vectors for comparison. Using only one shuffle constant! ;) */ - const vec_float4 y_02_ = spu_shuffle(v0->data[0], v2->data[0], SHUFFLE4(0,B,b,C)); - const vec_float4 y_10_ = spu_shuffle(v1->data[0], v0->data[0], SHUFFLE4(0,B,b,C)); - const vec_float4 y_012 = spu_shuffle(y_02_, v1->data[0], SHUFFLE4(0,B,b,C)); - const vec_float4 y_120 = spu_shuffle(y_10_, v2->data[0], SHUFFLE4(0,B,b,C)); + const qword y_02_ = si_shufb(f0, f2, SHUFB4(0,B,b,C)); + const qword y_10_ = si_shufb(f1, f0, SHUFB4(0,B,b,C)); + const qword y_012 = si_shufb(y_02_, f1, SHUFB4(0,B,b,C)); + const qword y_120 = si_shufb(y_10_, f2, SHUFB4(0,B,b,C)); /* Perform comparison: {y0,y1,y2} > {y1,y2,y0} */ - const vec_uint4 compare = spu_cmpgt(y_012, y_120); + const qword compare = si_fcgt(y_012, y_120); /* Compress the result of the comparison into 4 bits */ - const vec_uint4 gather = spu_gather(compare); + const qword gather = si_gb(compare); /* Subtract one to attain the index into the LUT. Magical. */ - const unsigned int index = spu_extract(gather, 0) - 1; + const unsigned int index = si_to_uint(gather) - 1; /* Load the appropriate pattern and construct the desired vector. */ - setup.vertex_headers = (qword)spu_shuffle(vs, vs, sort_order_patterns[index]); + setup.vertex_headers = si_shufb(vs, vs, sort_order_patterns[index]); /* Using the result of the comparison, set sign. Very magical. */ - sign = ((si_to_uint(si_cntb((qword)gather)) == 2) ? 1.0f : -1.0f); + sign = ((si_to_uint(si_cntb(gather)) == 2) ? 1.0f : -1.0f); } - /* Check if triangle is completely outside the tile bounds */ - if (spu_extract(setup.vmin->data[0], 1) > setup.cliprect_maxy) - return FALSE; - if (spu_extract(setup.vmax->data[0], 1) < setup.cliprect_miny) - return FALSE; - if (spu_extract(setup.vmin->data[0], 0) < setup.cliprect_minx && - spu_extract(setup.vmid->data[0], 0) < setup.cliprect_minx && - spu_extract(setup.vmax->data[0], 0) < setup.cliprect_minx) - return FALSE; - if (spu_extract(setup.vmin->data[0], 0) > setup.cliprect_maxx && - spu_extract(setup.vmid->data[0], 0) > setup.cliprect_maxx && - spu_extract(setup.vmax->data[0], 0) > setup.cliprect_maxx) - return FALSE; - setup.ebot.ds = spu_sub(setup.vmid->data[0], setup.vmin->data[0]); setup.emaj.ds = spu_sub(setup.vmax->data[0], setup.vmin->data[0]); setup.etop.ds = spu_sub(setup.vmax->data[0], setup.vmid->data[0]); @@ -761,21 +802,19 @@ subtriangle(struct edge *eleft, struct edge *eright, unsigned lines) * The tile data should have already been fetched. */ boolean -tri_draw(const float *v0, const float *v1, const float *v2, +tri_draw(const qword vs, uint tx, uint ty) { setup.tx = tx; setup.ty = ty; /* set clipping bounds to tile bounds */ - setup.cliprect_minx = tx * TILE_SIZE; - setup.cliprect_miny = ty * TILE_SIZE; - setup.cliprect_maxx = (tx + 1) * TILE_SIZE; - setup.cliprect_maxy = (ty + 1) * TILE_SIZE; - - if (!setup_sort_vertices((struct vertex_header *) v0, - (struct vertex_header *) v1, - (struct vertex_header *) v2)) { + const qword clipbase = (qword)((vec_uint4){tx, ty}); + const qword clipmin = si_mpyui(clipbase, TILE_SIZE); + const qword clipmax = si_ai(clipmin, TILE_SIZE); + setup.cliprect = si_shufb(clipmin, clipmax, SHUFB4(A,B,a,b)); + + if(!setup_sort_vertices(vs)) { return FALSE; /* totally clipped */ } diff --git a/src/gallium/drivers/cell/spu/spu_tri.h b/src/gallium/drivers/cell/spu/spu_tri.h index aa694dd7c93..82e3b19ad7e 100644 --- a/src/gallium/drivers/cell/spu/spu_tri.h +++ b/src/gallium/drivers/cell/spu/spu_tri.h @@ -31,7 +31,7 @@ extern boolean -tri_draw(const float *v0, const float *v1, const float *v2, uint tx, uint ty); +tri_draw(const qword vs, uint tx, uint ty); #endif /* SPU_TRI_H */ diff --git a/src/gallium/drivers/i915simple/i915_fpc_translate.c b/src/gallium/drivers/i915simple/i915_fpc_translate.c index 961c1bf2134..89504ced276 100644 --- a/src/gallium/drivers/i915simple/i915_fpc_translate.c +++ b/src/gallium/drivers/i915simple/i915_fpc_translate.c @@ -975,8 +975,9 @@ i915_translate_instructions(struct i915_fp_compile *p, = &parse.FullToken.FullImmediate; const uint pos = p->num_immediates++; uint j; + assert( imm->Immediate.NrTokens <= 4 + 1 ); for (j = 0; j < imm->Immediate.NrTokens - 1; j++) { - p->immediates[pos][j] = imm->u.ImmediateFloat32[j].Float; + p->immediates[pos][j] = imm->u[j].Float; } } break; diff --git a/src/gallium/drivers/i965simple/brw_draw.c b/src/gallium/drivers/i965simple/brw_draw.c index 648aaa0da52..49d80cb41c5 100644 --- a/src/gallium/drivers/i965simple/brw_draw.c +++ b/src/gallium/drivers/i965simple/brw_draw.c @@ -35,6 +35,7 @@ #include "pipe/p_context.h" #include "pipe/internal/p_winsys_screen.h" +#include "util/u_prim.h" static unsigned hw_prim[PIPE_PRIM_POLYGON+1] = { _3DPRIM_POINTLIST, @@ -50,20 +51,6 @@ static unsigned hw_prim[PIPE_PRIM_POLYGON+1] = { }; -static const int reduced_prim[PIPE_PRIM_POLYGON+1] = { - PIPE_PRIM_POINTS, - PIPE_PRIM_LINES, - PIPE_PRIM_LINES, - PIPE_PRIM_LINES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES -}; - - /* When the primitive changes, set a state bit and re-validate. Not * the nicest and would rather deal with this by having all the * programs be immune to the active primitive (ie. cope with all @@ -85,8 +72,8 @@ static void brw_set_prim(struct brw_context *brw, int prim) brw->primitive = prim; brw->state.dirty.brw |= BRW_NEW_PRIMITIVE; - if (reduced_prim[prim] != brw->reduced_primitive) { - brw->reduced_primitive = reduced_prim[prim]; + if (u_reduced_prim(prim) != brw->reduced_primitive) { + brw->reduced_primitive = u_reduced_prim(prim); brw->state.dirty.brw |= BRW_NEW_REDUCED_PRIMITIVE; } diff --git a/src/gallium/drivers/i965simple/brw_vs_emit.c b/src/gallium/drivers/i965simple/brw_vs_emit.c index e03d6534821..3ee82d95b3a 100644 --- a/src/gallium/drivers/i965simple/brw_vs_emit.c +++ b/src/gallium/drivers/i965simple/brw_vs_emit.c @@ -1294,10 +1294,10 @@ void brw_vs_emit(struct brw_vs_compile *c) case TGSI_TOKEN_TYPE_IMMEDIATE: { struct tgsi_full_immediate *imm = &parse.FullToken.FullImmediate; assert(imm->Immediate.NrTokens == 4 + 1); - c->prog_data.imm_buf[c->prog_data.num_imm][0] = imm->u.ImmediateFloat32[0].Float; - c->prog_data.imm_buf[c->prog_data.num_imm][1] = imm->u.ImmediateFloat32[1].Float; - c->prog_data.imm_buf[c->prog_data.num_imm][2] = imm->u.ImmediateFloat32[2].Float; - c->prog_data.imm_buf[c->prog_data.num_imm][3] = imm->u.ImmediateFloat32[3].Float; + c->prog_data.imm_buf[c->prog_data.num_imm][0] = imm->u[0].Float; + c->prog_data.imm_buf[c->prog_data.num_imm][1] = imm->u[1].Float; + c->prog_data.imm_buf[c->prog_data.num_imm][2] = imm->u[2].Float; + c->prog_data.imm_buf[c->prog_data.num_imm][3] = imm->u[3].Float; c->prog_data.num_imm++; } break; diff --git a/src/gallium/drivers/identity/Makefile b/src/gallium/drivers/identity/Makefile new file mode 100644 index 00000000000..e32b9102e59 --- /dev/null +++ b/src/gallium/drivers/identity/Makefile @@ -0,0 +1,12 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = identity + +C_SOURCES = \ + id_objects.c \ + id_context.c \ + id_screen.c \ + id_drm.c + +include ../../Makefile.template diff --git a/src/gallium/drivers/identity/SConscript b/src/gallium/drivers/identity/SConscript new file mode 100644 index 00000000000..7f079dd0a8b --- /dev/null +++ b/src/gallium/drivers/identity/SConscript @@ -0,0 +1,13 @@ +Import('*') + +env = env.Clone() + +identity = env.ConvenienceLibrary( + target = 'identity', + source = [ + 'id_screen.c', + 'id_context.c', + 'id_objects.c', + ]) + +Export('identity') diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c new file mode 100644 index 00000000000..a500ec60454 --- /dev/null +++ b/src/gallium/drivers/identity/id_context.c @@ -0,0 +1,719 @@ +/************************************************************************** + * + * 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 "pipe/p_context.h" +#include "util/u_memory.h" + +#include "id_public.h" +#include "id_context.h" +#include "id_objects.h" + + +static void +identity_destroy(struct pipe_context *_pipe) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->destroy(pipe); + + free(id_pipe); +} + +static void +identity_set_edgeflags(struct pipe_context *_pipe, + const unsigned *bitfield) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->set_edgeflags(pipe, + bitfield); +} + +static boolean +identity_draw_arrays(struct pipe_context *_pipe, + unsigned prim, + unsigned start, + unsigned count) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + return pipe->draw_arrays(pipe, + prim, + start, + count); +} + +static boolean +identity_draw_elements(struct pipe_context *_pipe, + struct pipe_buffer *_indexBuffer, + unsigned indexSize, + unsigned prim, + unsigned start, + unsigned count) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct identity_buffer *id_buffer = identity_buffer(_indexBuffer); + struct pipe_context *pipe = id_pipe->pipe; + struct pipe_buffer *indexBuffer = id_buffer->buffer; + + return pipe->draw_elements(pipe, + indexBuffer, + indexSize, + prim, + start, + count); +} + +static boolean +identity_draw_range_elements(struct pipe_context *_pipe, + struct pipe_buffer *_indexBuffer, + unsigned indexSize, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct identity_buffer *id_buffer = identity_buffer(_indexBuffer); + struct pipe_context *pipe = id_pipe->pipe; + struct pipe_buffer *indexBuffer = id_buffer->buffer; + + return pipe->draw_range_elements(pipe, + indexBuffer, + indexSize, + minIndex, + maxIndex, + mode, + start, + count); +} + +static struct pipe_query * +identity_create_query(struct pipe_context *_pipe, + unsigned query_type) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + return pipe->create_query(pipe, + query_type); +} + +static void +identity_destroy_query(struct pipe_context *_pipe, + struct pipe_query *query) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->destroy_query(pipe, + query); +} + +static void +identity_begin_query(struct pipe_context *_pipe, + struct pipe_query *query) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->begin_query(pipe, + query); +} + +static void +identity_end_query(struct pipe_context *_pipe, + struct pipe_query *query) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->end_query(pipe, + query); +} + +static boolean +identity_get_query_result(struct pipe_context *_pipe, + struct pipe_query *query, + boolean wait, + uint64_t *result) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + return pipe->get_query_result(pipe, + query, + wait, + result); +} + +static void * +identity_create_blend_state(struct pipe_context *_pipe, + const struct pipe_blend_state *blend) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + return pipe->create_blend_state(pipe, + blend); +} + +static void +identity_bind_blend_state(struct pipe_context *_pipe, + void *blend) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->bind_blend_state(pipe, + blend); +} + +static void +identity_delete_blend_state(struct pipe_context *_pipe, + void *blend) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->delete_blend_state(pipe, + blend); +} + +static void * +identity_create_sampler_state(struct pipe_context *_pipe, + const struct pipe_sampler_state *sampler) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + return pipe->create_sampler_state(pipe, + sampler); +} + +static void +identity_bind_sampler_states(struct pipe_context *_pipe, + unsigned num, + void **samplers) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->bind_sampler_states(pipe, + num, + samplers); +} + +static void +identity_delete_sampler_state(struct pipe_context *_pipe, + void *sampler) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->delete_sampler_state(pipe, + sampler); +} + +static void * +identity_create_rasterizer_state(struct pipe_context *_pipe, + const struct pipe_rasterizer_state *rasterizer) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + return pipe->create_rasterizer_state(pipe, + rasterizer); +} + +static void +identity_bind_rasterizer_state(struct pipe_context *_pipe, + void *rasterizer) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->bind_rasterizer_state(pipe, + rasterizer); +} + +static void +identity_delete_rasterizer_state(struct pipe_context *_pipe, + void *rasterizer) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->delete_rasterizer_state(pipe, + rasterizer); +} + +static void * +identity_create_depth_stencil_alpha_state(struct pipe_context *_pipe, + const struct pipe_depth_stencil_alpha_state *depth_stencil_alpha) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + return pipe->create_depth_stencil_alpha_state(pipe, + depth_stencil_alpha); +} + +static void +identity_bind_depth_stencil_alpha_state(struct pipe_context *_pipe, + void *depth_stencil_alpha) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->bind_depth_stencil_alpha_state(pipe, + depth_stencil_alpha); +} + +static void +identity_delete_depth_stencil_alpha_state(struct pipe_context *_pipe, + void *depth_stencil_alpha) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->delete_depth_stencil_alpha_state(pipe, + depth_stencil_alpha); +} + +static void * +identity_create_fs_state(struct pipe_context *_pipe, + const struct pipe_shader_state *fs) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + return pipe->create_fs_state(pipe, + fs); +} + +static void +identity_bind_fs_state(struct pipe_context *_pipe, + void *fs) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->bind_fs_state(pipe, + fs); +} + +static void +identity_delete_fs_state(struct pipe_context *_pipe, + void *fs) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->delete_fs_state(pipe, + fs); +} + +static void * +identity_create_vs_state(struct pipe_context *_pipe, + const struct pipe_shader_state *vs) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + return pipe->create_vs_state(pipe, + vs); +} + +static void +identity_bind_vs_state(struct pipe_context *_pipe, + void *vs) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->bind_vs_state(pipe, + vs); +} + +static void +identity_delete_vs_state(struct pipe_context *_pipe, + void *vs) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->delete_vs_state(pipe, + vs); +} + +static void +identity_set_blend_color(struct pipe_context *_pipe, + const struct pipe_blend_color *blend_color) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->set_blend_color(pipe, + blend_color); +} + +static void +identity_set_clip_state(struct pipe_context *_pipe, + const struct pipe_clip_state *clip) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->set_clip_state(pipe, + clip); +} + +static void +identity_set_constant_buffer(struct pipe_context *_pipe, + uint shader, + uint index, + const struct pipe_constant_buffer *_buffer) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + struct pipe_constant_buffer unwrapped_buffer; + struct pipe_constant_buffer *buffer = NULL; + + /* unwrap the input state */ + if (_buffer) { + unwrapped_buffer.buffer = identity_buffer_unwrap(_buffer->buffer); + buffer = &unwrapped_buffer; + } + + pipe->set_constant_buffer(pipe, + shader, + index, + buffer); +} + +static void +identity_set_framebuffer_state(struct pipe_context *_pipe, + const struct pipe_framebuffer_state *_state) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + struct pipe_framebuffer_state unwrapped_state; + struct pipe_framebuffer_state *state = NULL; + unsigned i; + + /* unwrap the input state */ + if (_state) { + memcpy(&unwrapped_state, _state, sizeof(unwrapped_state)); + for(i = 0; i < _state->nr_cbufs; i++) + unwrapped_state.cbufs[i] = identity_surface_unwrap(_state->cbufs[i]); + for (; i < PIPE_MAX_COLOR_BUFS; i++) + unwrapped_state.cbufs[i] = NULL; + unwrapped_state.zsbuf = identity_surface_unwrap(_state->zsbuf); + state = &unwrapped_state; + } + + pipe->set_framebuffer_state(pipe, + state); +} + +static void +identity_set_polygon_stipple(struct pipe_context *_pipe, + const struct pipe_poly_stipple *poly_stipple) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->set_polygon_stipple(pipe, + poly_stipple); +} + +static void +identity_set_scissor_state(struct pipe_context *_pipe, + const struct pipe_scissor_state *scissor) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->set_scissor_state(pipe, + scissor); +} + +static void +identity_set_viewport_state(struct pipe_context *_pipe, + const struct pipe_viewport_state *viewport) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->set_viewport_state(pipe, + viewport); +} + +static void +identity_set_sampler_textures(struct pipe_context *_pipe, + unsigned num_textures, + struct pipe_texture **_textures) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + struct pipe_texture *unwrapped_textures[PIPE_MAX_SAMPLERS]; + struct pipe_texture **textures = NULL; + unsigned i; + + if (_textures) { + for (i = 0; i < num_textures; i++) + unwrapped_textures[i] = identity_texture_unwrap(_textures[i]); + for (; i < PIPE_MAX_SAMPLERS; i++) + unwrapped_textures[i] = NULL; + + textures = unwrapped_textures; + } + + pipe->set_sampler_textures(pipe, + num_textures, + _textures); +} + +static void +identity_set_vertex_buffers(struct pipe_context *_pipe, + unsigned num_buffers, + const struct pipe_vertex_buffer *_buffers) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + struct pipe_vertex_buffer unwrapped_buffers[PIPE_MAX_SHADER_INPUTS]; + struct pipe_vertex_buffer *buffers = NULL; + unsigned i; + + if (num_buffers) { + memcpy(unwrapped_buffers, _buffers, num_buffers * sizeof(*_buffers)); + for (i = 0; i < num_buffers; i++) + unwrapped_buffers[i].buffer = identity_buffer_unwrap(_buffers[i].buffer); + buffers = unwrapped_buffers; + } + + pipe->set_vertex_buffers(pipe, + num_buffers, + buffers); +} + +static void +identity_set_vertex_elements(struct pipe_context *_pipe, + unsigned num_elements, + const struct pipe_vertex_element *vertex_elements) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->set_vertex_elements(pipe, + num_elements, + vertex_elements); +} + +static void +identity_surface_copy(struct pipe_context *_pipe, + struct pipe_surface *_dst, + unsigned dstx, + unsigned dsty, + struct pipe_surface *_src, + unsigned srcx, + unsigned srcy, + unsigned width, + unsigned height) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct identity_surface *id_surface_dst = identity_surface(_dst); + struct identity_surface *id_surface_src = identity_surface(_src); + struct pipe_context *pipe = id_pipe->pipe; + struct pipe_surface *dst = id_surface_dst->surface; + struct pipe_surface *src = id_surface_src->surface; + + pipe->surface_copy(pipe, + dst, + dstx, + dsty, + src, + srcx, + srcy, + width, + height); +} + +static void +identity_surface_fill(struct pipe_context *_pipe, + struct pipe_surface *_dst, + unsigned dstx, + unsigned dsty, + unsigned width, + unsigned height, + unsigned value) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct identity_surface *id_surface_dst = identity_surface(_dst); + struct pipe_context *pipe = id_pipe->pipe; + struct pipe_surface *dst = id_surface_dst->surface; + + pipe->surface_fill(pipe, + dst, + dstx, + dsty, + width, + height, + value); +} + +static void +identity_clear(struct pipe_context *_pipe, + unsigned buffers, + const float *rgba, + double depth, + unsigned stencil) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->clear(pipe, + buffers, + rgba, + depth, + stencil); +} + +static void +identity_flush(struct pipe_context *_pipe, + unsigned flags, + struct pipe_fence_handle **fence) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->flush(pipe, + flags, + fence); +} + +static unsigned int +identity_is_texture_referenced(struct pipe_context *_pipe, + struct pipe_texture *_texture, + unsigned face, + unsigned level) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct identity_texture *id_texture = identity_texture(_texture); + struct pipe_context *pipe = id_pipe->pipe; + struct pipe_texture *texture = id_texture->texture; + + return pipe->is_texture_referenced(pipe, + texture, + face, + level); +} + +static unsigned int +identity_is_buffer_referenced(struct pipe_context *_pipe, + struct pipe_buffer *_buffer) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct identity_buffer *id_buffer = identity_buffer(_buffer); + struct pipe_context *pipe = id_pipe->pipe; + struct pipe_buffer *buffer = id_buffer->buffer; + + return pipe->is_buffer_referenced(pipe, + buffer); +} + +struct pipe_context * +identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) +{ + struct identity_context *id_pipe; + (void)identity_screen(_screen); + + id_pipe = CALLOC_STRUCT(identity_context); + if (!id_pipe) { + return NULL; + } + + id_pipe->base.winsys = NULL; + id_pipe->base.screen = _screen; + id_pipe->base.priv = pipe->priv; + id_pipe->base.draw = NULL; + + id_pipe->base.destroy = identity_destroy; + id_pipe->base.set_edgeflags = identity_set_edgeflags; + id_pipe->base.draw_arrays = identity_draw_arrays; + id_pipe->base.draw_elements = identity_draw_elements; + id_pipe->base.draw_range_elements = identity_draw_range_elements; + id_pipe->base.create_query = identity_create_query; + id_pipe->base.destroy_query = identity_destroy_query; + id_pipe->base.begin_query = identity_begin_query; + id_pipe->base.end_query = identity_end_query; + id_pipe->base.get_query_result = identity_get_query_result; + id_pipe->base.create_blend_state = identity_create_blend_state; + id_pipe->base.bind_blend_state = identity_bind_blend_state; + id_pipe->base.delete_blend_state = identity_delete_blend_state; + id_pipe->base.create_sampler_state = identity_create_sampler_state; + id_pipe->base.bind_sampler_states = identity_bind_sampler_states; + id_pipe->base.delete_sampler_state = identity_delete_sampler_state; + id_pipe->base.create_rasterizer_state = identity_create_rasterizer_state; + id_pipe->base.bind_rasterizer_state = identity_bind_rasterizer_state; + id_pipe->base.delete_rasterizer_state = identity_delete_rasterizer_state; + id_pipe->base.create_depth_stencil_alpha_state = identity_create_depth_stencil_alpha_state; + id_pipe->base.bind_depth_stencil_alpha_state = identity_bind_depth_stencil_alpha_state; + id_pipe->base.delete_depth_stencil_alpha_state = identity_delete_depth_stencil_alpha_state; + id_pipe->base.create_fs_state = identity_create_fs_state; + id_pipe->base.bind_fs_state = identity_bind_fs_state; + id_pipe->base.delete_fs_state = identity_delete_fs_state; + id_pipe->base.create_vs_state = identity_create_vs_state; + id_pipe->base.bind_vs_state = identity_bind_vs_state; + id_pipe->base.delete_vs_state = identity_delete_vs_state; + id_pipe->base.set_blend_color = identity_set_blend_color; + id_pipe->base.set_clip_state = identity_set_clip_state; + id_pipe->base.set_constant_buffer = identity_set_constant_buffer; + id_pipe->base.set_framebuffer_state = identity_set_framebuffer_state; + id_pipe->base.set_polygon_stipple = identity_set_polygon_stipple; + id_pipe->base.set_scissor_state = identity_set_scissor_state; + id_pipe->base.set_viewport_state = identity_set_viewport_state; + id_pipe->base.set_sampler_textures = identity_set_sampler_textures; + id_pipe->base.set_vertex_buffers = identity_set_vertex_buffers; + id_pipe->base.set_vertex_elements = identity_set_vertex_elements; + id_pipe->base.surface_copy = identity_surface_copy; + id_pipe->base.surface_fill = identity_surface_fill; + id_pipe->base.clear = identity_clear; + id_pipe->base.flush = identity_flush; + id_pipe->base.is_texture_referenced = identity_is_texture_referenced; + id_pipe->base.is_buffer_referenced = identity_is_buffer_referenced; + + id_pipe->pipe = pipe; + + return &id_pipe->base; +} diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_lock.c b/src/gallium/drivers/identity/id_context.h index 92f5bd09c9d..75b73fc7df6 100644 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_lock.c +++ b/src/gallium/drivers/identity/id_context.h @@ -1,8 +1,8 @@ /************************************************************************** - * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * + * 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 @@ -10,64 +10,39 @@ * 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 + * 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 <pipe/p_thread.h> -#include "nouveau_context.h" -#include "nouveau_screen.h" -#include "nouveau_drmif.h" +#ifndef ID_CONTEXT_H +#define ID_CONTEXT_H -pipe_static_mutex(lockMutex); +#include "pipe/p_state.h" +#include "pipe/p_context.h" -/* Lock the hardware and validate our state. - */ -void -LOCK_HARDWARE(struct nouveau_context *nv) -{ - struct nouveau_screen *nv_screen = nv->dri_screen->private; - struct nouveau_device *dev = nv_screen->device; - struct nouveau_device_priv *nvdev = nouveau_device(dev); - char __ret=0; - assert(!nv->locked); - pipe_mutex_lock(lockMutex); +struct identity_context { + struct pipe_context base; /**< base class */ - DRM_CAS(nvdev->lock, nvdev->ctx, - (DRM_LOCK_HELD | nvdev->ctx), __ret); + struct pipe_context *pipe; +}; - if (__ret) { - drmGetLock(nvdev->fd, nvdev->ctx, 0); - nouveau_contended_lock(nv); - } - nv->locked = 1; -} -/* Unlock the hardware using the global current context - */ -void -UNLOCK_HARDWARE(struct nouveau_context *nv) +static INLINE struct identity_context * +identity_context(struct pipe_context *pipe) { - struct nouveau_screen *nv_screen = nv->dri_screen->private; - struct nouveau_device *dev = nv_screen->device; - struct nouveau_device_priv *nvdev = nouveau_device(dev); - - assert(nv->locked); - nv->locked = 0; - - DRM_UNLOCK(nvdev->fd, nvdev->lock, nvdev->ctx); + return (struct identity_context *)pipe; +} - pipe_mutex_unlock(lockMutex); -} +#endif /* ID_CONTEXT_H */ diff --git a/src/gallium/drivers/identity/id_drm.c b/src/gallium/drivers/identity/id_drm.c new file mode 100644 index 00000000000..555220f8531 --- /dev/null +++ b/src/gallium/drivers/identity/id_drm.c @@ -0,0 +1,187 @@ +/************************************************************************** + * + * 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 "state_tracker/drm_api.h" + +#include "util/u_memory.h" +#include "identity/id_drm.h" +#include "identity/id_public.h" +#include "identity/id_screen.h" +#include "identity/id_objects.h" + +struct identity_drm_api +{ + struct drm_api base; + + struct drm_api *api; +}; + +static INLINE struct identity_drm_api * +identity_drm_api(struct drm_api *_api) +{ + return (struct identity_drm_api *)_api; +} + +static struct pipe_screen * +identity_drm_create_screen(struct drm_api *_api, int fd, + struct drm_create_screen_arg *arg) +{ + struct identity_drm_api *id_api = identity_drm_api(_api); + struct drm_api *api = id_api->api; + struct pipe_screen *screen; + + if (arg && arg->mode != DRM_CREATE_NORMAL) + return NULL; + + screen = api->create_screen(api, fd, arg); + + return identity_screen_create(screen); +}; + +static struct pipe_context * +identity_drm_create_context(struct drm_api *_api, + struct pipe_screen *_screen) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct identity_drm_api *id_api = identity_drm_api(_api); + struct pipe_screen *screen = id_screen->screen; + struct drm_api *api = id_api->api; + struct pipe_context *pipe; + + pipe = api->create_context(api, screen); + + pipe = identity_context_create(_screen, pipe); + + return pipe; +}; + +static boolean +identity_drm_buffer_from_texture(struct drm_api *_api, + struct pipe_texture *_texture, + struct pipe_buffer **_buffer, + unsigned *stride) +{ + struct identity_texture *id_texture = identity_texture(_texture); + struct identity_drm_api *id_api = identity_drm_api(_api); + struct pipe_texture *texture = id_texture->texture; + struct drm_api *api = id_api->api; + struct pipe_buffer *buffer = NULL; + boolean result; + + result = api->buffer_from_texture(api, texture, &buffer, stride); + + if (result && _buffer) + buffer = identity_buffer_create(identity_screen(texture->screen), buffer); + + if (_buffer) + *_buffer = buffer; + else + pipe_buffer_reference(&buffer, NULL); + + return result; +} + +static struct pipe_buffer * +identity_drm_buffer_from_handle(struct drm_api *_api, + struct pipe_screen *_screen, + const char *name, + unsigned handle) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct identity_drm_api *id_api = identity_drm_api(_api); + struct pipe_screen *screen = id_screen->screen; + struct drm_api *api = id_api->api; + struct pipe_buffer *result; + + result = api->buffer_from_handle(api, screen, name, handle); + + result = identity_buffer_create(identity_screen(_screen), result); + + return result; +} + +static boolean +identity_drm_handle_from_buffer(struct drm_api *_api, + struct pipe_screen *_screen, + struct pipe_buffer *_buffer, + unsigned *handle) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct identity_buffer *id_buffer = identity_buffer(_buffer); + struct identity_drm_api *id_api = identity_drm_api(_api); + struct pipe_screen *screen = id_screen->screen; + struct pipe_buffer *buffer = id_buffer->buffer; + struct drm_api *api = id_api->api; + + return api->handle_from_buffer(api, screen, buffer, handle); +} + +static boolean +identity_drm_global_handle_from_buffer(struct drm_api *_api, + struct pipe_screen *_screen, + struct pipe_buffer *_buffer, + unsigned *handle) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct identity_buffer *id_buffer = identity_buffer(_buffer); + struct identity_drm_api *id_api = identity_drm_api(_api); + struct pipe_screen *screen = id_screen->screen; + struct pipe_buffer *buffer = id_buffer->buffer; + struct drm_api *api = id_api->api; + + return api->global_handle_from_buffer(api, screen, buffer, handle); +} + +static void +identity_drm_destroy(struct drm_api *_api) +{ + struct identity_drm_api *id_api = identity_drm_api(_api); + struct drm_api *api = id_api->api; + api->destroy(api); + + free(id_api); +} + +struct drm_api * +identity_drm_create(struct drm_api *api) +{ + struct identity_drm_api *id_api = CALLOC_STRUCT(identity_drm_api); + + if (!id_api) + return NULL; + + id_api->base.create_screen = identity_drm_create_screen; + id_api->base.create_context = identity_drm_create_context; + id_api->base.buffer_from_texture = identity_drm_buffer_from_texture; + id_api->base.buffer_from_handle = identity_drm_buffer_from_handle; + id_api->base.handle_from_buffer = identity_drm_handle_from_buffer; + id_api->base.global_handle_from_buffer = identity_drm_global_handle_from_buffer; + id_api->base.destroy = identity_drm_destroy; + id_api->api = api; + + return &id_api->base; +} diff --git a/src/gallium/drivers/identity/id_drm.h b/src/gallium/drivers/identity/id_drm.h new file mode 100644 index 00000000000..cf2ad2ce07f --- /dev/null +++ b/src/gallium/drivers/identity/id_drm.h @@ -0,0 +1,35 @@ +/************************************************************************** + * + * 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 ID_DRM_H +#define ID_DRM_H + +struct drm_api; + +struct drm_api* identity_drm_create(struct drm_api *api); + +#endif /* ID_DRM_H */ diff --git a/src/gallium/drivers/identity/id_objects.c b/src/gallium/drivers/identity/id_objects.c new file mode 100644 index 00000000000..e893e599408 --- /dev/null +++ b/src/gallium/drivers/identity/id_objects.c @@ -0,0 +1,182 @@ +/************************************************************************** + * + * 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 "id_public.h" +#include "id_screen.h" +#include "id_objects.h" + +struct pipe_buffer * +identity_buffer_create(struct identity_screen *id_screen, + struct pipe_buffer *buffer) +{ + struct identity_buffer *id_buffer; + + if(!buffer) + goto error; + + assert(buffer->screen == id_screen->screen); + + id_buffer = CALLOC_STRUCT(identity_buffer); + if(!id_buffer) + goto error; + + memcpy(&id_buffer->base, buffer, sizeof(struct pipe_buffer)); + + pipe_reference_init(&id_buffer->base.reference, 1); + id_buffer->base.screen = &id_screen->base; + id_buffer->buffer = buffer; + + return &id_buffer->base; + +error: + pipe_buffer_reference(&buffer, NULL); + return NULL; +} + +void +identity_buffer_destroy(struct identity_buffer *id_buffer) +{ + pipe_buffer_reference(&id_buffer->buffer, NULL); + FREE(id_buffer); +} + + +struct pipe_texture * +identity_texture_create(struct identity_screen *id_screen, + struct pipe_texture *texture) +{ + struct identity_texture *id_texture; + + if(!texture) + goto error; + + assert(texture->screen == id_screen->screen); + + id_texture = CALLOC_STRUCT(identity_texture); + if(!id_texture) + goto error; + + memcpy(&id_texture->base, texture, sizeof(struct pipe_texture)); + + pipe_reference_init(&id_texture->base.reference, 1); + id_texture->base.screen = &id_screen->base; + id_texture->texture = texture; + + return &id_texture->base; + +error: + pipe_texture_reference(&texture, NULL); + return NULL; +} + +void +identity_texture_destroy(struct identity_texture *id_texture) +{ + pipe_texture_reference(&id_texture->texture, NULL); + FREE(id_texture); +} + + +struct pipe_surface * +identity_surface_create(struct identity_texture *id_texture, + struct pipe_surface *surface) +{ + struct identity_surface *id_surface; + + if(!surface) + goto error; + + assert(surface->texture == id_texture->texture); + + id_surface = CALLOC_STRUCT(identity_surface); + if(!id_surface) + goto error; + + memcpy(&id_surface->base, surface, sizeof(struct pipe_surface)); + + pipe_reference_init(&id_surface->base.reference, 1); + id_surface->base.texture = NULL; + pipe_texture_reference(&id_surface->base.texture, &id_texture->base); + id_surface->surface = surface; + + return &id_surface->base; + +error: + pipe_surface_reference(&surface, NULL); + return NULL; +} + +void +identity_surface_destroy(struct identity_surface *id_surface) +{ + pipe_texture_reference(&id_surface->base.texture, NULL); + pipe_surface_reference(&id_surface->surface, NULL); + FREE(id_surface); +} + + +struct pipe_transfer * +identity_transfer_create(struct identity_texture *id_texture, + struct pipe_transfer *transfer) +{ + struct identity_transfer *id_transfer; + + if(!transfer) + goto error; + + assert(transfer->texture == id_texture->texture); + + id_transfer = CALLOC_STRUCT(identity_transfer); + if(!id_transfer) + goto error; + + memcpy(&id_transfer->base, transfer, sizeof(struct pipe_transfer)); + + id_transfer->base.texture = NULL; + pipe_texture_reference(&id_transfer->base.texture, &id_texture->base); + id_transfer->transfer = transfer; + assert(id_transfer->base.texture == &id_texture->base); + + return &id_transfer->base; + +error: + transfer->texture->screen->tex_transfer_destroy(transfer); + return NULL; +} + +void +identity_transfer_destroy(struct identity_transfer *id_transfer) +{ + struct identity_screen *id_screen = identity_screen(id_transfer->base.texture->screen); + struct pipe_screen *screen = id_screen->screen; + + pipe_texture_reference(&id_transfer->base.texture, NULL); + screen->tex_transfer_destroy(id_transfer->transfer); + FREE(id_transfer); +} diff --git a/src/gallium/drivers/identity/id_objects.h b/src/gallium/drivers/identity/id_objects.h new file mode 100644 index 00000000000..ce58faa3c7c --- /dev/null +++ b/src/gallium/drivers/identity/id_objects.h @@ -0,0 +1,169 @@ +/************************************************************************** + * + * 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 ID_OBJECTS_H +#define ID_OBJECTS_H + + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" + +#include "id_screen.h" + + +struct identity_buffer +{ + struct pipe_buffer base; + + struct pipe_buffer *buffer; +}; + + +struct identity_texture +{ + struct pipe_texture base; + + struct pipe_texture *texture; +}; + + +struct identity_surface +{ + struct pipe_surface base; + + struct pipe_surface *surface; +}; + + +struct identity_transfer +{ + struct pipe_transfer base; + + struct pipe_transfer *transfer; +}; + + +static INLINE struct identity_buffer * +identity_buffer(struct pipe_buffer *_buffer) +{ + if(!_buffer) + return NULL; + (void)identity_screen(_buffer->screen); + return (struct identity_buffer *)_buffer; +} + +static INLINE struct identity_texture * +identity_texture(struct pipe_texture *_texture) +{ + if(!_texture) + return NULL; + (void)identity_screen(_texture->screen); + return (struct identity_texture *)_texture; +} + +static INLINE struct identity_surface * +identity_surface(struct pipe_surface *_surface) +{ + if(!_surface) + return NULL; + (void)identity_texture(_surface->texture); + return (struct identity_surface *)_surface; +} + +static INLINE struct identity_transfer * +identity_transfer(struct pipe_transfer *_transfer) +{ + if(!_transfer) + return NULL; + (void)identity_texture(_transfer->texture); + return (struct identity_transfer *)_transfer; +} + + +static INLINE struct pipe_buffer * +identity_buffer_unwrap(struct pipe_buffer *_buffer) +{ + if(!_buffer) + return NULL; + return identity_buffer(_buffer)->buffer; +} + +static INLINE struct pipe_texture * +identity_texture_unwrap(struct pipe_texture *_texture) +{ + if(!_texture) + return NULL; + return identity_texture(_texture)->texture; +} + +static INLINE struct pipe_surface * +identity_surface_unwrap(struct pipe_surface *_surface) +{ + if(!_surface) + return NULL; + return identity_surface(_surface)->surface; +} + +static INLINE struct pipe_transfer * +identity_transfer_unwrap(struct pipe_transfer *_transfer) +{ + if(!_transfer) + return NULL; + return identity_transfer(_transfer)->transfer; +} + + +struct pipe_buffer * +identity_buffer_create(struct identity_screen *id_screen, + struct pipe_buffer *buffer); + +void +identity_buffer_destroy(struct identity_buffer *id_buffer); + +struct pipe_texture * +identity_texture_create(struct identity_screen *id_screen, + struct pipe_texture *texture); + +void +identity_texture_destroy(struct identity_texture *id_texture); + +struct pipe_surface * +identity_surface_create(struct identity_texture *id_texture, + struct pipe_surface *surface); + +void +identity_surface_destroy(struct identity_surface *id_surface); + +struct pipe_transfer * +identity_transfer_create(struct identity_texture *id_texture, + struct pipe_transfer *transfer); + +void +identity_transfer_destroy(struct identity_transfer *id_transfer); + + +#endif /* ID_OBJECTS_H */ diff --git a/src/gallium/drivers/identity/id_public.h b/src/gallium/drivers/identity/id_public.h new file mode 100644 index 00000000000..cac14cfd604 --- /dev/null +++ b/src/gallium/drivers/identity/id_public.h @@ -0,0 +1,40 @@ +/************************************************************************** + * + * 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 ID_PUBLIC_H +#define ID_PUBLIC_H + +struct pipe_screen; +struct pipe_context; + +struct pipe_screen * +identity_screen_create(struct pipe_screen *screen); + +struct pipe_context * +identity_context_create(struct pipe_screen *screen, struct pipe_context *pipe); + +#endif /* PT_PUBLIC_H */ diff --git a/src/gallium/drivers/identity/id_screen.c b/src/gallium/drivers/identity/id_screen.c new file mode 100644 index 00000000000..259f1be36e7 --- /dev/null +++ b/src/gallium/drivers/identity/id_screen.c @@ -0,0 +1,481 @@ +/************************************************************************** + * + * 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 "pipe/p_screen.h" +#include "pipe/p_state.h" +#include "util/u_memory.h" + +#include "id_public.h" +#include "id_screen.h" +#include "id_objects.h" + + +static void +identity_screen_destroy(struct pipe_screen *_screen) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct pipe_screen *screen = id_screen->screen; + + screen->destroy(screen); + + FREE(id_screen); +} + +static const char * +identity_screen_get_name(struct pipe_screen *_screen) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct pipe_screen *screen = id_screen->screen; + + return screen->get_name(screen); +} + +static const char * +identity_screen_get_vendor(struct pipe_screen *_screen) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct pipe_screen *screen = id_screen->screen; + + return screen->get_vendor(screen); +} + +static int +identity_screen_get_param(struct pipe_screen *_screen, + int param) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct pipe_screen *screen = id_screen->screen; + + return screen->get_param(screen, + param); +} + +static float +identity_screen_get_paramf(struct pipe_screen *_screen, + int param) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct pipe_screen *screen = id_screen->screen; + + return screen->get_paramf(screen, + param); +} + +static boolean +identity_screen_is_format_supported(struct pipe_screen *_screen, + enum pipe_format format, + enum pipe_texture_target target, + unsigned tex_usage, + unsigned geom_flags) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct pipe_screen *screen = id_screen->screen; + + return screen->is_format_supported(screen, + format, + target, + tex_usage, + geom_flags); +} + +static struct pipe_texture * +identity_screen_texture_create(struct pipe_screen *_screen, + const struct pipe_texture *templat) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct pipe_screen *screen = id_screen->screen; + struct pipe_texture *result; + + result = screen->texture_create(screen, + templat); + + if (result) + return identity_texture_create(id_screen, result); + return NULL; +} + +static struct pipe_texture * +identity_screen_texture_blanket(struct pipe_screen *_screen, + const struct pipe_texture *templat, + const unsigned *stride, + struct pipe_buffer *_buffer) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct identity_buffer *id_buffer = identity_buffer(_buffer); + struct pipe_screen *screen = id_screen->screen; + struct pipe_buffer *buffer = id_buffer->buffer; + struct pipe_texture *result; + + result = screen->texture_blanket(screen, + templat, + stride, + buffer); + + if (result) + return identity_texture_create(id_screen, result); + return NULL; +} + +static void +identity_screen_texture_destroy(struct pipe_texture *_texture) +{ + identity_texture_destroy(identity_texture(_texture)); +} + +static struct pipe_surface * +identity_screen_get_tex_surface(struct pipe_screen *_screen, + struct pipe_texture *_texture, + unsigned face, + unsigned level, + unsigned zslice, + unsigned usage) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct identity_texture *id_texture = identity_texture(_texture); + struct pipe_screen *screen = id_screen->screen; + struct pipe_texture *texture = id_texture->texture; + struct pipe_surface *result; + + result = screen->get_tex_surface(screen, + texture, + face, + level, + zslice, + usage); + + if (result) + return identity_surface_create(id_texture, result); + return NULL; +} + +static void +identity_screen_tex_surface_destroy(struct pipe_surface *_surface) +{ + identity_surface_destroy(identity_surface(_surface)); +} + +static struct pipe_transfer * +identity_screen_get_tex_transfer(struct pipe_screen *_screen, + struct pipe_texture *_texture, + unsigned face, + unsigned level, + unsigned zslice, + enum pipe_transfer_usage usage, + unsigned x, + unsigned y, + unsigned w, + unsigned h) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct identity_texture *id_texture = identity_texture(_texture); + struct pipe_screen *screen = id_screen->screen; + struct pipe_texture *texture = id_texture->texture; + struct pipe_transfer *result; + + result = screen->get_tex_transfer(screen, + texture, + face, + level, + zslice, + usage, + x, + y, + w, + h); + + if (result) + return identity_transfer_create(id_texture, result); + return NULL; +} + +static void +identity_screen_tex_transfer_destroy(struct pipe_transfer *_transfer) +{ + identity_transfer_destroy(identity_transfer(_transfer)); +} + +static void * +identity_screen_transfer_map(struct pipe_screen *_screen, + struct pipe_transfer *_transfer) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct identity_transfer *id_transfer = identity_transfer(_transfer); + struct pipe_screen *screen = id_screen->screen; + struct pipe_transfer *transfer = id_transfer->transfer; + + return screen->transfer_map(screen, + transfer); +} + +static void +identity_screen_transfer_unmap(struct pipe_screen *_screen, + struct pipe_transfer *_transfer) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct identity_transfer *id_transfer = identity_transfer(_transfer); + struct pipe_screen *screen = id_screen->screen; + struct pipe_transfer *transfer = id_transfer->transfer; + + screen->transfer_unmap(screen, + transfer); +} + +static struct pipe_buffer * +identity_screen_buffer_create(struct pipe_screen *_screen, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct pipe_screen *screen = id_screen->screen; + struct pipe_buffer *result; + + result = screen->buffer_create(screen, + alignment, + usage, + size); + + if (result) + return identity_buffer_create(id_screen, result); + return NULL; +} + +static struct pipe_buffer * +identity_screen_user_buffer_create(struct pipe_screen *_screen, + void *ptr, + unsigned bytes) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct pipe_screen *screen = id_screen->screen; + struct pipe_buffer *result; + + result = screen->user_buffer_create(screen, + ptr, + bytes); + + if (result) + return identity_buffer_create(id_screen, result); + return NULL; +} + +static struct pipe_buffer * +identity_screen_surface_buffer_create(struct pipe_screen *_screen, + unsigned width, + unsigned height, + enum pipe_format format, + unsigned usage, + unsigned *stride) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct pipe_screen *screen = id_screen->screen; + struct pipe_buffer *result; + + result = screen->surface_buffer_create(screen, + width, + height, + format, + usage, + stride); + + if (result) + return identity_buffer_create(id_screen, result); + return NULL; +} + +static void * +identity_screen_buffer_map(struct pipe_screen *_screen, + struct pipe_buffer *_buffer, + unsigned usage) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct identity_buffer *id_buffer = identity_buffer(_buffer); + struct pipe_screen *screen = id_screen->screen; + struct pipe_buffer *buffer = id_buffer->buffer; + + return screen->buffer_map(screen, + buffer, + usage); +} + +static void * +identity_screen_buffer_map_range(struct pipe_screen *_screen, + struct pipe_buffer *_buffer, + unsigned offset, + unsigned length, + unsigned usage) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct identity_buffer *id_buffer = identity_buffer(_buffer); + struct pipe_screen *screen = id_screen->screen; + struct pipe_buffer *buffer = id_buffer->buffer; + + return screen->buffer_map_range(screen, + buffer, + offset, + length, + usage); +} + +static void +identity_screen_buffer_flush_mapped_range(struct pipe_screen *_screen, + struct pipe_buffer *_buffer, + unsigned offset, + unsigned length) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct identity_buffer *id_buffer = identity_buffer(_buffer); + struct pipe_screen *screen = id_screen->screen; + struct pipe_buffer *buffer = id_buffer->buffer; + + screen->buffer_flush_mapped_range(screen, + buffer, + offset, + length); +} + +static void +identity_screen_buffer_unmap(struct pipe_screen *_screen, + struct pipe_buffer *_buffer) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct identity_buffer *id_buffer = identity_buffer(_buffer); + struct pipe_screen *screen = id_screen->screen; + struct pipe_buffer *buffer = id_buffer->buffer; + + screen->buffer_unmap(screen, + buffer); +} + +static void +identity_screen_buffer_destroy(struct pipe_buffer *_buffer) +{ + identity_buffer_destroy(identity_buffer(_buffer)); +} + +static void +identity_screen_flush_frontbuffer(struct pipe_screen *_screen, + struct pipe_surface *_surface, + void *context_private) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct identity_surface *id_surface = identity_surface(_surface); + struct pipe_screen *screen = id_screen->screen; + struct pipe_surface *surface = id_surface->surface; + + screen->flush_frontbuffer(screen, + surface, + context_private); +} + +static void +identity_screen_fence_reference(struct pipe_screen *_screen, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct pipe_screen *screen = id_screen->screen; + + screen->fence_reference(screen, + ptr, + fence); +} + +static int +identity_screen_fence_signalled(struct pipe_screen *_screen, + struct pipe_fence_handle *fence, + unsigned flags) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct pipe_screen *screen = id_screen->screen; + + return screen->fence_signalled(screen, + fence, + flags); +} + +static int +identity_screen_fence_finish(struct pipe_screen *_screen, + struct pipe_fence_handle *fence, + unsigned flags) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct pipe_screen *screen = id_screen->screen; + + return screen->fence_finish(screen, + fence, + flags); +} + +struct pipe_screen * +identity_screen_create(struct pipe_screen *screen) +{ + struct identity_screen *id_screen; + + id_screen = CALLOC_STRUCT(identity_screen); + if (!id_screen) { + return NULL; + } + + id_screen->base.winsys = NULL; + + id_screen->base.destroy = identity_screen_destroy; + id_screen->base.get_name = identity_screen_get_name; + id_screen->base.get_vendor = identity_screen_get_vendor; + id_screen->base.get_param = identity_screen_get_param; + id_screen->base.get_paramf = identity_screen_get_paramf; + id_screen->base.is_format_supported = identity_screen_is_format_supported; + id_screen->base.texture_create = identity_screen_texture_create; + id_screen->base.texture_blanket = identity_screen_texture_blanket; + id_screen->base.texture_destroy = identity_screen_texture_destroy; + id_screen->base.get_tex_surface = identity_screen_get_tex_surface; + id_screen->base.tex_surface_destroy = identity_screen_tex_surface_destroy; + id_screen->base.get_tex_transfer = identity_screen_get_tex_transfer; + id_screen->base.tex_transfer_destroy = identity_screen_tex_transfer_destroy; + id_screen->base.transfer_map = identity_screen_transfer_map; + id_screen->base.transfer_unmap = identity_screen_transfer_unmap; + id_screen->base.buffer_create = identity_screen_buffer_create; + id_screen->base.user_buffer_create = identity_screen_user_buffer_create; + id_screen->base.surface_buffer_create = identity_screen_surface_buffer_create; + if (screen->buffer_map) + id_screen->base.buffer_map = identity_screen_buffer_map; + if (screen->buffer_map_range) + id_screen->base.buffer_map_range = identity_screen_buffer_map_range; + if (screen->buffer_flush_mapped_range) + id_screen->base.buffer_flush_mapped_range = identity_screen_buffer_flush_mapped_range; + if (screen->buffer_unmap) + id_screen->base.buffer_unmap = identity_screen_buffer_unmap; + id_screen->base.buffer_destroy = identity_screen_buffer_destroy; + id_screen->base.flush_frontbuffer = identity_screen_flush_frontbuffer; + id_screen->base.fence_reference = identity_screen_fence_reference; + id_screen->base.fence_signalled = identity_screen_fence_signalled; + id_screen->base.fence_finish = identity_screen_fence_finish; + + id_screen->screen = screen; + + return &id_screen->base; +} diff --git a/src/gallium/drivers/identity/id_screen.h b/src/gallium/drivers/identity/id_screen.h new file mode 100644 index 00000000000..2c4f1290894 --- /dev/null +++ b/src/gallium/drivers/identity/id_screen.h @@ -0,0 +1,48 @@ +/************************************************************************** + * + * 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 ID_SCREEN_H +#define ID_SCREEN_H + +#include "pipe/p_screen.h" +#include "pipe/p_defines.h" + + +struct identity_screen { + struct pipe_screen base; + + struct pipe_screen *screen; +}; + + +static INLINE struct identity_screen * +identity_screen(struct pipe_screen *screen) +{ + return (struct identity_screen *)screen; +} + +#endif /* ID_SCREEN_H */ diff --git a/src/gallium/drivers/nouveau/Makefile b/src/gallium/drivers/nouveau/Makefile new file mode 100644 index 00000000000..dbe8a6e7bf5 --- /dev/null +++ b/src/gallium/drivers/nouveau/Makefile @@ -0,0 +1,8 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = nouveau + +C_SOURCES = nouveau_screen.c + +include ../../Makefile.template diff --git a/src/gallium/drivers/nouveau/nouveau_push.h b/src/gallium/drivers/nouveau/nouveau_push.h index 54ef1c1291e..9c235080a55 100644 --- a/src/gallium/drivers/nouveau/nouveau_push.h +++ b/src/gallium/drivers/nouveau/nouveau_push.h @@ -9,13 +9,13 @@ #define OUT_RING(data) do { \ NOUVEAU_PUSH_CONTEXT(pc); \ - (*pc->nvws->channel->pushbuf->cur++) = (data); \ + (*pc->base.channel->pushbuf->cur++) = (data); \ } while(0) #define OUT_RINGp(src,size) do { \ NOUVEAU_PUSH_CONTEXT(pc); \ - memcpy(pc->nvws->channel->pushbuf->cur, (src), (size) * 4); \ - pc->nvws->channel->pushbuf->cur += (size); \ + memcpy(pc->base.channel->pushbuf->cur, (src), (size) * 4); \ + pc->base.channel->pushbuf->cur += (size); \ } while(0) #define OUT_RINGf(data) do { \ @@ -26,25 +26,35 @@ #define BEGIN_RING(obj,mthd,size) do { \ NOUVEAU_PUSH_CONTEXT(pc); \ - if (pc->nvws->channel->pushbuf->remaining < ((size) + 1)) \ - pc->nvws->push_flush(pc->nvws, ((size) + 1), NULL); \ + struct nouveau_channel *chan = pc->base.channel; \ + if (chan->pushbuf->remaining < ((size) + 1)) \ + nouveau_pushbuf_flush(chan, ((size) + 1)); \ OUT_RING((pc->obj->subc << 13) | ((size) << 18) | (mthd)); \ - pc->nvws->channel->pushbuf->remaining -= ((size) + 1); \ + chan->pushbuf->remaining -= ((size) + 1); \ } while(0) #define BEGIN_RING_NI(obj,mthd,size) do { \ BEGIN_RING(obj, (mthd) | 0x40000000, (size)); \ } while(0) +static inline void +DO_FIRE_RING(struct nouveau_channel *chan, struct pipe_fence_handle **fence) +{ + nouveau_pushbuf_flush(chan, 0); + if (fence) + *fence = NULL; +} + #define FIRE_RING(fence) do { \ NOUVEAU_PUSH_CONTEXT(pc); \ - pc->nvws->push_flush(pc->nvws, 0, fence); \ + DO_FIRE_RING(pc->base.channel, fence); \ } while(0) #define OUT_RELOC(bo,data,flags,vor,tor) do { \ NOUVEAU_PUSH_CONTEXT(pc); \ - pc->nvws->push_reloc(pc->nvws, pc->nvws->channel->pushbuf->cur++, \ - (bo), (data), (flags), (vor), (tor)); \ + struct nouveau_channel *chan = pc->base.channel; \ + nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, nouveau_bo(bo), \ + (data), 0, (flags), (vor), (tor)); \ } while(0) /* Raw data + flags depending on FB/TT buffer */ @@ -55,8 +65,8 @@ /* FB/TT object handle */ #define OUT_RELOCo(bo,flags) do { \ OUT_RELOC((bo), 0, (flags) | NOUVEAU_BO_OR, \ - pc->nvws->channel->vram->handle, \ - pc->nvws->channel->gart->handle); \ + pc->base.channel->vram->handle, \ + pc->base.channel->gart->handle); \ } while(0) /* Low 32-bits of offset */ @@ -72,11 +82,12 @@ /* A reloc which'll recombine into a NV_DMA_METHOD packet header */ #define OUT_RELOCm(bo, flags, obj, mthd, size) do { \ NOUVEAU_PUSH_CONTEXT(pc); \ - if (pc->nvws->channel->pushbuf->remaining < ((size) + 1)) \ - pc->nvws->push_flush(pc->nvws->channel, ((size) + 1), NULL); \ + struct nouveau_channel *chan = pc->base.channel; \ + if (chan->pushbuf->remaining < ((size) + 1)) \ + nouveau_pushbuf_flush(chan, ((size) + 1)); \ OUT_RELOCd((bo), (pc->obj->subc << 13) | ((size) << 18) | (mthd), \ (flags), 0, 0); \ - pc->nvws->channel->pushbuf->remaining -= ((size) + 1); \ + chan->pushbuf->remaining -= ((size) + 1); \ } while(0) #endif diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c new file mode 100644 index 00000000000..e4cf91c005c --- /dev/null +++ b/src/gallium/drivers/nouveau/nouveau_screen.c @@ -0,0 +1,243 @@ +#include <pipe/p_defines.h> +#include <pipe/p_screen.h> +#include <pipe/p_state.h> + +#include <util/u_memory.h> + +#include <errno.h> + +#include "nouveau/nouveau_bo.h" +#include "nouveau_winsys.h" +#include "nouveau_screen.h" + +static const char * +nouveau_screen_get_name(struct pipe_screen *pscreen) +{ + struct nouveau_device *dev = nouveau_screen(pscreen)->device; + static char buffer[128]; + + snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); + return buffer; +} + +static const char * +nouveau_screen_get_vendor(struct pipe_screen *pscreen) +{ + return "nouveau"; +} + +static struct pipe_buffer * +nouveau_screen_bo_skel(struct pipe_screen *pscreen, struct nouveau_bo *bo, + unsigned alignment, unsigned usage, unsigned size) +{ + struct pipe_buffer *pb; + + pb = CALLOC(1, sizeof(struct pipe_buffer)+sizeof(struct nouveau_bo *)); + if (!pb) { + nouveau_bo_ref(NULL, &bo); + return NULL; + } + + pipe_reference_init(&pb->reference, 1); + pb->screen = pscreen; + pb->alignment = alignment; + pb->usage = usage; + pb->size = size; + *(struct nouveau_bo **)(pb + 1) = bo; + return pb; +} + +static struct pipe_buffer * +nouveau_screen_bo_new(struct pipe_screen *pscreen, unsigned alignment, + unsigned usage, unsigned size) +{ + struct nouveau_device *dev = nouveau_screen(pscreen)->device; + struct nouveau_bo *bo = NULL; + uint32_t flags = NOUVEAU_BO_MAP; + int ret; + + if (usage & NOUVEAU_BUFFER_USAGE_TRANSFER) + flags |= NOUVEAU_BO_GART; + else + if (usage & PIPE_BUFFER_USAGE_VERTEX) { + if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_VTXBUF)) + flags |= NOUVEAU_BO_GART; + } else + if (usage & PIPE_BUFFER_USAGE_INDEX) { + if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF)) + flags |= NOUVEAU_BO_GART; + } + + if (usage & PIPE_BUFFER_USAGE_PIXEL) { + if (usage & NOUVEAU_BUFFER_USAGE_TEXTURE) + flags |= NOUVEAU_BO_GART; + if (!(usage & PIPE_BUFFER_USAGE_CPU_READ_WRITE)) + flags |= NOUVEAU_BO_VRAM; + + if (dev->chipset == 0x50 || dev->chipset >= 0x80) { + flags |= NOUVEAU_BO_TILED; + if (usage & NOUVEAU_BUFFER_USAGE_ZETA) + flags |= NOUVEAU_BO_ZTILE; + } + } + + ret = nouveau_bo_new(dev, flags, alignment, size, &bo); + if (ret) + return NULL; + + return nouveau_screen_bo_skel(pscreen, bo, alignment, usage, size); +} + +static struct pipe_buffer * +nouveau_screen_bo_user(struct pipe_screen *pscreen, void *ptr, unsigned bytes) +{ + struct nouveau_device *dev = nouveau_screen(pscreen)->device; + struct nouveau_bo *bo = NULL; + int ret; + + ret = nouveau_bo_user(dev, ptr, bytes, &bo); + if (ret) + return NULL; + + return nouveau_screen_bo_skel(pscreen, bo, 0, 0, bytes); +} + +static inline uint32_t +nouveau_screen_map_flags(unsigned pipe) +{ + uint32_t flags = 0; + + if (pipe & PIPE_BUFFER_USAGE_CPU_READ) + flags |= NOUVEAU_BO_RD; + if (pipe & PIPE_BUFFER_USAGE_CPU_WRITE) + flags |= NOUVEAU_BO_WR; + if (pipe & PIPE_BUFFER_USAGE_DISCARD) + flags |= NOUVEAU_BO_INVAL; + if (pipe & PIPE_BUFFER_USAGE_DONTBLOCK) + flags |= NOUVEAU_BO_NOWAIT; + else + if (pipe & 0 /*PIPE_BUFFER_USAGE_UNSYNCHRONIZED*/) + flags |= NOUVEAU_BO_NOSYNC; + + return flags; +} + +static void * +nouveau_screen_bo_map(struct pipe_screen *pscreen, struct pipe_buffer *pb, + unsigned usage) +{ + struct nouveau_bo *bo = nouveau_bo(pb); + int ret; + + ret = nouveau_bo_map(bo, nouveau_screen_map_flags(usage)); + if (ret) { + debug_printf("map failed: %d\n", ret); + return NULL; + } + + return bo->map; +} + +static void * +nouveau_screen_bo_map_range(struct pipe_screen *pscreen, struct pipe_buffer *pb, + unsigned offset, unsigned length, unsigned usage) +{ + struct nouveau_bo *bo = nouveau_bo(pb); + uint32_t flags = nouveau_screen_map_flags(usage); + int ret; + + ret = nouveau_bo_map_range(bo, offset, length, flags); + if (ret) { + if (!(flags & NOUVEAU_BO_NOWAIT) || ret != -EBUSY) + debug_printf("map_range failed: %d\n", ret); + return NULL; + } + + return (char *)bo->map - offset; /* why gallium? why? */ +} + +static void +nouveau_screen_bo_map_flush(struct pipe_screen *pscreen, struct pipe_buffer *pb, + unsigned offset, unsigned length) +{ + struct nouveau_bo *bo = nouveau_bo(pb); + + nouveau_bo_map_flush(bo, offset, length); +} + +static void +nouveau_screen_bo_unmap(struct pipe_screen *pscreen, struct pipe_buffer *pb) +{ + struct nouveau_bo *bo = nouveau_bo(pb); + + nouveau_bo_unmap(bo); +} + +static void +nouveau_screen_bo_del(struct pipe_buffer *pb) +{ + struct nouveau_bo *bo = nouveau_bo(pb); + + nouveau_bo_ref(NULL, &bo); + FREE(pb); +} + +static void +nouveau_screen_fence_ref(struct pipe_screen *pscreen, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *pfence) +{ + *ptr = pfence; +} + +static int +nouveau_screen_fence_signalled(struct pipe_screen *screen, + struct pipe_fence_handle *pfence, + unsigned flags) +{ + return 0; +} + +static int +nouveau_screen_fence_finish(struct pipe_screen *screen, + struct pipe_fence_handle *pfence, + unsigned flags) +{ + return 0; +} + +int +nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) +{ + struct pipe_screen *pscreen = &screen->base; + int ret; + + ret = nouveau_channel_alloc(dev, 0xbeef0201, 0xbeef0202, + &screen->channel); + if (ret) + return ret; + screen->device = dev; + + pscreen->get_name = nouveau_screen_get_name; + pscreen->get_vendor = nouveau_screen_get_vendor; + + pscreen->buffer_create = nouveau_screen_bo_new; + pscreen->user_buffer_create = nouveau_screen_bo_user; + pscreen->buffer_map = nouveau_screen_bo_map; + pscreen->buffer_map_range = nouveau_screen_bo_map_range; + pscreen->buffer_flush_mapped_range = nouveau_screen_bo_map_flush; + pscreen->buffer_unmap = nouveau_screen_bo_unmap; + pscreen->buffer_destroy = nouveau_screen_bo_del; + + pscreen->fence_reference = nouveau_screen_fence_ref; + pscreen->fence_signalled = nouveau_screen_fence_signalled; + pscreen->fence_finish = nouveau_screen_fence_finish; + + return 0; +} + +void +nouveau_screen_fini(struct nouveau_screen *screen) +{ +} + diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h new file mode 100644 index 00000000000..9968b078966 --- /dev/null +++ b/src/gallium/drivers/nouveau/nouveau_screen.h @@ -0,0 +1,25 @@ +#ifndef __NOUVEAU_SCREEN_H__ +#define __NOUVEAU_SCREEN_H__ + +struct nouveau_screen { + struct pipe_screen base; + struct nouveau_device *device; + struct nouveau_channel *channel; +}; + +static inline struct nouveau_screen * +nouveau_screen(struct pipe_screen *pscreen) +{ + return (struct nouveau_screen *)pscreen; +} + +static inline struct nouveau_bo * +nouveau_bo(struct pipe_buffer *pb) +{ + return pb ? *(struct nouveau_bo **)(pb + 1) : NULL; +} + +int nouveau_screen_init(struct nouveau_screen *, struct nouveau_device *); +void nouveau_screen_fini(struct nouveau_screen *); + +#endif diff --git a/src/gallium/drivers/nouveau/nouveau_stateobj.h b/src/gallium/drivers/nouveau/nouveau_stateobj.h index a54820e8512..b595405357f 100644 --- a/src/gallium/drivers/nouveau/nouveau_stateobj.h +++ b/src/gallium/drivers/nouveau/nouveau_stateobj.h @@ -4,7 +4,7 @@ #include "util/u_debug.h" struct nouveau_stateobj_reloc { - struct pipe_buffer *bo; + struct nouveau_bo *bo; unsigned offset; unsigned packet; @@ -51,7 +51,7 @@ so_ref(struct nouveau_stateobj *ref, struct nouveau_stateobj **pso) if (pipe_reference((struct pipe_reference**)pso, &ref->reference)) { free(so->push); for (i = 0; i < so->cur_reloc; i++) - pipe_buffer_reference(&so->reloc[i].bo, NULL); + nouveau_bo_ref(NULL, &so->reloc[i].bo); free(so->reloc); free(so); } @@ -81,13 +81,13 @@ so_method(struct nouveau_stateobj *so, struct nouveau_grobj *gr, } static INLINE void -so_reloc(struct nouveau_stateobj *so, struct pipe_buffer *bo, +so_reloc(struct nouveau_stateobj *so, struct nouveau_bo *bo, unsigned data, unsigned flags, unsigned vor, unsigned tor) { struct nouveau_stateobj_reloc *r = &so->reloc[so->cur_reloc++]; r->bo = NULL; - pipe_buffer_reference(&r->bo, bo); + nouveau_bo_ref(bo, &r->bo); r->offset = so->cur - so->push; r->packet = so->cur_packet; r->data = data; @@ -107,50 +107,52 @@ so_dump(struct nouveau_stateobj *so) } static INLINE void -so_emit(struct nouveau_winsys *nvws, struct nouveau_stateobj *so) +so_emit(struct nouveau_channel *chan, struct nouveau_stateobj *so) { - struct nouveau_pushbuf *pb = nvws->channel->pushbuf; + struct nouveau_pushbuf *pb = chan->pushbuf; unsigned nr, i; nr = so->cur - so->push; if (pb->remaining < nr) - nvws->push_flush(nvws, nr, NULL); + nouveau_pushbuf_flush(chan, nr); pb->remaining -= nr; memcpy(pb->cur, so->push, nr * 4); for (i = 0; i < so->cur_reloc; i++) { struct nouveau_stateobj_reloc *r = &so->reloc[i]; - nvws->push_reloc(nvws, pb->cur + r->offset, r->bo, - r->data, r->flags, r->vor, r->tor); + nouveau_pushbuf_emit_reloc(chan, pb->cur + r->offset, + r->bo, r->data, 0, r->flags, + r->vor, r->tor); } pb->cur += nr; } static INLINE void -so_emit_reloc_markers(struct nouveau_winsys *nvws, struct nouveau_stateobj *so) +so_emit_reloc_markers(struct nouveau_channel *chan, struct nouveau_stateobj *so) { - struct nouveau_pushbuf *pb = nvws->channel->pushbuf; + struct nouveau_pushbuf *pb = chan->pushbuf; unsigned i; if (!so) return; i = so->cur_reloc << 1; - if (nvws->channel->pushbuf->remaining < i) - nvws->push_flush(nvws, i, NULL); - nvws->channel->pushbuf->remaining -= i; + if (pb->remaining < i) + nouveau_pushbuf_flush(chan, i); + pb->remaining -= i; for (i = 0; i < so->cur_reloc; i++) { struct nouveau_stateobj_reloc *r = &so->reloc[i]; - nvws->push_reloc(nvws, pb->cur++, r->bo, r->packet, - (r->flags & (NOUVEAU_BO_VRAM | - NOUVEAU_BO_GART | - NOUVEAU_BO_RDWR)) | - NOUVEAU_BO_DUMMY, 0, 0); - nvws->push_reloc(nvws, pb->cur++, r->bo, r->data, - r->flags | NOUVEAU_BO_DUMMY, r->vor, r->tor); + nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo, r->packet, 0, + (r->flags & (NOUVEAU_BO_VRAM | + NOUVEAU_BO_GART | + NOUVEAU_BO_RDWR)) | + NOUVEAU_BO_DUMMY, 0, 0); + nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo, r->data, 0, + r->flags | NOUVEAU_BO_DUMMY, + r->vor, r->tor); } } diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h index ff7dd1c51c8..42c77e5e778 100644 --- a/src/gallium/drivers/nouveau/nouveau_winsys.h +++ b/src/gallium/drivers/nouveau/nouveau_winsys.h @@ -23,77 +23,38 @@ #define NOUVEAU_BUFFER_USAGE_ZETA (1 << 17) #define NOUVEAU_BUFFER_USAGE_TRANSFER (1 << 18) -struct nouveau_winsys { - struct pipe_winsys *ws; - - struct nouveau_channel *channel; - - int (*res_init)(struct nouveau_resource **heap, unsigned start, - unsigned size); - int (*res_alloc)(struct nouveau_resource *heap, int size, void *priv, - struct nouveau_resource **); - void (*res_free)(struct nouveau_resource **); - - int (*push_reloc)(struct nouveau_winsys *, void *ptr, - struct pipe_buffer *, uint32_t data, - uint32_t flags, uint32_t vor, uint32_t tor); - int (*push_flush)(struct nouveau_winsys *, unsigned size, - struct pipe_fence_handle **fence); - - int (*grobj_alloc)(struct nouveau_winsys *, int grclass, - struct nouveau_grobj **); - void (*grobj_free)(struct nouveau_grobj **); - - int (*notifier_alloc)(struct nouveau_winsys *, int count, - struct nouveau_notifier **); - void (*notifier_free)(struct nouveau_notifier **); - void (*notifier_reset)(struct nouveau_notifier *, int id); - uint32_t (*notifier_status)(struct nouveau_notifier *, int id); - uint32_t (*notifier_retval)(struct nouveau_notifier *, int id); - int (*notifier_wait)(struct nouveau_notifier *, int id, - int status, double timeout); - - int (*surface_copy)(struct nouveau_winsys *, struct pipe_surface *, - unsigned, unsigned, struct pipe_surface *, - unsigned, unsigned, unsigned, unsigned); - int (*surface_fill)(struct nouveau_winsys *, struct pipe_surface *, - unsigned, unsigned, unsigned, unsigned, unsigned); - - struct nouveau_bo *(*get_bo)(struct pipe_buffer *); -}; - extern struct pipe_screen * -nv04_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *); +nv04_screen_create(struct pipe_winsys *ws, struct nouveau_device *); extern struct pipe_context * nv04_create(struct pipe_screen *, unsigned pctx_id); extern struct pipe_screen * -nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *); +nv10_screen_create(struct pipe_winsys *ws, struct nouveau_device *); extern struct pipe_context * nv10_create(struct pipe_screen *, unsigned pctx_id); extern struct pipe_screen * -nv20_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *); +nv20_screen_create(struct pipe_winsys *ws, struct nouveau_device *); extern struct pipe_context * nv20_create(struct pipe_screen *, unsigned pctx_id); extern struct pipe_screen * -nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *); +nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *); extern struct pipe_context * nv30_create(struct pipe_screen *, unsigned pctx_id); extern struct pipe_screen * -nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *); +nv40_screen_create(struct pipe_winsys *ws, struct nouveau_device *); extern struct pipe_context * nv40_create(struct pipe_screen *, unsigned pctx_id); extern struct pipe_screen * -nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *); +nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *); extern struct pipe_context * nv50_create(struct pipe_screen *, unsigned pctx_id); diff --git a/src/gallium/drivers/nv04/nv04_miptree.c b/src/gallium/drivers/nv04/nv04_miptree.c index 4da833c25e8..93f752faec9 100644 --- a/src/gallium/drivers/nv04/nv04_miptree.c +++ b/src/gallium/drivers/nv04/nv04_miptree.c @@ -31,7 +31,8 @@ nv04_miptree_layout(struct nv04_miptree *nv04mt) for (l = 0; l <= pt->last_level; l++) { - nv04mt->level[l].image_offset = offset; + nv04mt->level[l].image_offset = + CALLOC(nr_faces, sizeof(unsigned)); offset += nv04mt->level[l].pitch * pt->height[l]; } diff --git a/src/gallium/drivers/nv04/nv04_screen.c b/src/gallium/drivers/nv04/nv04_screen.c index f9f6d974264..ff2febb668e 100644 --- a/src/gallium/drivers/nv04/nv04_screen.c +++ b/src/gallium/drivers/nv04/nv04_screen.c @@ -1,27 +1,9 @@ #include "pipe/p_screen.h" #include "pipe/p_inlines.h" -#include "util/u_simple_screen.h" #include "nv04_context.h" #include "nv04_screen.h" -static const char * -nv04_screen_get_name(struct pipe_screen *screen) -{ - struct nv04_screen *nv04screen = nv04_screen(screen); - struct nouveau_device *dev = nv04screen->nvws->channel->device; - static char buffer[128]; - - snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); - return buffer; -} - -static const char * -nv04_screen_get_vendor(struct pipe_screen *screen) -{ - return "nouveau"; -} - static int nv04_screen_get_param(struct pipe_screen *screen, int param) { @@ -58,6 +40,10 @@ nv04_screen_get_param(struct pipe_screen *screen, int param) return 0; case PIPE_CAP_TEXTURE_MIRROR_REPEAT: return 1; + case PIPE_CAP_TGSI_CONT_SUPPORTED: + return 0; + case PIPE_CAP_BLEND_EQUATION_SEPARATE: + return 0; case NOUVEAU_CAP_HW_VTXBUF: case NOUVEAU_CAP_HW_IDXBUF: return 0; @@ -97,6 +83,13 @@ nv04_screen_is_format_supported(struct pipe_screen *screen, switch (format) { case PIPE_FORMAT_A8R8G8B8_UNORM: case PIPE_FORMAT_R5G6B5_UNORM: + return TRUE; + default: + break; + } + } else + if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) { + switch (format) { case PIPE_FORMAT_Z16_UNORM: return TRUE; default: @@ -123,10 +116,9 @@ static void nv04_screen_destroy(struct pipe_screen *pscreen) { struct nv04_screen *screen = nv04_screen(pscreen); - struct nouveau_winsys *nvws = screen->nvws; - nvws->notifier_free(&screen->sync); - nvws->grobj_free(&screen->fahrenheit); + nouveau_notifier_free(&screen->sync); + nouveau_grobj_free(&screen->fahrenheit); nv04_surface_2d_takedown(&screen->eng2d); FREE(pscreen); @@ -141,21 +133,38 @@ nv04_surface_buffer(struct pipe_surface *surf) } struct pipe_screen * -nv04_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) +nv04_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) { struct nv04_screen *screen = CALLOC_STRUCT(nv04_screen); + struct nouveau_channel *chan; + struct pipe_screen *pscreen; unsigned fahrenheit_class = 0, sub3d_class = 0; - unsigned chipset = nvws->channel->device->chipset; int ret; if (!screen) return NULL; - screen->nvws = nvws; + pscreen = &screen->base.base; + + ret = nouveau_screen_init(&screen->base, dev); + if (ret) { + nv04_screen_destroy(pscreen); + return NULL; + } + chan = screen->base.channel; + + pscreen->winsys = ws; + pscreen->destroy = nv04_screen_destroy; + pscreen->get_param = nv04_screen_get_param; + pscreen->get_paramf = nv04_screen_get_paramf; + pscreen->is_format_supported = nv04_screen_is_format_supported; - if (chipset>=0x20) { + nv04_screen_init_miptree_functions(pscreen); + nv04_screen_init_transfer_functions(pscreen); + + if (dev->chipset >= 0x20) { fahrenheit_class = 0; sub3d_class = 0; - } else if (chipset>=0x10) { + } else if (dev->chipset >= 0x10) { fahrenheit_class = NV10_DX5_TEXTURED_TRIANGLE; sub3d_class = NV10_CONTEXT_SURFACES_3D; } else { @@ -164,50 +173,40 @@ nv04_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) } if (!fahrenheit_class) { - NOUVEAU_ERR("Unknown nv04 chipset: nv%02x\n", chipset); + NOUVEAU_ERR("Unknown nv04 chipset: nv%02x\n", dev->chipset); return NULL; } - /* 2D engine setup */ - screen->eng2d = nv04_surface_2d_init(nvws); - screen->eng2d->buf = nv04_surface_buffer; - /* 3D object */ - ret = nvws->grobj_alloc(nvws, fahrenheit_class, &screen->fahrenheit); + ret = nouveau_grobj_alloc(chan, 0xbeef0001, fahrenheit_class, + &screen->fahrenheit); if (ret) { NOUVEAU_ERR("Error creating 3D object: %d\n", ret); return NULL; } + BIND_RING(chan, screen->fahrenheit, 7); /* 3D surface object */ - ret = nvws->grobj_alloc(nvws, sub3d_class, &screen->context_surfaces_3d); + ret = nouveau_grobj_alloc(chan, 0xbeef0002, sub3d_class, + &screen->context_surfaces_3d); if (ret) { NOUVEAU_ERR("Error creating 3D surface object: %d\n", ret); return NULL; } + BIND_RING(chan, screen->context_surfaces_3d, 6); + + /* 2D engine setup */ + screen->eng2d = nv04_surface_2d_init(&screen->base); + screen->eng2d->buf = nv04_surface_buffer; /* Notifier for sync purposes */ - ret = nvws->notifier_alloc(nvws, 1, &screen->sync); + ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); if (ret) { NOUVEAU_ERR("Error creating notifier object: %d\n", ret); - nv04_screen_destroy(&screen->pipe); + nv04_screen_destroy(pscreen); return NULL; } - screen->pipe.winsys = ws; - screen->pipe.destroy = nv04_screen_destroy; - - screen->pipe.get_name = nv04_screen_get_name; - screen->pipe.get_vendor = nv04_screen_get_vendor; - screen->pipe.get_param = nv04_screen_get_param; - screen->pipe.get_paramf = nv04_screen_get_paramf; - - screen->pipe.is_format_supported = nv04_screen_is_format_supported; - - nv04_screen_init_miptree_functions(&screen->pipe); - nv04_screen_init_transfer_functions(&screen->pipe); - u_simple_screen_init(&screen->pipe); - - return &screen->pipe; + return pscreen; } diff --git a/src/gallium/drivers/nv04/nv04_screen.h b/src/gallium/drivers/nv04/nv04_screen.h index ee6fb6db44a..11466b9442c 100644 --- a/src/gallium/drivers/nv04/nv04_screen.h +++ b/src/gallium/drivers/nv04/nv04_screen.h @@ -1,11 +1,11 @@ #ifndef __NV04_SCREEN_H__ #define __NV04_SCREEN_H__ -#include "pipe/p_screen.h" +#include "nouveau/nouveau_screen.h" #include "nv04_surface_2d.h" struct nv04_screen { - struct pipe_screen pipe; + struct nouveau_screen base; struct nouveau_winsys *nvws; unsigned chipset; diff --git a/src/gallium/drivers/nv04/nv04_state.c b/src/gallium/drivers/nv04/nv04_state.c index 87c635f962a..d356ebd8b36 100644 --- a/src/gallium/drivers/nv04/nv04_state.c +++ b/src/gallium/drivers/nv04/nv04_state.c @@ -2,6 +2,7 @@ #include "pipe/p_state.h" #include "pipe/p_defines.h" #include "pipe/p_shader_tokens.h" +#include "pipe/p_inlines.h" #include "tgsi/tgsi_parse.h" @@ -334,7 +335,7 @@ nv04_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, const struct pipe_constant_buffer *buf ) { struct nv04_context *nv04 = nv04_context(pipe); - struct pipe_winsys *ws = pipe->winsys; + struct pipe_screen *pscreen = pipe->screen; assert(shader < PIPE_SHADER_TYPES); assert(index == 0); @@ -342,12 +343,12 @@ nv04_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, if (buf) { void *mapped; if (buf->buffer && buf->buffer->size && - (mapped = ws->buffer_map(ws, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ))) + (mapped = pipe_buffer_map(pscreen, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ))) { memcpy(nv04->constbuf[shader], mapped, buf->buffer->size); nv04->constbuf_nr[shader] = buf->buffer->size / (4 * sizeof(float)); - ws->buffer_unmap(ws, buf->buffer); + pipe_buffer_unmap(pscreen, buf->buffer); } } } diff --git a/src/gallium/drivers/nv04/nv04_state.h b/src/gallium/drivers/nv04/nv04_state.h index 0d51439e3ff..399f750dbe7 100644 --- a/src/gallium/drivers/nv04/nv04_state.h +++ b/src/gallium/drivers/nv04/nv04_state.h @@ -37,7 +37,7 @@ struct nv04_miptree { struct { uint pitch; - uint image_offset; + uint *image_offset; } level[PIPE_MAX_TEXTURE_LEVELS]; }; diff --git a/src/gallium/drivers/nv04/nv04_surface_2d.c b/src/gallium/drivers/nv04/nv04_surface_2d.c index f3a8d7efeed..bbbcb54c467 100644 --- a/src/gallium/drivers/nv04/nv04_surface_2d.c +++ b/src/gallium/drivers/nv04/nv04_surface_2d.c @@ -4,6 +4,7 @@ #include "nouveau/nouveau_winsys.h" #include "nouveau/nouveau_util.h" +#include "nouveau/nouveau_screen.h" #include "nv04_surface_2d.h" static INLINE int @@ -96,11 +97,11 @@ nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx, struct pipe_surface *src, int sx, int sy, int w, int h) { - struct nouveau_channel *chan = ctx->nvws->channel; + struct nouveau_channel *chan = ctx->swzsurf->channel; struct nouveau_grobj *swzsurf = ctx->swzsurf; struct nouveau_grobj *sifm = ctx->sifm; - struct nouveau_bo *src_bo = ctx->nvws->get_bo(ctx->buf(src)); - struct nouveau_bo *dst_bo = ctx->nvws->get_bo(ctx->buf(dst)); + struct nouveau_bo *src_bo = nouveau_bo(ctx->buf(src)); + struct nouveau_bo *dst_bo = nouveau_bo(ctx->buf(dst)); const unsigned src_pitch = ((struct nv04_surface *)src)->pitch; const unsigned max_w = 1024; const unsigned max_h = 1024; @@ -109,10 +110,10 @@ nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx, unsigned cx; unsigned cy; - /* POT or GTFO */ - assert(!(w & (w - 1)) && !(h & (h - 1))); +#if 0 /* That's the way she likes it */ assert(src_pitch == ((struct nv04_surface *)dst)->pitch); +#endif BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE, 1); OUT_RELOCo(chan, dst_bo, @@ -132,7 +133,7 @@ nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx, for (cy = 0; cy < h; cy += sub_h) { for (cx = 0; cx < w; cx += sub_w) { BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_OFFSET, 1); - OUT_RELOCl(chan, dst_bo, dst->offset + nv04_swizzle_bits(cx, cy) * + OUT_RELOCl(chan, dst_bo, dst->offset + nv04_swizzle_bits(cx+dx, cy+dy) * dst->texture->block.size, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); @@ -152,8 +153,8 @@ nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx, OUT_RING (chan, src_pitch | NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER | NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE); - OUT_RELOCl(chan, src_bo, src->offset + cy * src_pitch + - cx * src->texture->block.size, NOUVEAU_BO_GART | + OUT_RELOCl(chan, src_bo, src->offset + (cy+sy) * src_pitch + + (cx+sx) * src->texture->block.size, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); OUT_RING (chan, 0); } @@ -167,10 +168,10 @@ nv04_surface_copy_m2mf(struct nv04_surface_2d *ctx, struct pipe_surface *dst, int dx, int dy, struct pipe_surface *src, int sx, int sy, int w, int h) { - struct nouveau_channel *chan = ctx->nvws->channel; + struct nouveau_channel *chan = ctx->m2mf->channel; struct nouveau_grobj *m2mf = ctx->m2mf; - struct nouveau_bo *src_bo = ctx->nvws->get_bo(ctx->buf(src)); - struct nouveau_bo *dst_bo = ctx->nvws->get_bo(ctx->buf(dst)); + struct nouveau_bo *src_bo = nouveau_bo(ctx->buf(src)); + struct nouveau_bo *dst_bo = nouveau_bo(ctx->buf(dst)); unsigned src_pitch = ((struct nv04_surface *)src)->pitch; unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch; unsigned dst_offset = dst->offset + dy * dst_pitch + @@ -209,15 +210,52 @@ nv04_surface_copy_m2mf(struct nv04_surface_2d *ctx, } static int +nv04_surface_copy_m2mf_swizzle(struct nv04_surface_2d *ctx, + struct pipe_surface *dst, int dx, int dy, + struct pipe_surface *src, int sx, int sy) +{ + struct nouveau_channel *chan = ctx->m2mf->channel; + struct nouveau_grobj *m2mf = ctx->m2mf; + struct nouveau_bo *src_bo = nouveau_bo(ctx->buf(src)); + struct nouveau_bo *dst_bo = nouveau_bo(ctx->buf(dst)); + unsigned src_pitch = ((struct nv04_surface *)src)->pitch; + unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch; + unsigned dst_offset = dst->offset + nv04_swizzle_bits(dx, dy) * + dst->texture->block.size; + unsigned src_offset = src->offset + sy * src_pitch + + sx * src->texture->block.size; + + BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2); + OUT_RELOCo(chan, src_bo, + NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + OUT_RELOCo(chan, dst_bo, + NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + + BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); + OUT_RELOCl(chan, src_bo, src_offset, + NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); + OUT_RELOCl(chan, dst_bo, dst_offset, + NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR); + OUT_RING (chan, src_pitch); + OUT_RING (chan, dst_pitch); + OUT_RING (chan, 1 * src->texture->block.size); + OUT_RING (chan, 1); + OUT_RING (chan, 0x0101); + OUT_RING (chan, 0); + + return 0; +} + +static int nv04_surface_copy_blit(struct nv04_surface_2d *ctx, struct pipe_surface *dst, int dx, int dy, struct pipe_surface *src, int sx, int sy, int w, int h) { - struct nouveau_channel *chan = ctx->nvws->channel; + struct nouveau_channel *chan = ctx->surf2d->channel; struct nouveau_grobj *surf2d = ctx->surf2d; struct nouveau_grobj *blit = ctx->blit; - struct nouveau_bo *src_bo = ctx->nvws->get_bo(ctx->buf(src)); - struct nouveau_bo *dst_bo = ctx->nvws->get_bo(ctx->buf(dst)); + struct nouveau_bo *src_bo = nouveau_bo(ctx->buf(src)); + struct nouveau_bo *dst_bo = nouveau_bo(ctx->buf(dst)); unsigned src_pitch = ((struct nv04_surface *)src)->pitch; unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch; int format; @@ -257,8 +295,59 @@ nv04_surface_copy(struct nv04_surface_2d *ctx, struct pipe_surface *dst, assert(src->format == dst->format); /* Setup transfer to swizzle the texture to vram if needed */ - if (src_linear && !dst_linear && w > 1 && h > 1) { - nv04_surface_copy_swizzle(ctx, dst, dx, dy, src, sx, sy, w, h); + if (src_linear && !dst_linear) { + int x,y; + + if ((w>1) && (h>1)) { + int potWidth = 1<<log2i(w); + int potHeight = 1<<log2i(h); + int remainWidth = w-potWidth; + int remainHeight = h-potHeight; + int squareDim = (potWidth>potHeight ? potHeight : potWidth); + + /* top left is always POT, but we can only swizzle squares */ + for (y=0; y<potHeight; y+=squareDim) { + for (x=0; x<potWidth; x+= squareDim) { + nv04_surface_copy_swizzle(ctx, dst, dx+x, dy+y, + src, sx+x, sy+y, + squareDim, squareDim); + } + } + + /* top right */ + if (remainWidth>0) { + nv04_surface_copy(ctx, dst, dx+potWidth, dy, + src, sx+potWidth, sy, + remainWidth, potHeight); + } + + /* bottom left */ + if (remainHeight>0) { + nv04_surface_copy(ctx, dst, dx, dy+potHeight, + src, sx, sy+potHeight, + potWidth, remainHeight); + } + + /* bottom right */ + if ((remainWidth>0) && (remainHeight>0)) { + nv04_surface_copy(ctx, dst, dx+potWidth, dy+potHeight, + src, sx+potWidth, sy+potHeight, + remainWidth, remainHeight); + } + } else if (w==1) { + /* We have a column to copy to a swizzled texture */ + for (y=0; y<h; y++) { + nv04_surface_copy_m2mf_swizzle(ctx, dst, dx, dy+y, + src, sx, sy+y); + } + } else if (h==1) { + /* We have a row to copy to a swizzled texture */ + for (x=0; x<w; x++) { + nv04_surface_copy_m2mf_swizzle(ctx, dst, dx+x, dy, + src, sx+x, sy); + } + } + return; } @@ -266,8 +355,7 @@ nv04_surface_copy(struct nv04_surface_2d *ctx, struct pipe_surface *dst, * to NV_MEMORY_TO_MEMORY_FORMAT in this case. */ if ((src->offset & 63) || (dst->offset & 63) || - (src_pitch & 63) || (dst_pitch & 63) || - debug_get_bool_option("NOUVEAU_NO_COPYBLIT", FALSE)) { + (src_pitch & 63) || (dst_pitch & 63)) { nv04_surface_copy_m2mf(ctx, dst, dx, dy, src, sx, sy, w, h); return; } @@ -279,10 +367,10 @@ static void nv04_surface_fill(struct nv04_surface_2d *ctx, struct pipe_surface *dst, int dx, int dy, int w, int h, unsigned value) { - struct nouveau_channel *chan = ctx->nvws->channel; + struct nouveau_channel *chan = ctx->surf2d->channel; struct nouveau_grobj *surf2d = ctx->surf2d; struct nouveau_grobj *rect = ctx->rect; - struct nouveau_bo *dst_bo = ctx->nvws->get_bo(ctx->buf(dst)); + struct nouveau_bo *dst_bo = nouveau_bo(ctx->buf(dst)); unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch; int cs2d_format, gdirect_format; @@ -334,10 +422,10 @@ nv04_surface_2d_takedown(struct nv04_surface_2d **pctx) } struct nv04_surface_2d * -nv04_surface_2d_init(struct nouveau_winsys *nvws) +nv04_surface_2d_init(struct nouveau_screen *screen) { struct nv04_surface_2d *ctx = CALLOC_STRUCT(nv04_surface_2d); - struct nouveau_channel *chan = nvws->channel; + struct nouveau_channel *chan = screen->channel; unsigned handle = 0x88000000, class; int ret; @@ -460,7 +548,6 @@ nv04_surface_2d_init(struct nouveau_winsys *nvws) return NULL; } - ctx->nvws = nvws; ctx->copy = nv04_surface_copy; ctx->fill = nv04_surface_fill; return ctx; diff --git a/src/gallium/drivers/nv04/nv04_surface_2d.h b/src/gallium/drivers/nv04/nv04_surface_2d.h index 82ce7189c8b..02b3f56ba8b 100644 --- a/src/gallium/drivers/nv04/nv04_surface_2d.h +++ b/src/gallium/drivers/nv04/nv04_surface_2d.h @@ -7,7 +7,6 @@ struct nv04_surface { }; struct nv04_surface_2d { - struct nouveau_winsys *nvws; struct nouveau_notifier *ntfy; struct nouveau_grobj *surf2d; struct nouveau_grobj *swzsurf; @@ -26,7 +25,7 @@ struct nv04_surface_2d { }; struct nv04_surface_2d * -nv04_surface_2d_init(struct nouveau_winsys *nvws); +nv04_surface_2d_init(struct nouveau_screen *screen); void nv04_surface_2d_takedown(struct nv04_surface_2d **); diff --git a/src/gallium/drivers/nv04/nv04_vbo.c b/src/gallium/drivers/nv04/nv04_vbo.c index d21a0e34f71..e3167814f2b 100644 --- a/src/gallium/drivers/nv04/nv04_vbo.c +++ b/src/gallium/drivers/nv04/nv04_vbo.c @@ -1,6 +1,7 @@ #include "draw/draw_context.h" #include "pipe/p_context.h" #include "pipe/p_state.h" +#include "pipe/p_inlines.h" #include "nv04_context.h" #include "nv04_state.h" @@ -13,6 +14,7 @@ boolean nv04_draw_elements( struct pipe_context *pipe, unsigned indexSize, unsigned prim, unsigned start, unsigned count) { + struct pipe_screen *pscreen = pipe->screen; struct nv04_context *nv04 = nv04_context( pipe ); struct draw_context *draw = nv04->draw; unsigned i; @@ -25,17 +27,17 @@ boolean nv04_draw_elements( struct pipe_context *pipe, for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { if (nv04->vtxbuf[i].buffer) { void *buf - = pipe->winsys->buffer_map(pipe->winsys, - nv04->vtxbuf[i].buffer, - PIPE_BUFFER_USAGE_CPU_READ); + = pipe_buffer_map(pscreen, + nv04->vtxbuf[i].buffer, + PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_vertex_buffer(draw, i, buf); } } /* Map index buffer, if present */ if (indexBuffer) { void *mapped_indexes - = pipe->winsys->buffer_map(pipe->winsys, indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); + = pipe_buffer_map(pscreen, indexBuffer, + PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes); } else { @@ -55,12 +57,12 @@ boolean nv04_draw_elements( struct pipe_context *pipe, */ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { if (nv04->vtxbuf[i].buffer) { - pipe->winsys->buffer_unmap(pipe->winsys, nv04->vtxbuf[i].buffer); + pipe_buffer_unmap(pscreen, nv04->vtxbuf[i].buffer); draw_set_mapped_vertex_buffer(draw, i, NULL); } } if (indexBuffer) { - pipe->winsys->buffer_unmap(pipe->winsys, indexBuffer); + pipe_buffer_unmap(pscreen, indexBuffer); draw_set_mapped_element_buffer(draw, 0, NULL); } diff --git a/src/gallium/drivers/nv10/nv10_context.c b/src/gallium/drivers/nv10/nv10_context.c index 3da8d2f568f..a127b134ecd 100644 --- a/src/gallium/drivers/nv10/nv10_context.c +++ b/src/gallium/drivers/nv10/nv10_context.c @@ -30,18 +30,18 @@ nv10_destroy(struct pipe_context *pipe) static void nv10_init_hwctx(struct nv10_context *nv10) { struct nv10_screen *screen = nv10->screen; - struct nouveau_winsys *nvws = screen->nvws; + struct nouveau_channel *chan = screen->base.channel; int i; float projectionmatrix[16]; BEGIN_RING(celsius, NV10TCL_DMA_NOTIFY, 1); OUT_RING (screen->sync->handle); BEGIN_RING(celsius, NV10TCL_DMA_IN_MEMORY0, 2); - OUT_RING (nvws->channel->vram->handle); - OUT_RING (nvws->channel->gart->handle); + OUT_RING (chan->vram->handle); + OUT_RING (chan->gart->handle); BEGIN_RING(celsius, NV10TCL_DMA_IN_MEMORY2, 2); - OUT_RING (nvws->channel->vram->handle); - OUT_RING (nvws->channel->vram->handle); + OUT_RING (chan->vram->handle); + OUT_RING (chan->vram->handle); BEGIN_RING(celsius, NV10TCL_NOP, 1); OUT_RING (0); diff --git a/src/gallium/drivers/nv10/nv10_prim_vbuf.c b/src/gallium/drivers/nv10/nv10_prim_vbuf.c index 089c236302a..1806d5f8ccc 100644 --- a/src/gallium/drivers/nv10/nv10_prim_vbuf.c +++ b/src/gallium/drivers/nv10/nv10_prim_vbuf.c @@ -40,7 +40,6 @@ #include "util/u_debug.h" #include "pipe/p_inlines.h" -#include "pipe/internal/p_winsys_screen.h" #include "nv10_context.h" #include "nv10_state.h" @@ -124,11 +123,10 @@ nv10_vbuf_render_map_vertices( struct vbuf_render *render ) { struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); struct nv10_context *nv10 = nv10_render->nv10; - struct pipe_winsys *winsys = nv10->pipe.winsys; + struct pipe_screen *pscreen = nv10->pipe.screen; - return winsys->buffer_map(winsys, - nv10_render->buffer, - PIPE_BUFFER_USAGE_CPU_WRITE); + return pipe_buffer_map(pscreen, nv10_render->buffer, + PIPE_BUFFER_USAGE_CPU_WRITE); } static void @@ -138,10 +136,10 @@ nv10_vbuf_render_unmap_vertices( struct vbuf_render *render, { struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); struct nv10_context *nv10 = nv10_render->nv10; - struct pipe_winsys *winsys = nv10->pipe.winsys; + struct pipe_screen *pscreen = nv10->pipe.screen; assert(!nv10_render->buffer); - winsys->buffer_unmap(winsys, nv10_render->buffer); + pipe_buffer_unmap(pscreen, nv10_render->buffer); } static boolean @@ -202,8 +200,6 @@ static void nv10_vbuf_render_release_vertices( struct vbuf_render *render ) { struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); - struct nv10_context *nv10 = nv10_render->nv10; - struct pipe_screen *pscreen = &nv10->screen->pipe; assert(nv10_render->buffer); pipe_buffer_reference(&nv10_render->buffer, NULL); diff --git a/src/gallium/drivers/nv10/nv10_screen.c b/src/gallium/drivers/nv10/nv10_screen.c index 6532a93c7ba..4469b22d91a 100644 --- a/src/gallium/drivers/nv10/nv10_screen.c +++ b/src/gallium/drivers/nv10/nv10_screen.c @@ -1,26 +1,8 @@ #include "pipe/p_screen.h" -#include "util/u_simple_screen.h" #include "nv10_context.h" #include "nv10_screen.h" -static const char * -nv10_screen_get_name(struct pipe_screen *screen) -{ - struct nv10_screen *nv10screen = nv10_screen(screen); - struct nouveau_device *dev = nv10screen->nvws->channel->device; - static char buffer[128]; - - snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); - return buffer; -} - -static const char * -nv10_screen_get_vendor(struct pipe_screen *screen) -{ - return "nouveau"; -} - static int nv10_screen_get_param(struct pipe_screen *screen, int param) { @@ -53,6 +35,10 @@ nv10_screen_get_param(struct pipe_screen *screen, int param) return 12; case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: return 0; + case PIPE_CAP_TGSI_CONT_SUPPORTED: + return 0; + case PIPE_CAP_BLEND_EQUATION_SEPARATE: + return 0; case NOUVEAU_CAP_HW_VTXBUF: case NOUVEAU_CAP_HW_IDXBUF: return 0; @@ -92,7 +78,15 @@ nv10_screen_is_format_supported(struct pipe_screen *screen, switch (format) { case PIPE_FORMAT_A8R8G8B8_UNORM: case PIPE_FORMAT_R5G6B5_UNORM: + return TRUE; + default: + break; + } + } else + if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) { + switch (format) { case PIPE_FORMAT_Z24S8_UNORM: + case PIPE_FORMAT_Z24X8_UNORM: case PIPE_FORMAT_Z16_UNORM: return TRUE; default: @@ -120,10 +114,9 @@ static void nv10_screen_destroy(struct pipe_screen *pscreen) { struct nv10_screen *screen = nv10_screen(pscreen); - struct nouveau_winsys *nvws = screen->nvws; - nvws->notifier_free(&screen->sync); - nvws->grobj_free(&screen->celsius); + nouveau_notifier_free(&screen->sync); + nouveau_grobj_free(&screen->celsius); FREE(pscreen); } @@ -137,64 +130,69 @@ nv10_surface_buffer(struct pipe_surface *surf) } struct pipe_screen * -nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) +nv10_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) { struct nv10_screen *screen = CALLOC_STRUCT(nv10_screen); + struct nouveau_channel *chan; + struct pipe_screen *pscreen; unsigned celsius_class; - unsigned chipset = nvws->channel->device->chipset; int ret; if (!screen) return NULL; - screen->nvws = nvws; + pscreen = &screen->base.base; - /* 2D engine setup */ - screen->eng2d = nv04_surface_2d_init(nvws); - screen->eng2d->buf = nv10_surface_buffer; + ret = nouveau_screen_init(&screen->base, dev); + if (ret) { + nv10_screen_destroy(pscreen); + return NULL; + } + chan = screen->base.channel; + + pscreen->winsys = ws; + pscreen->destroy = nv10_screen_destroy; + pscreen->get_param = nv10_screen_get_param; + pscreen->get_paramf = nv10_screen_get_paramf; + pscreen->is_format_supported = nv10_screen_is_format_supported; + + nv10_screen_init_miptree_functions(pscreen); + nv10_screen_init_transfer_functions(pscreen); /* 3D object */ - if (chipset>=0x20) - celsius_class=NV11TCL; - else if (chipset>=0x17) - celsius_class=NV17TCL; - else if (chipset>=0x11) - celsius_class=NV11TCL; + if (dev->chipset >= 0x20) + celsius_class = NV11TCL; + else if (dev->chipset >= 0x17) + celsius_class = NV17TCL; + else if (dev->chipset >= 0x11) + celsius_class = NV11TCL; else - celsius_class=NV10TCL; + celsius_class = NV10TCL; if (!celsius_class) { - NOUVEAU_ERR("Unknown nv1x chipset: nv%02x\n", chipset); + NOUVEAU_ERR("Unknown nv1x chipset: nv%02x\n", dev->chipset); return NULL; } - ret = nvws->grobj_alloc(nvws, celsius_class, &screen->celsius); + ret = nouveau_grobj_alloc(chan, 0xbeef0001, celsius_class, + &screen->celsius); if (ret) { NOUVEAU_ERR("Error creating 3D object: %d\n", ret); return FALSE; } + BIND_RING(chan, screen->celsius, 7); + + /* 2D engine setup */ + screen->eng2d = nv04_surface_2d_init(&screen->base); + screen->eng2d->buf = nv10_surface_buffer; /* Notifier for sync purposes */ - ret = nvws->notifier_alloc(nvws, 1, &screen->sync); + ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); if (ret) { NOUVEAU_ERR("Error creating notifier object: %d\n", ret); - nv10_screen_destroy(&screen->pipe); + nv10_screen_destroy(pscreen); return NULL; } - screen->pipe.winsys = ws; - screen->pipe.destroy = nv10_screen_destroy; - - screen->pipe.get_name = nv10_screen_get_name; - screen->pipe.get_vendor = nv10_screen_get_vendor; - screen->pipe.get_param = nv10_screen_get_param; - screen->pipe.get_paramf = nv10_screen_get_paramf; - - screen->pipe.is_format_supported = nv10_screen_is_format_supported; - - nv10_screen_init_miptree_functions(&screen->pipe); - nv10_screen_init_transfer_functions(&screen->pipe); - u_simple_screen_init(&screen->pipe); - - return &screen->pipe; + return pscreen; } diff --git a/src/gallium/drivers/nv10/nv10_screen.h b/src/gallium/drivers/nv10/nv10_screen.h index ad829ee3fd4..86b6d8def54 100644 --- a/src/gallium/drivers/nv10/nv10_screen.h +++ b/src/gallium/drivers/nv10/nv10_screen.h @@ -1,11 +1,11 @@ #ifndef __NV10_SCREEN_H__ #define __NV10_SCREEN_H__ -#include "pipe/p_screen.h" +#include "nouveau/nouveau_screen.h" #include "nv04/nv04_surface_2d.h" struct nv10_screen { - struct pipe_screen pipe; + struct nouveau_screen base; struct nouveau_winsys *nvws; diff --git a/src/gallium/drivers/nv10/nv10_state.c b/src/gallium/drivers/nv10/nv10_state.c index 119af66dfd0..9b38219b996 100644 --- a/src/gallium/drivers/nv10/nv10_state.c +++ b/src/gallium/drivers/nv10/nv10_state.c @@ -2,6 +2,7 @@ #include "pipe/p_state.h" #include "pipe/p_defines.h" #include "pipe/p_shader_tokens.h" +#include "pipe/p_inlines.h" #include "tgsi/tgsi_parse.h" @@ -460,7 +461,7 @@ nv10_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, const struct pipe_constant_buffer *buf ) { struct nv10_context *nv10 = nv10_context(pipe); - struct pipe_winsys *ws = pipe->winsys; + struct pipe_screen *pscreen = pipe->screen; assert(shader < PIPE_SHADER_TYPES); assert(index == 0); @@ -468,12 +469,12 @@ nv10_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, if (buf) { void *mapped; if (buf->buffer && buf->buffer->size && - (mapped = ws->buffer_map(ws, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ))) + (mapped = pipe_buffer_map(pscreen, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ))) { memcpy(nv10->constbuf[shader], mapped, buf->buffer->size); nv10->constbuf_nr[shader] = buf->buffer->size / (4 * sizeof(float)); - ws->buffer_unmap(ws, buf->buffer); + pipe_buffer_unmap(pscreen, buf->buffer); } } } diff --git a/src/gallium/drivers/nv10/nv10_vbo.c b/src/gallium/drivers/nv10/nv10_vbo.c index d0e788ac036..441a4f75f3f 100644 --- a/src/gallium/drivers/nv10/nv10_vbo.c +++ b/src/gallium/drivers/nv10/nv10_vbo.c @@ -1,6 +1,7 @@ #include "draw/draw_context.h" #include "pipe/p_context.h" #include "pipe/p_state.h" +#include "pipe/p_inlines.h" #include "nv10_context.h" #include "nv10_state.h" @@ -15,6 +16,7 @@ boolean nv10_draw_elements( struct pipe_context *pipe, { struct nv10_context *nv10 = nv10_context( pipe ); struct draw_context *draw = nv10->draw; + struct pipe_screen *pscreen = pipe->screen; unsigned i; nv10_emit_hw_state(nv10); @@ -24,9 +26,8 @@ boolean nv10_draw_elements( struct pipe_context *pipe, */ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { if (nv10->vtxbuf[i].buffer) { - void *buf - = pipe->winsys->buffer_map(pipe->winsys, - nv10->vtxbuf[i].buffer, + void *buf = + pipe_buffer_map(pscreen, nv10->vtxbuf[i].buffer, PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_vertex_buffer(draw, i, buf); } @@ -34,8 +35,8 @@ boolean nv10_draw_elements( struct pipe_context *pipe, /* Map index buffer, if present */ if (indexBuffer) { void *mapped_indexes - = pipe->winsys->buffer_map(pipe->winsys, indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); + = pipe_buffer_map(pscreen, indexBuffer, + PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes); } else { @@ -55,12 +56,12 @@ boolean nv10_draw_elements( struct pipe_context *pipe, */ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { if (nv10->vtxbuf[i].buffer) { - pipe->winsys->buffer_unmap(pipe->winsys, nv10->vtxbuf[i].buffer); + pipe_buffer_unmap(pscreen, nv10->vtxbuf[i].buffer); draw_set_mapped_vertex_buffer(draw, i, NULL); } } if (indexBuffer) { - pipe->winsys->buffer_unmap(pipe->winsys, indexBuffer); + pipe_buffer_unmap(pscreen, indexBuffer); draw_set_mapped_element_buffer(draw, 0, NULL); } diff --git a/src/gallium/drivers/nv20/nv20_context.c b/src/gallium/drivers/nv20/nv20_context.c index cbc41707d54..b32d0d83ba0 100644 --- a/src/gallium/drivers/nv20/nv20_context.c +++ b/src/gallium/drivers/nv20/nv20_context.c @@ -30,7 +30,7 @@ nv20_destroy(struct pipe_context *pipe) static void nv20_init_hwctx(struct nv20_context *nv20) { struct nv20_screen *screen = nv20->screen; - struct nouveau_winsys *nvws = screen->nvws; + struct nouveau_channel *chan = screen->base.channel; int i; float projectionmatrix[16]; const boolean is_nv25tcl = (nv20->screen->kelvin->grclass == NV25TCL); @@ -38,11 +38,11 @@ static void nv20_init_hwctx(struct nv20_context *nv20) BEGIN_RING(kelvin, NV20TCL_DMA_NOTIFY, 1); OUT_RING (screen->sync->handle); BEGIN_RING(kelvin, NV20TCL_DMA_TEXTURE0, 2); - OUT_RING (nvws->channel->vram->handle); - OUT_RING (nvws->channel->gart->handle); /* TEXTURE1 */ + OUT_RING (chan->vram->handle); + OUT_RING (chan->gart->handle); /* TEXTURE1 */ BEGIN_RING(kelvin, NV20TCL_DMA_COLOR, 2); - OUT_RING (nvws->channel->vram->handle); - OUT_RING (nvws->channel->vram->handle); /* ZETA */ + OUT_RING (chan->vram->handle); + OUT_RING (chan->vram->handle); /* ZETA */ BEGIN_RING(kelvin, NV20TCL_DMA_QUERY, 1); OUT_RING (0); /* renouveau: beef0351, unique */ @@ -99,9 +99,9 @@ static void nv20_init_hwctx(struct nv20_context *nv20) OUT_RING (3); BEGIN_RING(kelvin, NV25TCL_DMA_IN_MEMORY9, 1); - OUT_RING (nvws->channel->vram->handle); + OUT_RING (chan->vram->handle); BEGIN_RING(kelvin, NV25TCL_DMA_IN_MEMORY8, 1); - OUT_RING (nvws->channel->vram->handle); + OUT_RING (chan->vram->handle); } BEGIN_RING(kelvin, NV20TCL_DMA_FENCE, 1); OUT_RING (0); /* renouveau: beef1e10 */ diff --git a/src/gallium/drivers/nv20/nv20_prim_vbuf.c b/src/gallium/drivers/nv20/nv20_prim_vbuf.c index 8aa342cd2db..ddfcdb8057a 100644 --- a/src/gallium/drivers/nv20/nv20_prim_vbuf.c +++ b/src/gallium/drivers/nv20/nv20_prim_vbuf.c @@ -152,12 +152,11 @@ static void * nv20_vbuf_render_map_vertices( struct vbuf_render *render ) { struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render); - struct pipe_winsys *winsys = nv20_render->nv20->pipe.winsys; + struct pipe_screen *pscreen = nv20_render->nv20->pipe.screen; if (nv20_render->pbuffer) { - return winsys->buffer_map(winsys, - nv20_render->pbuffer, - PIPE_BUFFER_USAGE_CPU_WRITE); + return pipe_buffer_map(pscreen, nv20_render->pbuffer, + PIPE_BUFFER_USAGE_CPU_WRITE); } else if (nv20_render->mbuffer) { return nv20_render->mbuffer; } else @@ -173,10 +172,10 @@ nv20_vbuf_render_unmap_vertices( struct vbuf_render *render, ushort max_index ) { struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render); - struct pipe_winsys *winsys = nv20_render->nv20->pipe.winsys; + struct pipe_screen *pscreen = nv20_render->nv20->pipe.screen; if (nv20_render->pbuffer) - winsys->buffer_unmap(winsys, nv20_render->pbuffer); + pipe_buffer_unmap(pscreen, nv20_render->pbuffer); } static boolean @@ -358,7 +357,6 @@ nv20_vbuf_render_release_vertices( struct vbuf_render *render ) { struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render); struct nv20_context *nv20 = nv20_render->nv20; - struct pipe_screen *pscreen = &nv20->screen->pipe; if (nv20_render->pbuffer) { pipe_buffer_reference(&nv20_render->pbuffer, NULL); diff --git a/src/gallium/drivers/nv20/nv20_screen.c b/src/gallium/drivers/nv20/nv20_screen.c index 7760ae27c0e..e6924ad71eb 100644 --- a/src/gallium/drivers/nv20/nv20_screen.c +++ b/src/gallium/drivers/nv20/nv20_screen.c @@ -1,26 +1,8 @@ #include "pipe/p_screen.h" -#include "util/u_simple_screen.h" #include "nv20_context.h" #include "nv20_screen.h" -static const char * -nv20_screen_get_name(struct pipe_screen *screen) -{ - struct nv20_screen *nv20screen = nv20_screen(screen); - struct nouveau_device *dev = nv20screen->nvws->channel->device; - static char buffer[128]; - - snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); - return buffer; -} - -static const char * -nv20_screen_get_vendor(struct pipe_screen *screen) -{ - return "nouveau"; -} - static int nv20_screen_get_param(struct pipe_screen *screen, int param) { @@ -53,6 +35,10 @@ nv20_screen_get_param(struct pipe_screen *screen, int param) return 12; case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: return 0; + case PIPE_CAP_TGSI_CONT_SUPPORTED: + return 0; + case PIPE_CAP_BLEND_EQUATION_SEPARATE: + return 0; case NOUVEAU_CAP_HW_VTXBUF: case NOUVEAU_CAP_HW_IDXBUF: return 0; @@ -92,7 +78,15 @@ nv20_screen_is_format_supported(struct pipe_screen *screen, switch (format) { case PIPE_FORMAT_A8R8G8B8_UNORM: case PIPE_FORMAT_R5G6B5_UNORM: + return TRUE; + default: + break; + } + } else + if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) { + switch (format) { case PIPE_FORMAT_Z24S8_UNORM: + case PIPE_FORMAT_Z24X8_UNORM: case PIPE_FORMAT_Z16_UNORM: return TRUE; default: @@ -120,10 +114,9 @@ static void nv20_screen_destroy(struct pipe_screen *pscreen) { struct nv20_screen *screen = nv20_screen(pscreen); - struct nouveau_winsys *nvws = screen->nvws; - nvws->notifier_free(&screen->sync); - nvws->grobj_free(&screen->kelvin); + nouveau_notifier_free(&screen->sync); + nouveau_grobj_free(&screen->kelvin); FREE(pscreen); } @@ -137,60 +130,65 @@ nv20_surface_buffer(struct pipe_surface *surf) } struct pipe_screen * -nv20_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) +nv20_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) { struct nv20_screen *screen = CALLOC_STRUCT(nv20_screen); + struct nouveau_channel *chan; + struct pipe_screen *pscreen; unsigned kelvin_class = 0; - unsigned chipset = nvws->channel->device->chipset; int ret; if (!screen) return NULL; - screen->nvws = nvws; + pscreen = &screen->base.base; - /* 2D engine setup */ - screen->eng2d = nv04_surface_2d_init(nvws); - screen->eng2d->buf = nv20_surface_buffer; + ret = nouveau_screen_init(&screen->base, dev); + if (ret) { + nv20_screen_destroy(pscreen); + return NULL; + } + chan = screen->base.channel; + + pscreen->winsys = ws; + pscreen->destroy = nv20_screen_destroy; + pscreen->get_param = nv20_screen_get_param; + pscreen->get_paramf = nv20_screen_get_paramf; + pscreen->is_format_supported = nv20_screen_is_format_supported; + + nv20_screen_init_miptree_functions(pscreen); + nv20_screen_init_transfer_functions(pscreen); /* 3D object */ - if (chipset >= 0x25) + if (dev->chipset >= 0x25) kelvin_class = NV25TCL; - else if (chipset >= 0x20) + else if (dev->chipset >= 0x20) kelvin_class = NV20TCL; - if (!kelvin_class || chipset >= 0x30) { - NOUVEAU_ERR("Unknown nv2x chipset: nv%02x\n", chipset); + if (!kelvin_class || dev->chipset >= 0x30) { + NOUVEAU_ERR("Unknown nv2x chipset: nv%02x\n", dev->chipset); return NULL; } - ret = nvws->grobj_alloc(nvws, kelvin_class, &screen->kelvin); + ret = nouveau_grobj_alloc(chan, 0xbeef0097, kelvin_class, + &screen->kelvin); if (ret) { NOUVEAU_ERR("Error creating 3D object: %d\n", ret); return FALSE; } + BIND_RING(chan, screen->kelvin, 7); + + /* 2D engine setup */ + screen->eng2d = nv04_surface_2d_init(&screen->base); + screen->eng2d->buf = nv20_surface_buffer; /* Notifier for sync purposes */ - ret = nvws->notifier_alloc(nvws, 1, &screen->sync); + ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); if (ret) { NOUVEAU_ERR("Error creating notifier object: %d\n", ret); - nv20_screen_destroy(&screen->pipe); + nv20_screen_destroy(pscreen); return NULL; } - screen->pipe.winsys = ws; - screen->pipe.destroy = nv20_screen_destroy; - - screen->pipe.get_name = nv20_screen_get_name; - screen->pipe.get_vendor = nv20_screen_get_vendor; - screen->pipe.get_param = nv20_screen_get_param; - screen->pipe.get_paramf = nv20_screen_get_paramf; - - screen->pipe.is_format_supported = nv20_screen_is_format_supported; - - nv20_screen_init_miptree_functions(&screen->pipe); - nv20_screen_init_transfer_functions(&screen->pipe); - u_simple_screen_init(&screen->pipe); - - return &screen->pipe; + return pscreen; } diff --git a/src/gallium/drivers/nv20/nv20_screen.h b/src/gallium/drivers/nv20/nv20_screen.h index d9fce2bced8..fc7bb050334 100644 --- a/src/gallium/drivers/nv20/nv20_screen.h +++ b/src/gallium/drivers/nv20/nv20_screen.h @@ -1,11 +1,11 @@ #ifndef __NV20_SCREEN_H__ #define __NV20_SCREEN_H__ -#include "pipe/p_screen.h" +#include "nouveau/nouveau_screen.h" #include "nv04/nv04_surface_2d.h" struct nv20_screen { - struct pipe_screen pipe; + struct nouveau_screen base; struct nouveau_winsys *nvws; diff --git a/src/gallium/drivers/nv20/nv20_state.c b/src/gallium/drivers/nv20/nv20_state.c index ecec4f49a0c..ed4084980f2 100644 --- a/src/gallium/drivers/nv20/nv20_state.c +++ b/src/gallium/drivers/nv20/nv20_state.c @@ -2,6 +2,7 @@ #include "pipe/p_state.h" #include "pipe/p_defines.h" #include "pipe/p_shader_tokens.h" +#include "pipe/p_inlines.h" #include "tgsi/tgsi_parse.h" @@ -453,7 +454,7 @@ nv20_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, const struct pipe_constant_buffer *buf ) { struct nv20_context *nv20 = nv20_context(pipe); - struct pipe_winsys *ws = pipe->winsys; + struct pipe_screen *pscreen = pipe->screen; assert(shader < PIPE_SHADER_TYPES); assert(index == 0); @@ -461,12 +462,12 @@ nv20_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, if (buf) { void *mapped; if (buf->buffer && buf->buffer->size && - (mapped = ws->buffer_map(ws, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ))) + (mapped = pipe_buffer_map(pscreen, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ))) { memcpy(nv20->constbuf[shader], mapped, buf->buffer->size); nv20->constbuf_nr[shader] = buf->buffer->size / (4 * sizeof(float)); - ws->buffer_unmap(ws, buf->buffer); + pipe_buffer_unmap(pscreen, buf->buffer); } } } diff --git a/src/gallium/drivers/nv20/nv20_vbo.c b/src/gallium/drivers/nv20/nv20_vbo.c index 24d8f4bef09..84d7db6c5e2 100644 --- a/src/gallium/drivers/nv20/nv20_vbo.c +++ b/src/gallium/drivers/nv20/nv20_vbo.c @@ -1,6 +1,7 @@ #include "draw/draw_context.h" #include "pipe/p_context.h" #include "pipe/p_state.h" +#include "pipe/p_inlines.h" #include "nv20_context.h" #include "nv20_state.h" @@ -13,6 +14,7 @@ boolean nv20_draw_elements( struct pipe_context *pipe, unsigned indexSize, unsigned prim, unsigned start, unsigned count) { + struct pipe_screen *pscreen = pipe->screen; struct nv20_context *nv20 = nv20_context( pipe ); struct draw_context *draw = nv20->draw; unsigned i; @@ -25,17 +27,17 @@ boolean nv20_draw_elements( struct pipe_context *pipe, for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { if (nv20->vtxbuf[i].buffer) { void *buf - = pipe->winsys->buffer_map(pipe->winsys, - nv20->vtxbuf[i].buffer, - PIPE_BUFFER_USAGE_CPU_READ); + = pipe_buffer_map(pscreen, + nv20->vtxbuf[i].buffer, + PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_vertex_buffer(draw, i, buf); } } /* Map index buffer, if present */ if (indexBuffer) { void *mapped_indexes - = pipe->winsys->buffer_map(pipe->winsys, indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); + = pipe_buffer_map(pscreen, indexBuffer, + PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes); } else { @@ -55,12 +57,12 @@ boolean nv20_draw_elements( struct pipe_context *pipe, */ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { if (nv20->vtxbuf[i].buffer) { - pipe->winsys->buffer_unmap(pipe->winsys, nv20->vtxbuf[i].buffer); + pipe_buffer_unmap(pscreen, nv20->vtxbuf[i].buffer); draw_set_mapped_vertex_buffer(draw, i, NULL); } } if (indexBuffer) { - pipe->winsys->buffer_unmap(pipe->winsys, indexBuffer); + pipe_buffer_unmap(pscreen, indexBuffer); draw_set_mapped_element_buffer(draw, 0, NULL); } diff --git a/src/gallium/drivers/nv20/nv20_vertprog.c b/src/gallium/drivers/nv20/nv20_vertprog.c index 5db0e807ff5..388245ecb04 100644 --- a/src/gallium/drivers/nv20/nv20_vertprog.c +++ b/src/gallium/drivers/nv20/nv20_vertprog.c @@ -1,6 +1,7 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" +#include "pipe/p_inlines.h" #include "pipe/p_shader_tokens.h" #include "tgsi/tgsi_parse.h" @@ -616,10 +617,10 @@ nv20_vertprog_translate(struct nv20_context *nv20, assert(imm->Immediate.NrTokens == 4 + 1); vpc->imm[vpc->nr_imm++] = constant(vpc, -1, - imm->u.ImmediateFloat32[0].Float, - imm->u.ImmediateFloat32[1].Float, - imm->u.ImmediateFloat32[2].Float, - imm->u.ImmediateFloat32[3].Float); + imm->u[0].Float, + imm->u[1].Float, + imm->u[2].Float, + imm->u[3].Float); } break; case TGSI_TOKEN_TYPE_INSTRUCTION: @@ -645,8 +646,8 @@ out_err: static boolean nv20_vertprog_validate(struct nv20_context *nv20) { + struct pipe_screen *pscreen = nv20->pipe.screen; struct nouveau_winsys *nvws = nv20->nvws; - struct pipe_winsys *ws = nv20->pipe.winsys; struct nouveau_grobj *rankine = nv20->screen->rankine; struct nv20_vertex_program *vp; struct pipe_buffer *constbuf; @@ -749,8 +750,8 @@ nv20_vertprog_validate(struct nv20_context *nv20) float *map = NULL; if (constbuf) { - map = ws->buffer_map(ws, constbuf, - PIPE_BUFFER_USAGE_CPU_READ); + map = pipe_buffer_map(pscreen, constbuf, + PIPE_BUFFER_USAGE_CPU_READ); } for (i = 0; i < vp->nr_consts; i++) { @@ -770,9 +771,8 @@ nv20_vertprog_validate(struct nv20_context *nv20) OUT_RINGp ((uint32_t *)vpd->value, 4); } - if (constbuf) { - ws->buffer_unmap(ws, constbuf); - } + if (constbuf) + pipe_buffer_unmap(pscreen, constbuf); } /* Upload vtxprog */ diff --git a/src/gallium/drivers/nv30/nv30_fragprog.c b/src/gallium/drivers/nv30/nv30_fragprog.c index bdfe1425d24..a48ba9782b3 100644 --- a/src/gallium/drivers/nv30/nv30_fragprog.c +++ b/src/gallium/drivers/nv30/nv30_fragprog.c @@ -1,6 +1,7 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" +#include "pipe/p_inlines.h" #include "pipe/p_shader_tokens.h" #include "tgsi/tgsi_parse.h" @@ -703,10 +704,10 @@ nv30_fragprog_prepare(struct nv30_fpc *fpc) assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32); assert(fpc->nr_imm < MAX_IMM); - vals[0] = imm->u.ImmediateFloat32[0].Float; - vals[1] = imm->u.ImmediateFloat32[1].Float; - vals[2] = imm->u.ImmediateFloat32[2].Float; - vals[3] = imm->u.ImmediateFloat32[3].Float; + vals[0] = imm->u[0].Float; + vals[1] = imm->u[1].Float; + vals[2] = imm->u[2].Float; + vals[3] = imm->u[3].Float; fpc->imm[fpc->nr_imm++] = constant(fpc, -1, vals); } break; @@ -798,12 +799,12 @@ static void nv30_fragprog_upload(struct nv30_context *nv30, struct nv30_fragment_program *fp) { - struct pipe_winsys *ws = nv30->pipe.winsys; + struct pipe_screen *pscreen = nv30->pipe.screen; const uint32_t le = 1; uint32_t *map; int i; - map = ws->buffer_map(ws, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE); + map = pipe_buffer_map(pscreen, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE); #if 0 for (i = 0; i < fp->insn_len; i++) { @@ -825,7 +826,7 @@ nv30_fragprog_upload(struct nv30_context *nv30, } } - ws->buffer_unmap(ws, fp->buffer); + pipe_buffer_unmap(pscreen, fp->buffer); } static boolean @@ -834,8 +835,7 @@ nv30_fragprog_validate(struct nv30_context *nv30) struct nv30_fragment_program *fp = nv30->fragprog; struct pipe_buffer *constbuf = nv30->constbuf[PIPE_SHADER_FRAGMENT]; - struct pipe_screen *screen = nv30->pipe.screen; - struct pipe_winsys *ws = nv30->pipe.winsys; + struct pipe_screen *pscreen = nv30->pipe.screen; struct nouveau_stateobj *so; boolean new_consts = FALSE; int i; @@ -850,14 +850,15 @@ nv30_fragprog_validate(struct nv30_context *nv30) return FALSE; } - fp->buffer = screen->buffer_create(screen, 0x100, 0, fp->insn_len * 4); + fp->buffer = pscreen->buffer_create(pscreen, 0x100, 0, fp->insn_len * 4); nv30_fragprog_upload(nv30, fp); so = so_new(8, 1); so_method(so, nv30->screen->rankine, NV34TCL_FP_ACTIVE_PROGRAM, 1); - so_reloc (so, fp->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | - NOUVEAU_BO_RD | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, - NV34TCL_FP_ACTIVE_PROGRAM_DMA0, NV34TCL_FP_ACTIVE_PROGRAM_DMA1); + so_reloc (so, nouveau_bo(fp->buffer), 0, NOUVEAU_BO_VRAM | + NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW | + NOUVEAU_BO_OR, NV34TCL_FP_ACTIVE_PROGRAM_DMA0, + NV34TCL_FP_ACTIVE_PROGRAM_DMA1); so_method(so, nv30->screen->rankine, NV34TCL_FP_CONTROL, 1); so_data (so, fp->fp_control); so_method(so, nv30->screen->rankine, NV34TCL_FP_REG_CONTROL, 1); @@ -871,7 +872,8 @@ update_constants: if (fp->nr_consts) { float *map; - map = ws->buffer_map(ws, constbuf, PIPE_BUFFER_USAGE_CPU_READ); + map = pipe_buffer_map(pscreen, constbuf, + PIPE_BUFFER_USAGE_CPU_READ); for (i = 0; i < fp->nr_consts; i++) { struct nv30_fragment_program_data *fpd = &fp->consts[i]; uint32_t *p = &fp->insn[fpd->offset]; @@ -882,7 +884,7 @@ update_constants: memcpy(p, cb, 4 * sizeof(float)); new_consts = TRUE; } - ws->buffer_unmap(ws, constbuf); + pipe_buffer_unmap(pscreen, constbuf); if (new_consts) nv30_fragprog_upload(nv30, fp); diff --git a/src/gallium/drivers/nv30/nv30_fragtex.c b/src/gallium/drivers/nv30/nv30_fragtex.c index 8b6ab992d16..822e1d8defe 100644 --- a/src/gallium/drivers/nv30/nv30_fragtex.c +++ b/src/gallium/drivers/nv30/nv30_fragtex.c @@ -61,6 +61,7 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit) struct nv30_sampler_state *ps = nv30->tex_sampler[unit]; struct nv30_miptree *nv30mt = nv30->tex_miptree[unit]; struct pipe_texture *pt = &nv30mt->base; + struct nouveau_bo *bo = nouveau_bo(nv30mt->buffer); struct nv30_texture_format *tf; struct nouveau_stateobj *so; uint32_t txf, txs , txp; @@ -106,9 +107,9 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit) so = so_new(16, 2); so_method(so, nv30->screen->rankine, NV34TCL_TX_OFFSET(unit), 8); - so_reloc (so, nv30mt->buffer, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0); - so_reloc (so, nv30mt->buffer, txf, tex_flags | NOUVEAU_BO_OR, - NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1); + so_reloc (so, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0); + so_reloc (so, bo, txf, tex_flags | NOUVEAU_BO_OR, + NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1); so_data (so, ps->wrap); so_data (so, NV34TCL_TX_ENABLE_ENABLE | ps->en); so_data (so, txs); diff --git a/src/gallium/drivers/nv30/nv30_query.c b/src/gallium/drivers/nv30/nv30_query.c index 2f974cf5c40..1d1c8a484e1 100644 --- a/src/gallium/drivers/nv30/nv30_query.c +++ b/src/gallium/drivers/nv30/nv30_query.c @@ -29,11 +29,10 @@ nv30_query_create(struct pipe_context *pipe, unsigned query_type) static void nv30_query_destroy(struct pipe_context *pipe, struct pipe_query *pq) { - struct nv30_context *nv30 = nv30_context(pipe); struct nv30_query *q = nv30_query(pq); if (q->object) - nv30->nvws->res_free(&q->object); + nouveau_resource_free(&q->object); FREE(q); } @@ -54,9 +53,9 @@ nv30_query_begin(struct pipe_context *pipe, struct pipe_query *pq) pipe->get_query_result(pipe, pq, 1, &tmp); } - if (nv30->nvws->res_alloc(nv30->screen->query_heap, 1, NULL, &q->object)) + if (nouveau_resource_alloc(nv30->screen->query_heap, 1, NULL, &q->object)) assert(0); - nv30->nvws->notifier_reset(nv30->screen->query, q->object->start); + nouveau_notifier_reset(nv30->screen->query, q->object->start); BEGIN_RING(rankine, NV34TCL_QUERY_RESET, 1); OUT_RING (1); @@ -84,27 +83,27 @@ nv30_query_result(struct pipe_context *pipe, struct pipe_query *pq, { struct nv30_context *nv30 = nv30_context(pipe); struct nv30_query *q = nv30_query(pq); - struct nouveau_winsys *nvws = nv30->nvws; assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER); if (!q->ready) { unsigned status; - status = nvws->notifier_status(nv30->screen->query, - q->object->start); + status = nouveau_notifier_status(nv30->screen->query, + q->object->start); if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) { if (wait == FALSE) return FALSE; - nvws->notifier_wait(nv30->screen->query, q->object->start, - NV_NOTIFY_STATE_STATUS_COMPLETED, - 0); + + nouveau_notifier_wait_status(nv30->screen->query, + q->object->start, + NV_NOTIFY_STATE_STATUS_COMPLETED, 0); } - q->result = nvws->notifier_retval(nv30->screen->query, - q->object->start); + q->result = nouveau_notifier_return_val(nv30->screen->query, + q->object->start); q->ready = TRUE; - nvws->res_free(&q->object); + nouveau_resource_free(&q->object); } *result = q->result; diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c index d395c5e1b7f..f8285e4455f 100644 --- a/src/gallium/drivers/nv30/nv30_screen.c +++ b/src/gallium/drivers/nv30/nv30_screen.c @@ -1,5 +1,7 @@ #include "pipe/p_screen.h" -#include "util/u_simple_screen.h" +#include "pipe/p_state.h" + +#include "nouveau/nouveau_screen.h" #include "nv30_context.h" #include "nv30_screen.h" @@ -8,23 +10,6 @@ #define NV34TCL_CHIPSET_3X_MASK 0x00000010 #define NV35TCL_CHIPSET_3X_MASK 0x000001e0 -static const char * -nv30_screen_get_name(struct pipe_screen *pscreen) -{ - struct nv30_screen *screen = nv30_screen(pscreen); - struct nouveau_device *dev = screen->nvws->channel->device; - static char buffer[128]; - - snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); - return buffer; -} - -static const char * -nv30_screen_get_vendor(struct pipe_screen *pscreen) -{ - return "nouveau"; -} - static int nv30_screen_get_param(struct pipe_screen *pscreen, int param) { @@ -61,6 +46,10 @@ nv30_screen_get_param(struct pipe_screen *pscreen, int param) return 1; case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: return 0; + case PIPE_CAP_TGSI_CONT_SUPPORTED: + return 0; + case PIPE_CAP_BLEND_EQUATION_SEPARATE: + return 0; case NOUVEAU_CAP_HW_VTXBUF: case NOUVEAU_CAP_HW_IDXBUF: return 1; @@ -100,7 +89,15 @@ nv30_screen_surface_format_supported(struct pipe_screen *pscreen, switch (format) { case PIPE_FORMAT_A8R8G8B8_UNORM: case PIPE_FORMAT_R5G6B5_UNORM: + return TRUE; + default: + break; + } + } else + if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) { + switch (format) { case PIPE_FORMAT_Z24S8_UNORM: + case PIPE_FORMAT_Z24X8_UNORM: case PIPE_FORMAT_Z16_UNORM: return TRUE; default: @@ -139,45 +136,57 @@ static void nv30_screen_destroy(struct pipe_screen *pscreen) { struct nv30_screen *screen = nv30_screen(pscreen); - struct nouveau_winsys *nvws = screen->nvws; - nvws->res_free(&screen->vp_exec_heap); - nvws->res_free(&screen->vp_data_heap); - nvws->res_free(&screen->query_heap); - nvws->notifier_free(&screen->query); - nvws->notifier_free(&screen->sync); - nvws->grobj_free(&screen->rankine); + nouveau_resource_free(&screen->vp_exec_heap); + nouveau_resource_free(&screen->vp_data_heap); + nouveau_resource_free(&screen->query_heap); + nouveau_notifier_free(&screen->query); + nouveau_notifier_free(&screen->sync); + nouveau_grobj_free(&screen->rankine); FREE(pscreen); } struct pipe_screen * -nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) +nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) { struct nv30_screen *screen = CALLOC_STRUCT(nv30_screen); + struct nouveau_channel *chan; + struct pipe_screen *pscreen; struct nouveau_stateobj *so; unsigned rankine_class = 0; - unsigned chipset = nvws->channel->device->chipset; int ret, i; if (!screen) return NULL; - screen->nvws = nvws; + pscreen = &screen->base.base; - /* 2D engine setup */ - screen->eng2d = nv04_surface_2d_init(nvws); - screen->eng2d->buf = nv30_surface_buffer; + ret = nouveau_screen_init(&screen->base, dev); + if (ret) { + nv30_screen_destroy(pscreen); + return NULL; + } + chan = screen->base.channel; + + pscreen->winsys = ws; + pscreen->destroy = nv30_screen_destroy; + pscreen->get_param = nv30_screen_get_param; + pscreen->get_paramf = nv30_screen_get_paramf; + pscreen->is_format_supported = nv30_screen_surface_format_supported; + + nv30_screen_init_miptree_functions(pscreen); + nv30_screen_init_transfer_functions(pscreen); /* 3D object */ - switch (chipset & 0xf0) { + switch (dev->chipset & 0xf0) { case 0x30: - if (NV30TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f))) + if (NV30TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f))) rankine_class = 0x0397; else - if (NV34TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f))) + if (NV34TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f))) rankine_class = 0x0697; else - if (NV35TCL_CHIPSET_3X_MASK & (1 << (chipset & 0x0f))) + if (NV35TCL_CHIPSET_3X_MASK & (1 << (dev->chipset & 0x0f))) rankine_class = 0x0497; break; default: @@ -185,43 +194,49 @@ nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) } if (!rankine_class) { - NOUVEAU_ERR("Unknown nv3x chipset: nv%02x\n", chipset); + NOUVEAU_ERR("Unknown nv3x chipset: nv%02x\n", dev->chipset); return NULL; } - ret = nvws->grobj_alloc(nvws, rankine_class, &screen->rankine); + ret = nouveau_grobj_alloc(chan, 0xbeef3097, rankine_class, + &screen->rankine); if (ret) { NOUVEAU_ERR("Error creating 3D object: %d\n", ret); return FALSE; } + BIND_RING(chan, screen->rankine, 7); + + /* 2D engine setup */ + screen->eng2d = nv04_surface_2d_init(&screen->base); + screen->eng2d->buf = nv30_surface_buffer; /* Notifier for sync purposes */ - ret = nvws->notifier_alloc(nvws, 1, &screen->sync); + ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); if (ret) { NOUVEAU_ERR("Error creating notifier object: %d\n", ret); - nv30_screen_destroy(&screen->pipe); + nv30_screen_destroy(pscreen); return NULL; } /* Query objects */ - ret = nvws->notifier_alloc(nvws, 32, &screen->query); + ret = nouveau_notifier_alloc(chan, 0xbeef0302, 32, &screen->query); if (ret) { NOUVEAU_ERR("Error initialising query objects: %d\n", ret); - nv30_screen_destroy(&screen->pipe); + nv30_screen_destroy(pscreen); return NULL; } - ret = nvws->res_init(&screen->query_heap, 0, 32); + ret = nouveau_resource_init(&screen->query_heap, 0, 32); if (ret) { NOUVEAU_ERR("Error initialising query object heap: %d\n", ret); - nv30_screen_destroy(&screen->pipe); + nv30_screen_destroy(pscreen); return NULL; } /* Vtxprog resources */ - if (nvws->res_init(&screen->vp_exec_heap, 0, 256) || - nvws->res_init(&screen->vp_data_heap, 0, 256)) { - nv30_screen_destroy(&screen->pipe); + if (nouveau_resource_init(&screen->vp_exec_heap, 0, 256) || + nouveau_resource_init(&screen->vp_data_heap, 0, 256)) { + nv30_screen_destroy(pscreen); return NULL; } @@ -230,23 +245,23 @@ nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) so_method(so, screen->rankine, NV34TCL_DMA_NOTIFY, 1); so_data (so, screen->sync->handle); so_method(so, screen->rankine, NV34TCL_DMA_TEXTURE0, 2); - so_data (so, nvws->channel->vram->handle); - so_data (so, nvws->channel->gart->handle); + so_data (so, chan->vram->handle); + so_data (so, chan->gart->handle); so_method(so, screen->rankine, NV34TCL_DMA_COLOR1, 1); - so_data (so, nvws->channel->vram->handle); + so_data (so, chan->vram->handle); so_method(so, screen->rankine, NV34TCL_DMA_COLOR0, 2); - so_data (so, nvws->channel->vram->handle); - so_data (so, nvws->channel->vram->handle); + so_data (so, chan->vram->handle); + so_data (so, chan->vram->handle); so_method(so, screen->rankine, NV34TCL_DMA_VTXBUF0, 2); - so_data (so, nvws->channel->vram->handle); - so_data (so, nvws->channel->gart->handle); + so_data (so, chan->vram->handle); + so_data (so, chan->gart->handle); /* so_method(so, screen->rankine, NV34TCL_DMA_FENCE, 2); so_data (so, 0); so_data (so, screen->query->handle);*/ so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY7, 1); - so_data (so, nvws->channel->vram->handle); + so_data (so, chan->vram->handle); so_method(so, screen->rankine, NV34TCL_DMA_IN_MEMORY8, 1); - so_data (so, nvws->channel->vram->handle); + so_data (so, chan->vram->handle); for (i=1; i<8; i++) { so_method(so, screen->rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(i), 1); @@ -301,23 +316,9 @@ nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) so_method(so, screen->rankine, 0x1e94, 1); so_data (so, 0x13); - so_emit(nvws, so); + so_emit(chan, so); so_ref(NULL, &so); - nvws->push_flush(nvws, 0, NULL); - - screen->pipe.winsys = ws; - screen->pipe.destroy = nv30_screen_destroy; - - screen->pipe.get_name = nv30_screen_get_name; - screen->pipe.get_vendor = nv30_screen_get_vendor; - screen->pipe.get_param = nv30_screen_get_param; - screen->pipe.get_paramf = nv30_screen_get_paramf; - - screen->pipe.is_format_supported = nv30_screen_surface_format_supported; - - nv30_screen_init_miptree_functions(&screen->pipe); - nv30_screen_init_transfer_functions(&screen->pipe); - u_simple_screen_init(&screen->pipe); + nouveau_pushbuf_flush(chan, 0); - return &screen->pipe; + return pscreen; } diff --git a/src/gallium/drivers/nv30/nv30_screen.h b/src/gallium/drivers/nv30/nv30_screen.h index 8e368839759..5fbd998b539 100644 --- a/src/gallium/drivers/nv30/nv30_screen.h +++ b/src/gallium/drivers/nv30/nv30_screen.h @@ -1,11 +1,12 @@ #ifndef __NV30_SCREEN_H__ #define __NV30_SCREEN_H__ -#include "pipe/p_screen.h" +#include "nouveau/nouveau_screen.h" + #include "nv04/nv04_surface_2d.h" struct nv30_screen { - struct pipe_screen pipe; + struct nouveau_screen base; struct nouveau_winsys *nvws; diff --git a/src/gallium/drivers/nv30/nv30_state_emit.c b/src/gallium/drivers/nv30/nv30_state_emit.c index c18be20a327..621b8846c8e 100644 --- a/src/gallium/drivers/nv30/nv30_state_emit.c +++ b/src/gallium/drivers/nv30/nv30_state_emit.c @@ -38,6 +38,7 @@ nv30_state_do_validate(struct nv30_context *nv30, void nv30_state_emit(struct nv30_context *nv30) { + struct nouveau_channel *chan = nv30->screen->base.channel; struct nv30_state *state = &nv30->state; struct nv30_screen *screen = nv30->screen; unsigned i, samplers; @@ -57,23 +58,23 @@ nv30_state_emit(struct nv30_context *nv30) continue; so_ref (state->hw[i], &nv30->screen->state[i]); if (state->hw[i]) - so_emit(nv30->nvws, nv30->screen->state[i]); + so_emit(chan, nv30->screen->state[i]); states &= ~(1ULL << i); } state->dirty = 0; - so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_FB]); + so_emit_reloc_markers(chan, state->hw[NV30_STATE_FB]); for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) { if (!(samplers & (1 << i))) continue; - so_emit_reloc_markers(nv30->nvws, + so_emit_reloc_markers(chan, state->hw[NV30_STATE_FRAGTEX0+i]); samplers &= ~(1ULL << i); } - so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_FRAGPROG]); + so_emit_reloc_markers(chan, state->hw[NV30_STATE_FRAGPROG]); if (state->hw[NV30_STATE_VTXBUF] /*&& nv30->render_mode == HW*/) - so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_VTXBUF]); + so_emit_reloc_markers(chan, state->hw[NV30_STATE_VTXBUF]); } boolean diff --git a/src/gallium/drivers/nv30/nv30_state_fb.c b/src/gallium/drivers/nv30/nv30_state_fb.c index fdc1cade905..44b6a74715a 100644 --- a/src/gallium/drivers/nv30/nv30_state_fb.c +++ b/src/gallium/drivers/nv30/nv30_state_fb.c @@ -5,6 +5,8 @@ static boolean nv30_state_framebuffer_validate(struct nv30_context *nv30) { struct pipe_framebuffer_state *fb = &nv30->framebuffer; + struct nouveau_channel *chan = nv30->screen->base.channel; + struct nouveau_grobj *rankine = nv30->screen->rankine; struct nv04_surface *rt[2], *zeta = NULL; uint32_t rt_enable, rt_format; int i, colour_format = 0, zeta_format = 0; @@ -63,6 +65,7 @@ nv30_state_framebuffer_validate(struct nv30_context *nv30) rt_format |= NV34TCL_RT_FORMAT_ZETA_Z16; break; case PIPE_FORMAT_Z24S8_UNORM: + case PIPE_FORMAT_Z24X8_UNORM: case 0: rt_format |= NV34TCL_RT_FORMAT_ZETA_Z24S8; break; @@ -79,56 +82,53 @@ nv30_state_framebuffer_validate(struct nv30_context *nv30) } nv30mt = (struct nv30_miptree *)rt[0]->base.texture; - so_method(so, nv30->screen->rankine, NV34TCL_DMA_COLOR0, 1); - so_reloc (so, nv30mt->buffer, 0, rt_flags | NOUVEAU_BO_OR, - nv30->nvws->channel->vram->handle, - nv30->nvws->channel->gart->handle); - so_method(so, nv30->screen->rankine, NV34TCL_COLOR0_PITCH, 2); + so_method(so, rankine, NV34TCL_DMA_COLOR0, 1); + so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, rankine, NV34TCL_COLOR0_PITCH, 2); so_data (so, pitch); - so_reloc (so, nv30mt->buffer, rt[0]->base.offset, rt_flags | - NOUVEAU_BO_LOW, 0, 0); + so_reloc (so, nouveau_bo(nv30mt->buffer), rt[0]->base.offset, + rt_flags | NOUVEAU_BO_LOW, 0, 0); } if (rt_enable & NV34TCL_RT_ENABLE_COLOR1) { nv30mt = (struct nv30_miptree *)rt[1]->base.texture; - so_method(so, nv30->screen->rankine, NV34TCL_DMA_COLOR1, 1); - so_reloc (so, nv30mt->buffer, 0, rt_flags | NOUVEAU_BO_OR, - nv30->nvws->channel->vram->handle, - nv30->nvws->channel->gart->handle); - so_method(so, nv30->screen->rankine, NV34TCL_COLOR1_OFFSET, 2); - so_reloc (so, nv30mt->buffer, rt[1]->base.offset, rt_flags | - NOUVEAU_BO_LOW, 0, 0); + so_method(so, rankine, NV34TCL_DMA_COLOR1, 1); + so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, rankine, NV34TCL_COLOR1_OFFSET, 2); + so_reloc (so, nouveau_bo(nv30mt->buffer), rt[1]->base.offset, + rt_flags | NOUVEAU_BO_LOW, 0, 0); so_data (so, rt[1]->pitch); } if (zeta_format) { nv30mt = (struct nv30_miptree *)zeta->base.texture; - so_method(so, nv30->screen->rankine, NV34TCL_DMA_ZETA, 1); - so_reloc (so, nv30mt->buffer, 0, rt_flags | NOUVEAU_BO_OR, - nv30->nvws->channel->vram->handle, - nv30->nvws->channel->gart->handle); - so_method(so, nv30->screen->rankine, NV34TCL_ZETA_OFFSET, 1); - so_reloc (so, nv30mt->buffer, zeta->base.offset, rt_flags | - NOUVEAU_BO_LOW, 0, 0); + so_method(so, rankine, NV34TCL_DMA_ZETA, 1); + so_reloc (so, nouveau_bo(nv30mt->buffer), 0, rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, rankine, NV34TCL_ZETA_OFFSET, 1); + so_reloc (so, nouveau_bo(nv30mt->buffer), zeta->base.offset, + rt_flags | NOUVEAU_BO_LOW, 0, 0); /* TODO: allocate LMA depth buffer */ } - so_method(so, nv30->screen->rankine, NV34TCL_RT_ENABLE, 1); + so_method(so, rankine, NV34TCL_RT_ENABLE, 1); so_data (so, rt_enable); - so_method(so, nv30->screen->rankine, NV34TCL_RT_HORIZ, 3); + so_method(so, rankine, NV34TCL_RT_HORIZ, 3); so_data (so, (w << 16) | 0); so_data (so, (h << 16) | 0); so_data (so, rt_format); - so_method(so, nv30->screen->rankine, NV34TCL_VIEWPORT_HORIZ, 2); + so_method(so, rankine, NV34TCL_VIEWPORT_HORIZ, 2); so_data (so, (w << 16) | 0); so_data (so, (h << 16) | 0); - so_method(so, nv30->screen->rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2); + so_method(so, rankine, NV34TCL_VIEWPORT_CLIP_HORIZ(0), 2); so_data (so, ((w - 1) << 16) | 0); so_data (so, ((h - 1) << 16) | 0); - so_method(so, nv30->screen->rankine, 0x1d88, 1); + so_method(so, rankine, 0x1d88, 1); so_data (so, (1 << 12) | h); /* Wonder why this is needed, context should all be set to zero on init */ - so_method(so, nv30->screen->rankine, NV34TCL_VIEWPORT_TX_ORIGIN, 1); + so_method(so, rankine, NV34TCL_VIEWPORT_TX_ORIGIN, 1); so_data (so, 0); so_ref(so, &nv30->state.hw[NV30_STATE_FB]); diff --git a/src/gallium/drivers/nv30/nv30_vbo.c b/src/gallium/drivers/nv30/nv30_vbo.c index 990a8763824..189656ec817 100644 --- a/src/gallium/drivers/nv30/nv30_vbo.c +++ b/src/gallium/drivers/nv30/nv30_vbo.c @@ -1,5 +1,6 @@ #include "pipe/p_context.h" #include "pipe/p_state.h" +#include "pipe/p_inlines.h" #include "nv30_context.h" #include "nv30_state.h" @@ -70,7 +71,7 @@ static boolean nv30_vbo_set_idxbuf(struct nv30_context *nv30, struct pipe_buffer *ib, unsigned ib_size) { - struct pipe_screen *pscreen = &nv30->screen->pipe; + struct pipe_screen *pscreen = &nv30->screen->base.base; unsigned type; if (!ib) { @@ -108,7 +109,7 @@ nv30_vbo_static_attrib(struct nv30_context *nv30, struct nouveau_stateobj *so, int attrib, struct pipe_vertex_element *ve, struct pipe_vertex_buffer *vb) { - struct pipe_winsys *ws = nv30->pipe.winsys; + struct pipe_screen *pscreen = nv30->pipe.screen; struct nouveau_grobj *rankine = nv30->screen->rankine; unsigned type, ncomp; void *map; @@ -116,7 +117,7 @@ nv30_vbo_static_attrib(struct nv30_context *nv30, struct nouveau_stateobj *so, if (nv30_vbo_format_to_hw(ve->src_format, &type, &ncomp)) return FALSE; - map = ws->buffer_map(ws, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); + map = pipe_buffer_map(pscreen, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); map += vb->buffer_offset + ve->src_offset; switch (type) { @@ -148,18 +149,17 @@ nv30_vbo_static_attrib(struct nv30_context *nv30, struct nouveau_stateobj *so, so_data (so, fui(v[0])); break; default: - ws->buffer_unmap(ws, vb->buffer); + pipe_buffer_unmap(pscreen, vb->buffer); return FALSE; } } break; default: - ws->buffer_unmap(ws, vb->buffer); + pipe_buffer_unmap(pscreen, vb->buffer); return FALSE; } - ws->buffer_unmap(ws, vb->buffer); - + pipe_buffer_unmap(pscreen, vb->buffer); return TRUE; } @@ -168,7 +168,7 @@ nv30_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { struct nv30_context *nv30 = nv30_context(pipe); - struct nouveau_channel *chan = nv30->nvws->channel; + struct nouveau_channel *chan = nv30->screen->base.channel; unsigned restart = 0; nv30_vbo_set_idxbuf(nv30, NULL, 0); @@ -228,7 +228,7 @@ static INLINE void nv30_draw_elements_u08(struct nv30_context *nv30, void *ib, unsigned mode, unsigned start, unsigned count) { - struct nouveau_channel *chan = nv30->nvws->channel; + struct nouveau_channel *chan = nv30->screen->base.channel; while (count) { uint8_t *elts = (uint8_t *)ib + start; @@ -277,7 +277,7 @@ static INLINE void nv30_draw_elements_u16(struct nv30_context *nv30, void *ib, unsigned mode, unsigned start, unsigned count) { - struct nouveau_channel *chan = nv30->nvws->channel; + struct nouveau_channel *chan = nv30->screen->base.channel; while (count) { uint16_t *elts = (uint16_t *)ib + start; @@ -326,7 +326,7 @@ static INLINE void nv30_draw_elements_u32(struct nv30_context *nv30, void *ib, unsigned mode, unsigned start, unsigned count) { - struct nouveau_channel *chan = nv30->nvws->channel; + struct nouveau_channel *chan = nv30->screen->base.channel; while (count) { uint32_t *elts = (uint32_t *)ib + start; @@ -368,10 +368,10 @@ nv30_draw_elements_inline(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { struct nv30_context *nv30 = nv30_context(pipe); - struct pipe_winsys *ws = pipe->winsys; + struct pipe_screen *pscreen = pipe->screen; void *map; - map = ws->buffer_map(ws, ib, PIPE_BUFFER_USAGE_CPU_READ); + map = pipe_buffer_map(pscreen, ib, PIPE_BUFFER_USAGE_CPU_READ); if (!ib) { NOUVEAU_ERR("failed mapping ib\n"); return FALSE; @@ -392,7 +392,7 @@ nv30_draw_elements_inline(struct pipe_context *pipe, break; } - ws->buffer_unmap(ws, ib); + pipe_buffer_unmap(pscreen, ib); return TRUE; } @@ -401,7 +401,7 @@ nv30_draw_elements_vbo(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { struct nv30_context *nv30 = nv30_context(pipe); - struct nouveau_channel *chan = nv30->nvws->channel; + struct nouveau_channel *chan = nv30->screen->base.channel; unsigned restart = 0; while (count) { @@ -521,18 +521,20 @@ nv30_vbo_validate(struct nv30_context *nv30) return FALSE; } - so_reloc(vtxbuf, vb->buffer, vb->buffer_offset + ve->src_offset, - vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, - 0, NV34TCL_VTXBUF_ADDRESS_DMA1); + so_reloc(vtxbuf, nouveau_bo(vb->buffer), vb->buffer_offset + + ve->src_offset, vb_flags | NOUVEAU_BO_LOW | + NOUVEAU_BO_OR, 0, NV34TCL_VTXBUF_ADDRESS_DMA1); so_data (vtxfmt, ((vb->stride << NV34TCL_VTXFMT_STRIDE_SHIFT) | (ncomp << NV34TCL_VTXFMT_SIZE_SHIFT) | type)); } if (ib) { + struct nouveau_bo *bo = nouveau_bo(ib); + so_method(vtxbuf, rankine, NV34TCL_IDXBUF_ADDRESS, 2); - so_reloc (vtxbuf, ib, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0); - so_reloc (vtxbuf, ib, ib_format, vb_flags | NOUVEAU_BO_OR, - 0, NV34TCL_IDXBUF_FORMAT_DMA1); + so_reloc (vtxbuf, bo, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0); + so_reloc (vtxbuf, bo, ib_format, vb_flags | NOUVEAU_BO_OR, + 0, NV34TCL_IDXBUF_FORMAT_DMA1); } so_method(vtxbuf, rankine, 0x1710, 1); diff --git a/src/gallium/drivers/nv30/nv30_vertprog.c b/src/gallium/drivers/nv30/nv30_vertprog.c index eaf543b8f79..14a5c0260d0 100644 --- a/src/gallium/drivers/nv30/nv30_vertprog.c +++ b/src/gallium/drivers/nv30/nv30_vertprog.c @@ -1,6 +1,7 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" +#include "pipe/p_inlines.h" #include "pipe/p_shader_tokens.h" #include "tgsi/tgsi_parse.h" @@ -616,10 +617,10 @@ nv30_vertprog_translate(struct nv30_context *nv30, assert(imm->Immediate.NrTokens == 4 + 1); vpc->imm[vpc->nr_imm++] = constant(vpc, -1, - imm->u.ImmediateFloat32[0].Float, - imm->u.ImmediateFloat32[1].Float, - imm->u.ImmediateFloat32[2].Float, - imm->u.ImmediateFloat32[3].Float); + imm->u[0].Float, + imm->u[1].Float, + imm->u[2].Float, + imm->u[3].Float); } break; case TGSI_TOKEN_TYPE_INSTRUCTION: @@ -645,8 +646,7 @@ out_err: static boolean nv30_vertprog_validate(struct nv30_context *nv30) { - struct nouveau_winsys *nvws = nv30->nvws; - struct pipe_winsys *ws = nv30->pipe.winsys; + struct pipe_screen *pscreen = nv30->pipe.screen; struct nouveau_grobj *rankine = nv30->screen->rankine; struct nv30_vertex_program *vp; struct pipe_buffer *constbuf; @@ -669,15 +669,15 @@ nv30_vertprog_validate(struct nv30_context *nv30) struct nouveau_stateobj *so; uint vplen = vp->nr_insns; - if (nvws->res_alloc(heap, vplen, vp, &vp->exec)) { + if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec)) { while (heap->next && heap->size < vplen) { struct nv30_vertex_program *evict; evict = heap->next->priv; - nvws->res_free(&evict->exec); + nouveau_resource_free(&evict->exec); } - if (nvws->res_alloc(heap, vplen, vp, &vp->exec)) + if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec)) assert(0); } @@ -694,15 +694,16 @@ nv30_vertprog_validate(struct nv30_context *nv30) if (vp->nr_consts && !vp->data) { struct nouveau_resource *heap = nv30->screen->vp_data_heap; - if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) { + if (nouveau_resource_alloc(heap, vp->nr_consts, vp, &vp->data)) { while (heap->next && heap->size < vp->nr_consts) { struct nv30_vertex_program *evict; evict = heap->next->priv; - nvws->res_free(&evict->data); + nouveau_resource_free(&evict->data); } - if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) + if (nouveau_resource_alloc(heap, vp->nr_consts, vp, + &vp->data)) assert(0); } @@ -750,8 +751,8 @@ nv30_vertprog_validate(struct nv30_context *nv30) float *map = NULL; if (constbuf) { - map = ws->buffer_map(ws, constbuf, - PIPE_BUFFER_USAGE_CPU_READ); + map = pipe_buffer_map(pscreen, constbuf, + PIPE_BUFFER_USAGE_CPU_READ); } for (i = 0; i < vp->nr_consts; i++) { @@ -771,9 +772,8 @@ nv30_vertprog_validate(struct nv30_context *nv30) OUT_RINGp ((uint32_t *)vpd->value, 4); } - if (constbuf) { - ws->buffer_unmap(ws, constbuf); - } + if (constbuf) + pipe_buffer_unmap(pscreen, constbuf); } /* Upload vtxprog */ @@ -804,8 +804,6 @@ nv30_vertprog_validate(struct nv30_context *nv30) void nv30_vertprog_destroy(struct nv30_context *nv30, struct nv30_vertex_program *vp) { - struct nouveau_winsys *nvws = nv30->screen->nvws; - vp->translated = FALSE; if (vp->nr_insns) { @@ -820,9 +818,9 @@ nv30_vertprog_destroy(struct nv30_context *nv30, struct nv30_vertex_program *vp) vp->nr_consts = 0; } - nvws->res_free(&vp->exec); + nouveau_resource_free(&vp->exec); vp->exec_start = 0; - nvws->res_free(&vp->data); + nouveau_resource_free(&vp->data); vp->data_start = 0; vp->data_start_min = 0; diff --git a/src/gallium/drivers/nv40/nv40_draw.c b/src/gallium/drivers/nv40/nv40_draw.c index c83ff91d7e3..b2f19ecb699 100644 --- a/src/gallium/drivers/nv40/nv40_draw.c +++ b/src/gallium/drivers/nv40/nv40_draw.c @@ -1,4 +1,5 @@ #include "pipe/p_shader_tokens.h" +#include "pipe/p_inlines.h" #include "util/u_pack_color.h" @@ -81,7 +82,7 @@ nv40_render_prim(struct draw_stage *stage, struct prim_header *prim, { struct nv40_render_stage *rs = nv40_render_stage(stage); struct nv40_context *nv40 = rs->nv40; - struct nouveau_pushbuf *pb = nv40->nvws->channel->pushbuf; + struct nouveau_pushbuf *pb = nv40->screen->base.channel->pushbuf; unsigned i; /* Ensure there's room for 4xfloat32 + potentially 3 begin/end */ @@ -231,7 +232,7 @@ nv40_draw_elements_swtnl(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { struct nv40_context *nv40 = nv40_context(pipe); - struct pipe_winsys *ws = pipe->winsys; + struct pipe_screen *pscreen = pipe->screen; unsigned i; void *map; @@ -241,13 +242,14 @@ nv40_draw_elements_swtnl(struct pipe_context *pipe, nv40_state_emit(nv40); for (i = 0; i < nv40->vtxbuf_nr; i++) { - map = ws->buffer_map(ws, nv40->vtxbuf[i].buffer, + map = pipe_buffer_map(pscreen, nv40->vtxbuf[i].buffer, PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_vertex_buffer(nv40->draw, i, map); } if (idxbuf) { - map = ws->buffer_map(ws, idxbuf, PIPE_BUFFER_USAGE_CPU_READ); + map = pipe_buffer_map(pscreen, idxbuf, + PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_element_buffer(nv40->draw, idxbuf_size, map); } else { draw_set_mapped_element_buffer(nv40->draw, 0, NULL); @@ -256,21 +258,22 @@ nv40_draw_elements_swtnl(struct pipe_context *pipe, if (nv40->constbuf[PIPE_SHADER_VERTEX]) { const unsigned nr = nv40->constbuf_nr[PIPE_SHADER_VERTEX]; - map = ws->buffer_map(ws, nv40->constbuf[PIPE_SHADER_VERTEX], - PIPE_BUFFER_USAGE_CPU_READ); + map = pipe_buffer_map(pscreen, + nv40->constbuf[PIPE_SHADER_VERTEX], + PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_constant_buffer(nv40->draw, map, nr); } draw_arrays(nv40->draw, mode, start, count); for (i = 0; i < nv40->vtxbuf_nr; i++) - ws->buffer_unmap(ws, nv40->vtxbuf[i].buffer); + pipe_buffer_unmap(pscreen, nv40->vtxbuf[i].buffer); if (idxbuf) - ws->buffer_unmap(ws, idxbuf); + pipe_buffer_unmap(pscreen, idxbuf); if (nv40->constbuf[PIPE_SHADER_VERTEX]) - ws->buffer_unmap(ws, nv40->constbuf[PIPE_SHADER_VERTEX]); + pipe_buffer_unmap(pscreen, nv40->constbuf[PIPE_SHADER_VERTEX]); draw_flush(nv40->draw); pipe->flush(pipe, 0, NULL); diff --git a/src/gallium/drivers/nv40/nv40_fragprog.c b/src/gallium/drivers/nv40/nv40_fragprog.c index 16e40889ec3..32d9ed1a7f8 100644 --- a/src/gallium/drivers/nv40/nv40_fragprog.c +++ b/src/gallium/drivers/nv40/nv40_fragprog.c @@ -1,6 +1,7 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" +#include "pipe/p_inlines.h" #include "pipe/p_shader_tokens.h" #include "tgsi/tgsi_parse.h" @@ -789,10 +790,10 @@ nv40_fragprog_prepare(struct nv40_fpc *fpc) assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32); assert(fpc->nr_imm < MAX_IMM); - vals[0] = imm->u.ImmediateFloat32[0].Float; - vals[1] = imm->u.ImmediateFloat32[1].Float; - vals[2] = imm->u.ImmediateFloat32[2].Float; - vals[3] = imm->u.ImmediateFloat32[3].Float; + vals[0] = imm->u[0].Float; + vals[1] = imm->u[1].Float; + vals[2] = imm->u[2].Float; + vals[3] = imm->u[3].Float; fpc->imm[fpc->nr_imm++] = constant(fpc, -1, vals); } break; @@ -881,12 +882,12 @@ static void nv40_fragprog_upload(struct nv40_context *nv40, struct nv40_fragment_program *fp) { - struct pipe_winsys *ws = nv40->pipe.winsys; + struct pipe_screen *pscreen = nv40->pipe.screen; const uint32_t le = 1; uint32_t *map; int i; - map = ws->buffer_map(ws, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE); + map = pipe_buffer_map(pscreen, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE); #if 0 for (i = 0; i < fp->insn_len; i++) { @@ -908,7 +909,7 @@ nv40_fragprog_upload(struct nv40_context *nv40, } } - ws->buffer_unmap(ws, fp->buffer); + pipe_buffer_unmap(pscreen, fp->buffer); } static boolean @@ -917,8 +918,7 @@ nv40_fragprog_validate(struct nv40_context *nv40) struct nv40_fragment_program *fp = nv40->fragprog; struct pipe_buffer *constbuf = nv40->constbuf[PIPE_SHADER_FRAGMENT]; - struct pipe_screen *screen = nv40->pipe.screen; - struct pipe_winsys *ws = nv40->pipe.winsys; + struct pipe_screen *pscreen = nv40->pipe.screen; struct nouveau_stateobj *so; boolean new_consts = FALSE; int i; @@ -933,14 +933,15 @@ nv40_fragprog_validate(struct nv40_context *nv40) return FALSE; } - fp->buffer = screen->buffer_create(screen, 0x100, 0, fp->insn_len * 4); + fp->buffer = pscreen->buffer_create(pscreen, 0x100, 0, fp->insn_len * 4); nv40_fragprog_upload(nv40, fp); so = so_new(4, 1); so_method(so, nv40->screen->curie, NV40TCL_FP_ADDRESS, 1); - so_reloc (so, fp->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | - NOUVEAU_BO_RD | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, - NV40TCL_FP_ADDRESS_DMA0, NV40TCL_FP_ADDRESS_DMA1); + so_reloc (so, nouveau_bo(fp->buffer), 0, NOUVEAU_BO_VRAM | + NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW | + NOUVEAU_BO_OR, NV40TCL_FP_ADDRESS_DMA0, + NV40TCL_FP_ADDRESS_DMA1); so_method(so, nv40->screen->curie, NV40TCL_FP_CONTROL, 1); so_data (so, fp->fp_control); so_ref(so, &fp->so); @@ -950,7 +951,8 @@ update_constants: if (fp->nr_consts) { float *map; - map = ws->buffer_map(ws, constbuf, PIPE_BUFFER_USAGE_CPU_READ); + map = pipe_buffer_map(pscreen, constbuf, + PIPE_BUFFER_USAGE_CPU_READ); for (i = 0; i < fp->nr_consts; i++) { struct nv40_fragment_program_data *fpd = &fp->consts[i]; uint32_t *p = &fp->insn[fpd->offset]; @@ -961,7 +963,7 @@ update_constants: memcpy(p, cb, 4 * sizeof(float)); new_consts = TRUE; } - ws->buffer_unmap(ws, constbuf); + pipe_buffer_unmap(pscreen, constbuf); if (new_consts) nv40_fragprog_upload(nv40, fp); diff --git a/src/gallium/drivers/nv40/nv40_fragtex.c b/src/gallium/drivers/nv40/nv40_fragtex.c index eb3002dc053..f6cdf31dfee 100644 --- a/src/gallium/drivers/nv40/nv40_fragtex.c +++ b/src/gallium/drivers/nv40/nv40_fragtex.c @@ -62,6 +62,7 @@ nv40_fragtex_build(struct nv40_context *nv40, int unit) { struct nv40_sampler_state *ps = nv40->tex_sampler[unit]; struct nv40_miptree *nv40mt = nv40->tex_miptree[unit]; + struct nouveau_bo *bo = nouveau_bo(nv40mt->buffer); struct pipe_texture *pt = &nv40mt->base; struct nv40_texture_format *tf; struct nouveau_stateobj *so; @@ -108,9 +109,9 @@ nv40_fragtex_build(struct nv40_context *nv40, int unit) so = so_new(16, 2); so_method(so, nv40->screen->curie, NV40TCL_TEX_OFFSET(unit), 8); - so_reloc (so, nv40mt->buffer, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0); - so_reloc (so, nv40mt->buffer, txf, tex_flags | NOUVEAU_BO_OR, - NV40TCL_TEX_FORMAT_DMA0, NV40TCL_TEX_FORMAT_DMA1); + so_reloc (so, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0); + so_reloc (so, bo, txf, tex_flags | NOUVEAU_BO_OR, + NV40TCL_TEX_FORMAT_DMA0, NV40TCL_TEX_FORMAT_DMA1); so_data (so, ps->wrap); so_data (so, NV40TCL_TEX_ENABLE_ENABLE | ps->en); so_data (so, txs); diff --git a/src/gallium/drivers/nv40/nv40_query.c b/src/gallium/drivers/nv40/nv40_query.c index 9b9a43f49df..7874aedd428 100644 --- a/src/gallium/drivers/nv40/nv40_query.c +++ b/src/gallium/drivers/nv40/nv40_query.c @@ -29,11 +29,10 @@ nv40_query_create(struct pipe_context *pipe, unsigned query_type) static void nv40_query_destroy(struct pipe_context *pipe, struct pipe_query *pq) { - struct nv40_context *nv40 = nv40_context(pipe); struct nv40_query *q = nv40_query(pq); if (q->object) - nv40->nvws->res_free(&q->object); + nouveau_resource_free(&q->object); FREE(q); } @@ -54,9 +53,9 @@ nv40_query_begin(struct pipe_context *pipe, struct pipe_query *pq) pipe->get_query_result(pipe, pq, 1, &tmp); } - if (nv40->nvws->res_alloc(nv40->screen->query_heap, 1, NULL, &q->object)) + if (nouveau_resource_alloc(nv40->screen->query_heap, 1, NULL, &q->object)) assert(0); - nv40->nvws->notifier_reset(nv40->screen->query, q->object->start); + nouveau_notifier_reset(nv40->screen->query, q->object->start); BEGIN_RING(curie, NV40TCL_QUERY_RESET, 1); OUT_RING (1); @@ -84,27 +83,27 @@ nv40_query_result(struct pipe_context *pipe, struct pipe_query *pq, { struct nv40_context *nv40 = nv40_context(pipe); struct nv40_query *q = nv40_query(pq); - struct nouveau_winsys *nvws = nv40->nvws; assert(q->object && q->type == PIPE_QUERY_OCCLUSION_COUNTER); if (!q->ready) { unsigned status; - status = nvws->notifier_status(nv40->screen->query, - q->object->start); + status = nouveau_notifier_status(nv40->screen->query, + q->object->start); if (status != NV_NOTIFY_STATE_STATUS_COMPLETED) { if (wait == FALSE) return FALSE; - nvws->notifier_wait(nv40->screen->query, q->object->start, - NV_NOTIFY_STATE_STATUS_COMPLETED, - 0); + nouveau_notifier_wait_status(nv40->screen->query, + q->object->start, + NV_NOTIFY_STATE_STATUS_COMPLETED, + 0); } - q->result = nvws->notifier_retval(nv40->screen->query, - q->object->start); + q->result = nouveau_notifier_return_val(nv40->screen->query, + q->object->start); q->ready = TRUE; - nvws->res_free(&q->object); + nouveau_resource_free(&q->object); } *result = q->result; diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c index 0d4baefaea3..5d2a4216c5a 100644 --- a/src/gallium/drivers/nv40/nv40_screen.c +++ b/src/gallium/drivers/nv40/nv40_screen.c @@ -1,5 +1,4 @@ #include "pipe/p_screen.h" -#include "util/u_simple_screen.h" #include "nv40_context.h" #include "nv40_screen.h" @@ -8,23 +7,6 @@ #define NV4X_GRCLASS4497_CHIPSETS 0x00005450 #define NV6X_GRCLASS4497_CHIPSETS 0x00000088 -static const char * -nv40_screen_get_name(struct pipe_screen *pscreen) -{ - struct nv40_screen *screen = nv40_screen(pscreen); - struct nouveau_device *dev = screen->nvws->channel->device; - static char buffer[128]; - - snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); - return buffer; -} - -static const char * -nv40_screen_get_vendor(struct pipe_screen *pscreen) -{ - return "nouveau"; -} - static int nv40_screen_get_param(struct pipe_screen *pscreen, int param) { @@ -62,6 +44,10 @@ nv40_screen_get_param(struct pipe_screen *pscreen, int param) return 1; case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: return 0; /* We have 4 - but unsupported currently */ + case PIPE_CAP_TGSI_CONT_SUPPORTED: + return 0; + case PIPE_CAP_BLEND_EQUATION_SEPARATE: + return 1; case NOUVEAU_CAP_HW_VTXBUF: return 1; case NOUVEAU_CAP_HW_IDXBUF: @@ -104,7 +90,15 @@ nv40_screen_surface_format_supported(struct pipe_screen *pscreen, switch (format) { case PIPE_FORMAT_A8R8G8B8_UNORM: case PIPE_FORMAT_R5G6B5_UNORM: + return TRUE; + default: + break; + } + } else + if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) { + switch (format) { case PIPE_FORMAT_Z24S8_UNORM: + case PIPE_FORMAT_Z24X8_UNORM: case PIPE_FORMAT_Z16_UNORM: return TRUE; default: @@ -148,88 +142,107 @@ static void nv40_screen_destroy(struct pipe_screen *pscreen) { struct nv40_screen *screen = nv40_screen(pscreen); - struct nouveau_winsys *nvws = screen->nvws; - nvws->res_free(&screen->vp_exec_heap); - nvws->res_free(&screen->vp_data_heap); - nvws->res_free(&screen->query_heap); - nvws->notifier_free(&screen->query); - nvws->notifier_free(&screen->sync); - nvws->grobj_free(&screen->curie); + nouveau_resource_free(&screen->vp_exec_heap); + nouveau_resource_free(&screen->vp_data_heap); + nouveau_resource_free(&screen->query_heap); + nouveau_notifier_free(&screen->query); + nouveau_notifier_free(&screen->sync); + nouveau_grobj_free(&screen->curie); + + nouveau_screen_fini(&screen->base); FREE(pscreen); } struct pipe_screen * -nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) +nv40_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) { struct nv40_screen *screen = CALLOC_STRUCT(nv40_screen); + struct nouveau_channel *chan; + struct pipe_screen *pscreen; struct nouveau_stateobj *so; unsigned curie_class = 0; - unsigned chipset = nvws->channel->device->chipset; int ret; if (!screen) return NULL; - screen->nvws = nvws; + pscreen = &screen->base.base; - /* 2D engine setup */ - screen->eng2d = nv04_surface_2d_init(nvws); - screen->eng2d->buf = nv40_surface_buffer; + ret = nouveau_screen_init(&screen->base, dev); + if (ret) { + nv40_screen_destroy(pscreen); + return NULL; + } + chan = screen->base.channel; + + pscreen->winsys = ws; + pscreen->destroy = nv40_screen_destroy; + pscreen->get_param = nv40_screen_get_param; + pscreen->get_paramf = nv40_screen_get_paramf; + pscreen->is_format_supported = nv40_screen_surface_format_supported; + + nv40_screen_init_miptree_functions(pscreen); + nv40_screen_init_transfer_functions(pscreen); /* 3D object */ - switch (chipset & 0xf0) { + switch (dev->chipset & 0xf0) { case 0x40: - if (NV4X_GRCLASS4097_CHIPSETS & (1 << (chipset & 0x0f))) + if (NV4X_GRCLASS4097_CHIPSETS & (1 << (dev->chipset & 0x0f))) curie_class = NV40TCL; else - if (NV4X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f))) + if (NV4X_GRCLASS4497_CHIPSETS & (1 << (dev->chipset & 0x0f))) curie_class = NV44TCL; break; case 0x60: - if (NV6X_GRCLASS4497_CHIPSETS & (1 << (chipset & 0x0f))) + if (NV6X_GRCLASS4497_CHIPSETS & (1 << (dev->chipset & 0x0f))) curie_class = NV44TCL; break; } if (!curie_class) { - NOUVEAU_ERR("Unknown nv4x chipset: nv%02x\n", chipset); + NOUVEAU_ERR("Unknown nv4x chipset: nv%02x\n", dev->chipset); return NULL; } - ret = nvws->grobj_alloc(nvws, curie_class, &screen->curie); + ret = nouveau_grobj_alloc(chan, 0xbeef3097, curie_class, &screen->curie); if (ret) { NOUVEAU_ERR("Error creating 3D object: %d\n", ret); return FALSE; } + BIND_RING(chan, screen->curie, 7); + + /* 2D engine setup */ + screen->eng2d = nv04_surface_2d_init(&screen->base); + screen->eng2d->buf = nv40_surface_buffer; /* Notifier for sync purposes */ - ret = nvws->notifier_alloc(nvws, 1, &screen->sync); + ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); if (ret) { NOUVEAU_ERR("Error creating notifier object: %d\n", ret); - nv40_screen_destroy(&screen->pipe); + nv40_screen_destroy(pscreen); return NULL; } /* Query objects */ - ret = nvws->notifier_alloc(nvws, 32, &screen->query); + ret = nouveau_notifier_alloc(chan, 0xbeef0302, 32, &screen->query); if (ret) { NOUVEAU_ERR("Error initialising query objects: %d\n", ret); - nv40_screen_destroy(&screen->pipe); + nv40_screen_destroy(pscreen); return NULL; } - ret = nvws->res_init(&screen->query_heap, 0, 32); + nouveau_resource_init(&screen->query_heap, 0, 32); if (ret) { NOUVEAU_ERR("Error initialising query object heap: %d\n", ret); - nv40_screen_destroy(&screen->pipe); + nv40_screen_destroy(pscreen); return NULL; } /* Vtxprog resources */ - if (nvws->res_init(&screen->vp_exec_heap, 0, 512) || - nvws->res_init(&screen->vp_data_heap, 0, 256)) { - nv40_screen_destroy(&screen->pipe); + if (nouveau_resource_init(&screen->vp_exec_heap, 0, 512) || + nouveau_resource_init(&screen->vp_data_heap, 0, 256)) { + nv40_screen_destroy(pscreen); return NULL; } @@ -238,25 +251,25 @@ nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) so_method(so, screen->curie, NV40TCL_DMA_NOTIFY, 1); so_data (so, screen->sync->handle); so_method(so, screen->curie, NV40TCL_DMA_TEXTURE0, 2); - so_data (so, nvws->channel->vram->handle); - so_data (so, nvws->channel->gart->handle); + so_data (so, chan->vram->handle); + so_data (so, chan->gart->handle); so_method(so, screen->curie, NV40TCL_DMA_COLOR1, 1); - so_data (so, nvws->channel->vram->handle); + so_data (so, chan->vram->handle); so_method(so, screen->curie, NV40TCL_DMA_COLOR0, 2); - so_data (so, nvws->channel->vram->handle); - so_data (so, nvws->channel->vram->handle); + so_data (so, chan->vram->handle); + so_data (so, chan->vram->handle); so_method(so, screen->curie, NV40TCL_DMA_VTXBUF0, 2); - so_data (so, nvws->channel->vram->handle); - so_data (so, nvws->channel->gart->handle); + so_data (so, chan->vram->handle); + so_data (so, chan->gart->handle); so_method(so, screen->curie, NV40TCL_DMA_FENCE, 2); so_data (so, 0); so_data (so, screen->query->handle); so_method(so, screen->curie, NV40TCL_DMA_UNK01AC, 2); - so_data (so, nvws->channel->vram->handle); - so_data (so, nvws->channel->vram->handle); + so_data (so, chan->vram->handle); + so_data (so, chan->vram->handle); so_method(so, screen->curie, NV40TCL_DMA_COLOR2, 2); - so_data (so, nvws->channel->vram->handle); - so_data (so, nvws->channel->vram->handle); + so_data (so, chan->vram->handle); + so_data (so, chan->vram->handle); so_method(so, screen->curie, 0x1ea4, 3); so_data (so, 0x00000010); @@ -281,24 +294,10 @@ nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) so_method(so, screen->curie, 0x1e94, 1); so_data (so, 0x00000001); - so_emit(nvws, so); + so_emit(chan, so); so_ref(NULL, &so); - nvws->push_flush(nvws, 0, NULL); - - screen->pipe.winsys = ws; - screen->pipe.destroy = nv40_screen_destroy; - - screen->pipe.get_name = nv40_screen_get_name; - screen->pipe.get_vendor = nv40_screen_get_vendor; - screen->pipe.get_param = nv40_screen_get_param; - screen->pipe.get_paramf = nv40_screen_get_paramf; - - screen->pipe.is_format_supported = nv40_screen_surface_format_supported; - - nv40_screen_init_miptree_functions(&screen->pipe); - nv40_screen_init_transfer_functions(&screen->pipe); - u_simple_screen_init(&screen->pipe); + nouveau_pushbuf_flush(chan, 0); - return &screen->pipe; + return pscreen; } diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h index 7b503bd207d..57b4c8fc46c 100644 --- a/src/gallium/drivers/nv40/nv40_screen.h +++ b/src/gallium/drivers/nv40/nv40_screen.h @@ -1,11 +1,11 @@ #ifndef __NV40_SCREEN_H__ #define __NV40_SCREEN_H__ -#include "pipe/p_screen.h" +#include "nouveau/nouveau_screen.h" #include "nv04/nv04_surface_2d.h" struct nv40_screen { - struct pipe_screen pipe; + struct nouveau_screen base; struct nouveau_winsys *nvws; diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c index 10aae298328..198692965dc 100644 --- a/src/gallium/drivers/nv40/nv40_state_emit.c +++ b/src/gallium/drivers/nv40/nv40_state_emit.c @@ -54,6 +54,7 @@ nv40_state_do_validate(struct nv40_context *nv40, void nv40_state_emit(struct nv40_context *nv40) { + struct nouveau_channel *chan = nv40->screen->base.channel; struct nv40_state *state = &nv40->state; struct nv40_screen *screen = nv40->screen; unsigned i, samplers; @@ -73,7 +74,7 @@ nv40_state_emit(struct nv40_context *nv40) continue; so_ref (state->hw[i], &nv40->screen->state[i]); if (state->hw[i]) - so_emit(nv40->nvws, nv40->screen->state[i]); + so_emit(chan, nv40->screen->state[i]); states &= ~(1ULL << i); } @@ -87,17 +88,17 @@ nv40_state_emit(struct nv40_context *nv40) state->dirty = 0; - so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_FB]); + so_emit_reloc_markers(chan, state->hw[NV40_STATE_FB]); for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) { if (!(samplers & (1 << i))) continue; - so_emit_reloc_markers(nv40->nvws, + so_emit_reloc_markers(chan, state->hw[NV40_STATE_FRAGTEX0+i]); samplers &= ~(1ULL << i); } - so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_FRAGPROG]); + so_emit_reloc_markers(chan, state->hw[NV40_STATE_FRAGPROG]); if (state->hw[NV40_STATE_VTXBUF] && nv40->render_mode == HW) - so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_VTXBUF]); + so_emit_reloc_markers(chan, state->hw[NV40_STATE_VTXBUF]); } boolean diff --git a/src/gallium/drivers/nv40/nv40_state_fb.c b/src/gallium/drivers/nv40/nv40_state_fb.c index be618a306bf..c2f739157ad 100644 --- a/src/gallium/drivers/nv40/nv40_state_fb.c +++ b/src/gallium/drivers/nv40/nv40_state_fb.c @@ -2,15 +2,19 @@ #include "nouveau/nouveau_util.h" static struct pipe_buffer * -nv40_surface_buffer(struct pipe_surface *surface) +nv40_do_surface_buffer(struct pipe_surface *surface) { struct nv40_miptree *mt = (struct nv40_miptree *)surface->texture; return mt->buffer; } +#define nv40_surface_buffer(ps) nouveau_bo(nv40_do_surface_buffer(ps)) + static boolean nv40_state_framebuffer_validate(struct nv40_context *nv40) { + struct nouveau_channel *chan = nv40->screen->base.channel; + struct nouveau_grobj *curie = nv40->screen->curie; struct pipe_framebuffer_state *fb = &nv40->framebuffer; struct nv04_surface *rt[4], *zeta; uint32_t rt_enable, rt_format; @@ -69,6 +73,7 @@ nv40_state_framebuffer_validate(struct nv40_context *nv40) rt_format |= NV40TCL_RT_FORMAT_ZETA_Z16; break; case PIPE_FORMAT_Z24S8_UNORM: + case PIPE_FORMAT_Z24X8_UNORM: case 0: rt_format |= NV40TCL_RT_FORMAT_ZETA_Z24S8; break; @@ -77,76 +82,80 @@ nv40_state_framebuffer_validate(struct nv40_context *nv40) } if (rt_enable & NV40TCL_RT_ENABLE_COLOR0) { - so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR0, 1); - so_reloc (so, nv40_surface_buffer(&rt[0]->base), 0, rt_flags | NOUVEAU_BO_OR, - nv40->nvws->channel->vram->handle, - nv40->nvws->channel->gart->handle); - so_method(so, nv40->screen->curie, NV40TCL_COLOR0_PITCH, 2); + so_method(so, curie, NV40TCL_DMA_COLOR0, 1); + so_reloc (so, nv40_surface_buffer(&rt[0]->base), 0, + rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, curie, NV40TCL_COLOR0_PITCH, 2); so_data (so, rt[0]->pitch); - so_reloc (so, nv40_surface_buffer(&rt[0]->base), rt[0]->base.offset, rt_flags | - NOUVEAU_BO_LOW, 0, 0); + so_reloc (so, nv40_surface_buffer(&rt[0]->base), + rt[0]->base.offset, rt_flags | NOUVEAU_BO_LOW, + 0, 0); } if (rt_enable & NV40TCL_RT_ENABLE_COLOR1) { - so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR1, 1); - so_reloc (so, nv40_surface_buffer(&rt[1]->base), 0, rt_flags | NOUVEAU_BO_OR, - nv40->nvws->channel->vram->handle, - nv40->nvws->channel->gart->handle); - so_method(so, nv40->screen->curie, NV40TCL_COLOR1_OFFSET, 2); - so_reloc (so, nv40_surface_buffer(&rt[1]->base), rt[1]->base.offset, rt_flags | - NOUVEAU_BO_LOW, 0, 0); + so_method(so, curie, NV40TCL_DMA_COLOR1, 1); + so_reloc (so, nv40_surface_buffer(&rt[1]->base), 0, + rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, curie, NV40TCL_COLOR1_OFFSET, 2); + so_reloc (so, nv40_surface_buffer(&rt[1]->base), + rt[1]->base.offset, rt_flags | NOUVEAU_BO_LOW, + 0, 0); so_data (so, rt[1]->pitch); } if (rt_enable & NV40TCL_RT_ENABLE_COLOR2) { - so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR2, 1); - so_reloc (so, nv40_surface_buffer(&rt[2]->base), 0, rt_flags | NOUVEAU_BO_OR, - nv40->nvws->channel->vram->handle, - nv40->nvws->channel->gart->handle); - so_method(so, nv40->screen->curie, NV40TCL_COLOR2_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(&rt[2]->base), rt[2]->base.offset, rt_flags | - NOUVEAU_BO_LOW, 0, 0); - so_method(so, nv40->screen->curie, NV40TCL_COLOR2_PITCH, 1); + so_method(so, curie, NV40TCL_DMA_COLOR2, 1); + so_reloc (so, nv40_surface_buffer(&rt[2]->base), 0, + rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, curie, NV40TCL_COLOR2_OFFSET, 1); + so_reloc (so, nv40_surface_buffer(&rt[2]->base), + rt[2]->base.offset, rt_flags | NOUVEAU_BO_LOW, + 0, 0); + so_method(so, curie, NV40TCL_COLOR2_PITCH, 1); so_data (so, rt[2]->pitch); } if (rt_enable & NV40TCL_RT_ENABLE_COLOR3) { - so_method(so, nv40->screen->curie, NV40TCL_DMA_COLOR3, 1); - so_reloc (so, nv40_surface_buffer(&rt[3]->base), 0, rt_flags | NOUVEAU_BO_OR, - nv40->nvws->channel->vram->handle, - nv40->nvws->channel->gart->handle); - so_method(so, nv40->screen->curie, NV40TCL_COLOR3_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(&rt[3]->base), rt[3]->base.offset, rt_flags | - NOUVEAU_BO_LOW, 0, 0); - so_method(so, nv40->screen->curie, NV40TCL_COLOR3_PITCH, 1); + so_method(so, curie, NV40TCL_DMA_COLOR3, 1); + so_reloc (so, nv40_surface_buffer(&rt[3]->base), 0, + rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, curie, NV40TCL_COLOR3_OFFSET, 1); + so_reloc (so, nv40_surface_buffer(&rt[3]->base), + rt[3]->base.offset, rt_flags | NOUVEAU_BO_LOW, + 0, 0); + so_method(so, curie, NV40TCL_COLOR3_PITCH, 1); so_data (so, rt[3]->pitch); } if (zeta_format) { - so_method(so, nv40->screen->curie, NV40TCL_DMA_ZETA, 1); - so_reloc (so, nv40_surface_buffer(&zeta->base), 0, rt_flags | NOUVEAU_BO_OR, - nv40->nvws->channel->vram->handle, - nv40->nvws->channel->gart->handle); - so_method(so, nv40->screen->curie, NV40TCL_ZETA_OFFSET, 1); - so_reloc (so, nv40_surface_buffer(&zeta->base), zeta->base.offset, rt_flags | - NOUVEAU_BO_LOW, 0, 0); - so_method(so, nv40->screen->curie, NV40TCL_ZETA_PITCH, 1); + so_method(so, curie, NV40TCL_DMA_ZETA, 1); + so_reloc (so, nv40_surface_buffer(&zeta->base), 0, + rt_flags | NOUVEAU_BO_OR, + chan->vram->handle, chan->gart->handle); + so_method(so, curie, NV40TCL_ZETA_OFFSET, 1); + so_reloc (so, nv40_surface_buffer(&zeta->base), + zeta->base.offset, rt_flags | NOUVEAU_BO_LOW, 0, 0); + so_method(so, curie, NV40TCL_ZETA_PITCH, 1); so_data (so, zeta->pitch); } - so_method(so, nv40->screen->curie, NV40TCL_RT_ENABLE, 1); + so_method(so, curie, NV40TCL_RT_ENABLE, 1); so_data (so, rt_enable); - so_method(so, nv40->screen->curie, NV40TCL_RT_HORIZ, 3); + so_method(so, curie, NV40TCL_RT_HORIZ, 3); so_data (so, (w << 16) | 0); so_data (so, (h << 16) | 0); so_data (so, rt_format); - so_method(so, nv40->screen->curie, NV40TCL_VIEWPORT_HORIZ, 2); + so_method(so, curie, NV40TCL_VIEWPORT_HORIZ, 2); so_data (so, (w << 16) | 0); so_data (so, (h << 16) | 0); - so_method(so, nv40->screen->curie, NV40TCL_VIEWPORT_CLIP_HORIZ(0), 2); + so_method(so, curie, NV40TCL_VIEWPORT_CLIP_HORIZ(0), 2); so_data (so, ((w - 1) << 16) | 0); so_data (so, ((h - 1) << 16) | 0); - so_method(so, nv40->screen->curie, 0x1d88, 1); + so_method(so, curie, 0x1d88, 1); so_data (so, (1 << 12) | h); so_ref(so, &nv40->state.hw[NV40_STATE_FB]); diff --git a/src/gallium/drivers/nv40/nv40_surface.c b/src/gallium/drivers/nv40/nv40_surface.c index 1a849da32d7..a596547974a 100644 --- a/src/gallium/drivers/nv40/nv40_surface.c +++ b/src/gallium/drivers/nv40/nv40_surface.c @@ -26,12 +26,13 @@ * **************************************************************************/ -#include "nv40_context.h" #include "pipe/p_defines.h" -#include "pipe/internal/p_winsys_screen.h" #include "pipe/p_inlines.h" + #include "util/u_tile.h" +#include "nv40_context.h" + static void nv40_surface_copy(struct pipe_context *pipe, struct pipe_surface *dest, unsigned destx, unsigned desty, diff --git a/src/gallium/drivers/nv40/nv40_transfer.c b/src/gallium/drivers/nv40/nv40_transfer.c index ce45055fe82..6d92ac3db9c 100644 --- a/src/gallium/drivers/nv40/nv40_transfer.c +++ b/src/gallium/drivers/nv40/nv40_transfer.c @@ -136,7 +136,7 @@ nv40_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, } static void -nv40_transfer_del(struct pipe_screen *pscreen, struct pipe_transfer *ptx) +nv40_transfer_del(struct pipe_transfer *ptx) { struct nv40_transfer *tx = (struct nv40_transfer *)ptx; diff --git a/src/gallium/drivers/nv40/nv40_vbo.c b/src/gallium/drivers/nv40/nv40_vbo.c index f3518b2e4fe..b2753b8e2e0 100644 --- a/src/gallium/drivers/nv40/nv40_vbo.c +++ b/src/gallium/drivers/nv40/nv40_vbo.c @@ -1,5 +1,6 @@ #include "pipe/p_context.h" #include "pipe/p_state.h" +#include "pipe/p_inlines.h" #include "nv40_context.h" #include "nv40_state.h" @@ -70,7 +71,7 @@ static boolean nv40_vbo_set_idxbuf(struct nv40_context *nv40, struct pipe_buffer *ib, unsigned ib_size) { - struct pipe_screen *pscreen = &nv40->screen->pipe; + struct pipe_screen *pscreen = &nv40->screen->base.base; unsigned type; if (!ib) { @@ -108,7 +109,7 @@ nv40_vbo_static_attrib(struct nv40_context *nv40, struct nouveau_stateobj *so, int attrib, struct pipe_vertex_element *ve, struct pipe_vertex_buffer *vb) { - struct pipe_winsys *ws = nv40->pipe.winsys; + struct pipe_screen *pscreen = nv40->pipe.screen; struct nouveau_grobj *curie = nv40->screen->curie; unsigned type, ncomp; void *map; @@ -116,7 +117,7 @@ nv40_vbo_static_attrib(struct nv40_context *nv40, struct nouveau_stateobj *so, if (nv40_vbo_format_to_hw(ve->src_format, &type, &ncomp)) return FALSE; - map = ws->buffer_map(ws, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); + map = pipe_buffer_map(pscreen, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); map += vb->buffer_offset + ve->src_offset; switch (type) { @@ -148,17 +149,17 @@ nv40_vbo_static_attrib(struct nv40_context *nv40, struct nouveau_stateobj *so, so_data (so, fui(v[0])); break; default: - ws->buffer_unmap(ws, vb->buffer); + pipe_buffer_unmap(pscreen, vb->buffer); return FALSE; } } break; default: - ws->buffer_unmap(ws, vb->buffer); + pipe_buffer_unmap(pscreen, vb->buffer); return FALSE; } - ws->buffer_unmap(ws, vb->buffer); + pipe_buffer_unmap(pscreen, vb->buffer); return TRUE; } @@ -168,7 +169,7 @@ nv40_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { struct nv40_context *nv40 = nv40_context(pipe); - struct nouveau_channel *chan = nv40->nvws->channel; + struct nouveau_channel *chan = nv40->screen->base.channel; unsigned restart; nv40_vbo_set_idxbuf(nv40, NULL, 0); @@ -227,7 +228,7 @@ static INLINE void nv40_draw_elements_u08(struct nv40_context *nv40, void *ib, unsigned mode, unsigned start, unsigned count) { - struct nouveau_channel *chan = nv40->nvws->channel; + struct nouveau_channel *chan = nv40->screen->base.channel; while (count) { uint8_t *elts = (uint8_t *)ib + start; @@ -276,7 +277,7 @@ static INLINE void nv40_draw_elements_u16(struct nv40_context *nv40, void *ib, unsigned mode, unsigned start, unsigned count) { - struct nouveau_channel *chan = nv40->nvws->channel; + struct nouveau_channel *chan = nv40->screen->base.channel; while (count) { uint16_t *elts = (uint16_t *)ib + start; @@ -325,7 +326,7 @@ static INLINE void nv40_draw_elements_u32(struct nv40_context *nv40, void *ib, unsigned mode, unsigned start, unsigned count) { - struct nouveau_channel *chan = nv40->nvws->channel; + struct nouveau_channel *chan = nv40->screen->base.channel; while (count) { uint32_t *elts = (uint32_t *)ib + start; @@ -367,10 +368,10 @@ nv40_draw_elements_inline(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { struct nv40_context *nv40 = nv40_context(pipe); - struct pipe_winsys *ws = pipe->winsys; + struct pipe_screen *pscreen = pipe->screen; void *map; - map = ws->buffer_map(ws, ib, PIPE_BUFFER_USAGE_CPU_READ); + map = pipe_buffer_map(pscreen, ib, PIPE_BUFFER_USAGE_CPU_READ); if (!ib) { NOUVEAU_ERR("failed mapping ib\n"); return FALSE; @@ -391,7 +392,7 @@ nv40_draw_elements_inline(struct pipe_context *pipe, break; } - ws->buffer_unmap(ws, ib); + pipe_buffer_unmap(pscreen, ib); return TRUE; } @@ -400,7 +401,7 @@ nv40_draw_elements_vbo(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { struct nv40_context *nv40 = nv40_context(pipe); - struct nouveau_channel *chan = nv40->nvws->channel; + struct nouveau_channel *chan = nv40->screen->base.channel; unsigned restart; while (count) { @@ -519,17 +520,20 @@ nv40_vbo_validate(struct nv40_context *nv40) return FALSE; } - so_reloc(vtxbuf, vb->buffer, vb->buffer_offset + ve->src_offset, - vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, - 0, NV40TCL_VTXBUF_ADDRESS_DMA1); + so_reloc(vtxbuf, nouveau_bo(vb->buffer), + vb->buffer_offset + ve->src_offset, + vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR, + 0, NV40TCL_VTXBUF_ADDRESS_DMA1); so_data (vtxfmt, ((vb->stride << NV40TCL_VTXFMT_STRIDE_SHIFT) | (ncomp << NV40TCL_VTXFMT_SIZE_SHIFT) | type)); } if (ib) { + struct nouveau_bo *bo = nouveau_bo(ib); + so_method(vtxbuf, curie, NV40TCL_IDXBUF_ADDRESS, 2); - so_reloc (vtxbuf, ib, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0); - so_reloc (vtxbuf, ib, ib_format, vb_flags | NOUVEAU_BO_OR, + so_reloc (vtxbuf, bo, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0); + so_reloc (vtxbuf, bo, ib_format, vb_flags | NOUVEAU_BO_OR, 0, NV40TCL_IDXBUF_FORMAT_DMA1); } diff --git a/src/gallium/drivers/nv40/nv40_vertprog.c b/src/gallium/drivers/nv40/nv40_vertprog.c index 7df9a4d3264..0382dbba8f6 100644 --- a/src/gallium/drivers/nv40/nv40_vertprog.c +++ b/src/gallium/drivers/nv40/nv40_vertprog.c @@ -1,6 +1,7 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" +#include "pipe/p_inlines.h" #include "pipe/p_shader_tokens.h" #include "tgsi/tgsi_parse.h" @@ -787,10 +788,10 @@ nv40_vertprog_translate(struct nv40_context *nv40, assert(imm->Immediate.NrTokens == 4 + 1); vpc->imm[vpc->nr_imm++] = constant(vpc, -1, - imm->u.ImmediateFloat32[0].Float, - imm->u.ImmediateFloat32[1].Float, - imm->u.ImmediateFloat32[2].Float, - imm->u.ImmediateFloat32[3].Float); + imm->u[0].Float, + imm->u[1].Float, + imm->u[2].Float, + imm->u[3].Float); } break; case TGSI_TOKEN_TYPE_INSTRUCTION: @@ -855,8 +856,7 @@ out_err: static boolean nv40_vertprog_validate(struct nv40_context *nv40) { - struct nouveau_winsys *nvws = nv40->nvws; - struct pipe_winsys *ws = nv40->pipe.winsys; + struct pipe_screen *pscreen = nv40->pipe.screen; struct nouveau_grobj *curie = nv40->screen->curie; struct nv40_vertex_program *vp; struct pipe_buffer *constbuf; @@ -895,15 +895,15 @@ check_gpu_resources: struct nouveau_stateobj *so; uint vplen = vp->nr_insns; - if (nvws->res_alloc(heap, vplen, vp, &vp->exec)) { + if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec)) { while (heap->next && heap->size < vplen) { struct nv40_vertex_program *evict; evict = heap->next->priv; - nvws->res_free(&evict->exec); + nouveau_resource_free(&evict->exec); } - if (nvws->res_alloc(heap, vplen, vp, &vp->exec)) + if (nouveau_resource_alloc(heap, vplen, vp, &vp->exec)) assert(0); } @@ -925,15 +925,15 @@ check_gpu_resources: if (vp->nr_consts && !vp->data) { struct nouveau_resource *heap = nv40->screen->vp_data_heap; - if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) { + if (nouveau_resource_alloc(heap, vp->nr_consts, vp, &vp->data)) { while (heap->next && heap->size < vp->nr_consts) { struct nv40_vertex_program *evict; evict = heap->next->priv; - nvws->res_free(&evict->data); + nouveau_resource_free(&evict->data); } - if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) + if (nouveau_resource_alloc(heap, vp->nr_consts, vp, &vp->data)) assert(0); } @@ -981,8 +981,8 @@ check_gpu_resources: float *map = NULL; if (constbuf) { - map = ws->buffer_map(ws, constbuf, - PIPE_BUFFER_USAGE_CPU_READ); + map = pipe_buffer_map(pscreen, constbuf, + PIPE_BUFFER_USAGE_CPU_READ); } for (i = 0; i < vp->nr_consts; i++) { @@ -1003,7 +1003,7 @@ check_gpu_resources: } if (constbuf) - ws->buffer_unmap(ws, constbuf); + pscreen->buffer_unmap(pscreen, constbuf); } /* Upload vtxprog */ @@ -1035,8 +1035,6 @@ check_gpu_resources: void nv40_vertprog_destroy(struct nv40_context *nv40, struct nv40_vertex_program *vp) { - struct nouveau_winsys *nvws = nv40->screen->nvws; - vp->translated = FALSE; if (vp->nr_insns) { @@ -1051,9 +1049,9 @@ nv40_vertprog_destroy(struct nv40_context *nv40, struct nv40_vertex_program *vp) vp->nr_consts = 0; } - nvws->res_free(&vp->exec); + nouveau_resource_free(&vp->exec); vp->exec_start = 0; - nvws->res_free(&vp->data); + nouveau_resource_free(&vp->data); vp->data_start = 0; vp->data_start_min = 0; diff --git a/src/gallium/drivers/nv50/nv50_clear.c b/src/gallium/drivers/nv50/nv50_clear.c index 33427a15a56..e0b2d2880b0 100644 --- a/src/gallium/drivers/nv50/nv50_clear.c +++ b/src/gallium/drivers/nv50/nv50_clear.c @@ -31,7 +31,7 @@ nv50_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba, double depth, unsigned stencil) { struct nv50_context *nv50 = nv50_context(pipe); - struct nouveau_channel *chan = nv50->screen->nvws->channel; + struct nouveau_channel *chan = nv50->screen->base.channel; struct nouveau_grobj *tesla = nv50->screen->tesla; struct pipe_framebuffer_state *fb = &nv50->framebuffer; unsigned mode = 0, i; diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index a511f655c19..e02afc4be99 100644 --- a/src/gallium/drivers/nv50/nv50_context.c +++ b/src/gallium/drivers/nv50/nv50_context.c @@ -33,7 +33,7 @@ nv50_flush(struct pipe_context *pipe, unsigned flags, { struct nv50_context *nv50 = (struct nv50_context *)pipe; - FIRE_RING(nv50->screen->nvws->channel); + FIRE_RING(nv50->screen->base.channel); } static void diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index 7b67a754397..9b8cc4d37d0 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -63,6 +63,11 @@ struct nv50_rasterizer_stateobj { struct nouveau_stateobj *so; }; +struct nv50_sampler_stateobj { + bool normalized; + unsigned tsc[8]; +}; + struct nv50_miptree_level { int *image_offset; unsigned pitch; @@ -70,7 +75,8 @@ struct nv50_miptree_level { struct nv50_miptree { struct pipe_texture base; - struct pipe_buffer *buffer; + + struct nouveau_bo *bo; struct nv50_miptree_level level[PIPE_MAX_TEXTURE_LEVELS]; int image_nr; @@ -93,13 +99,6 @@ nv50_surface(struct pipe_surface *pt) return (struct nv50_surface *)pt; } -static INLINE struct pipe_buffer * -nv50_surface_buffer(struct pipe_surface *surface) -{ - struct nv50_miptree *mt = (struct nv50_miptree *)surface->texture; - return mt->buffer; -} - struct nv50_state { unsigned dirty; @@ -115,6 +114,7 @@ struct nv50_state { unsigned viewport_bypass; struct nouveau_stateobj *tsc_upload; struct nouveau_stateobj *tic_upload; + unsigned miptree_nr; struct nouveau_stateobj *vertprog; struct nouveau_stateobj *fragprog; struct nouveau_stateobj *vtxfmt; @@ -147,7 +147,7 @@ struct nv50_context { unsigned vtxbuf_nr; struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS]; unsigned vtxelt_nr; - unsigned *sampler[PIPE_MAX_SAMPLERS]; + struct nv50_sampler_stateobj *sampler[PIPE_MAX_SAMPLERS]; unsigned sampler_nr; struct nv50_miptree *miptree[PIPE_MAX_SAMPLERS]; unsigned miptree_nr; diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c index f79a7ca86c9..c8392799ed8 100644 --- a/src/gallium/drivers/nv50/nv50_miptree.c +++ b/src/gallium/drivers/nv50/nv50_miptree.c @@ -29,26 +29,41 @@ static struct pipe_texture * nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp) { + struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree); struct pipe_texture *pt = &mt->base; - unsigned usage, width = tmp->width[0], height = tmp->height[0]; + unsigned width = tmp->width[0], height = tmp->height[0]; unsigned depth = tmp->depth[0]; - int i, l; + uint32_t tile_mode, tile_flags, tile_h; + int ret, i, l; mt->base = *tmp; pipe_reference_init(&mt->base.reference, 1); mt->base.screen = pscreen; - usage = PIPE_BUFFER_USAGE_PIXEL; switch (pt->format) { + case PIPE_FORMAT_Z32_FLOAT: + tile_flags = 0x4800; + break; case PIPE_FORMAT_Z24S8_UNORM: - case PIPE_FORMAT_Z16_UNORM: - usage |= NOUVEAU_BUFFER_USAGE_ZETA; + tile_flags = 0x1800; + break; + case PIPE_FORMAT_X8Z24_UNORM: + case PIPE_FORMAT_S8Z24_UNORM: + tile_flags = 0x2800; break; default: + tile_flags = 0x7000; break; } + if (pt->height[0] > 32) tile_mode = 4; + else if (pt->height[0] > 16) tile_mode = 3; + else if (pt->height[0] > 8) tile_mode = 2; + else if (pt->height[0] > 4) tile_mode = 1; + else tile_mode = 0; + tile_h = 1 << (tile_mode + 2); + switch (pt->target) { case PIPE_TEXTURE_3D: mt->image_nr = pt->depth[0]; @@ -85,7 +100,7 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp) size = align(pt->width[l], 8) * pt->block.size; size = align(size, 64); - size *= align(pt->height[l], 8) * pt->block.size; + size *= align(pt->height[l], tile_h) * pt->block.size; lvl->image_offset[i] = mt->total_size; @@ -93,12 +108,13 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp) } } - mt->buffer = pscreen->buffer_create(pscreen, 256, usage, mt->total_size); - if (!mt->buffer) { + ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 256, mt->total_size, + tile_mode, tile_flags, &mt->bo); + if (ret) { FREE(mt); return NULL; } - + return &mt->base; } @@ -106,6 +122,7 @@ static struct pipe_texture * nv50_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt, const unsigned *stride, struct pipe_buffer *pb) { + struct nouveau_bo *bo = nouveau_bo(pb); struct nv50_miptree *mt; /* Only supports 2D, non-mipmapped textures for the moment */ @@ -124,7 +141,7 @@ nv50_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt, mt->level[0].pitch = *stride; mt->level[0].image_offset = CALLOC(1, sizeof(unsigned)); - pipe_buffer_reference(&mt->buffer, pb); + nouveau_bo_ref(bo, &mt->bo); return &mt->base; } @@ -133,7 +150,7 @@ nv50_miptree_destroy(struct pipe_texture *pt) { struct nv50_miptree *mt = nv50_miptree(pt); - pipe_buffer_reference(&mt->buffer, NULL); + nouveau_bo_ref(NULL, &mt->bo); FREE(mt); } diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c index 2d15868ae84..4ec9c03305f 100644 --- a/src/gallium/drivers/nv50/nv50_program.c +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -85,6 +85,9 @@ struct nv50_reg { int hw; int neg; + + int rhw; /* result hw for FP outputs, or interpolant index */ + int acc; /* instruction where this reg is last read (first insn == 1) */ }; struct nv50_pc { @@ -108,12 +111,23 @@ struct nv50_pc { struct nv50_reg *temp_temp[16]; unsigned temp_temp_nr; + + unsigned interp_mode[32]; + /* perspective interpolation registers */ + struct nv50_reg *iv_p; + struct nv50_reg *iv_c; + + /* current instruction and total number of insns */ + unsigned insn_cur; + unsigned insn_nr; + + boolean allow32; }; static void alloc_reg(struct nv50_pc *pc, struct nv50_reg *reg) { - int i; + int i = 0; if (reg->type == P_RESULT) { if (pc->p->cfg.high_result < (reg->hw + 1)) @@ -131,7 +145,22 @@ alloc_reg(struct nv50_pc *pc, struct nv50_reg *reg) return; } - for (i = 0; i < NV50_SU_MAX_TEMP; i++) { + if (reg->rhw != -1) { + /* try to allocate temporary with index rhw first */ + if (!(pc->r_temp[reg->rhw])) { + pc->r_temp[reg->rhw] = reg; + reg->hw = reg->rhw; + if (pc->p->cfg.high_temp < (reg->rhw + 1)) + pc->p->cfg.high_temp = reg->rhw + 1; + return; + } + /* make sure we don't get things like $r0 needs to go + * in $r1 and $r1 in $r0 + */ + i = pc->result_nr * 4; + } + + for (; i < NV50_SU_MAX_TEMP; i++) { if (!(pc->r_temp[i])) { pc->r_temp[i] = reg; reg->hw = i; @@ -159,6 +188,7 @@ alloc_temp(struct nv50_pc *pc, struct nv50_reg *dst) r->type = P_TEMP; r->index = -1; r->hw = i; + r->rhw = -1; pc->r_temp[i] = r; return r; } @@ -168,6 +198,38 @@ alloc_temp(struct nv50_pc *pc, struct nv50_reg *dst) return NULL; } +/* Assign the hw of the discarded temporary register src + * to the tgsi register dst and free src. + */ +static void +assimilate_temp(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src) +{ + assert(src->index == -1 && src->hw != -1); + + if (dst->hw != -1) + pc->r_temp[dst->hw] = NULL; + pc->r_temp[src->hw] = dst; + dst->hw = src->hw; + + FREE(src); +} + +/* release the hardware resource held by r */ +static void +release_hw(struct nv50_pc *pc, struct nv50_reg *r) +{ + assert(r->type == P_TEMP); + if (r->hw == -1) + return; + + assert(pc->r_temp[r->hw] == r); + pc->r_temp[r->hw] = NULL; + + r->acc = 0; + if (r->index == -1) + FREE(r); +} + static void free_temp(struct nv50_pc *pc, struct nv50_reg *r) { @@ -250,7 +312,13 @@ alloc_immd(struct nv50_pc *pc, float f) struct nv50_reg *r = CALLOC_STRUCT(nv50_reg); unsigned hw; - hw = ctor_immd(pc, f, 0, 0, 0) * 4; + for (hw = 0; hw < pc->immd_nr * 4; hw++) + if (pc->immd_buf[hw] == f) + break; + + if (hw == pc->immd_nr * 4) + hw = ctor_immd(pc, f, -f, 0.5 * f, 0) * 4; + r->type = P_IMMD; r->hw = hw; r->index = -1; @@ -341,7 +409,8 @@ set_dst(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_program_exec *e) static INLINE void set_immd(struct nv50_pc *pc, struct nv50_reg *imm, struct nv50_program_exec *e) { - unsigned val = fui(pc->immd_buf[imm->hw]); /* XXX */ + float f = pc->immd_buf[imm->hw]; + unsigned val = fui(imm->neg ? -f : f); set_long(pc, e); /*XXX: can't be predicated - bits overlap.. catch cases where both @@ -354,20 +423,35 @@ set_immd(struct nv50_pc *pc, struct nv50_reg *imm, struct nv50_program_exec *e) e->inst[1] |= (val >> 6) << 2; } + +#define INTERP_LINEAR 0 +#define INTERP_FLAT 1 +#define INTERP_PERSPECTIVE 2 +#define INTERP_CENTROID 4 + +/* interpolant index has been stored in dst->rhw */ static void -emit_interp(struct nv50_pc *pc, struct nv50_reg *dst, - struct nv50_reg *src, struct nv50_reg *iv) +emit_interp(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *iv, + unsigned mode) { + assert(dst->rhw != -1); struct nv50_program_exec *e = exec(pc); e->inst[0] |= 0x80000000; set_dst(pc, dst, e); - alloc_reg(pc, src); - e->inst[0] |= (src->hw << 16); - if (iv) { - e->inst[0] |= (1 << 25); - alloc_reg(pc, iv); - e->inst[0] |= (iv->hw << 9); + e->inst[0] |= (dst->rhw << 16); + + if (mode & INTERP_FLAT) { + e->inst[0] |= (1 << 8); + } else { + if (mode & INTERP_PERSPECTIVE) { + e->inst[0] |= (1 << 25); + alloc_reg(pc, iv); + e->inst[0] |= (iv->hw << 9); + } + + if (mode & INTERP_CENTROID) + e->inst[0] |= (1 << 24); } emit(pc, e); @@ -378,22 +462,12 @@ set_data(struct nv50_pc *pc, struct nv50_reg *src, unsigned m, unsigned s, struct nv50_program_exec *e) { set_long(pc, e); -#if 1 - e->inst[1] |= (1 << 22); -#else - if (src->type == P_IMMD) { - e->inst[1] |= (NV50_CB_PMISC << 22); - } else { - if (pc->p->type == PIPE_SHADER_VERTEX) - e->inst[1] |= (NV50_CB_PVP << 22); - else - e->inst[1] |= (NV50_CB_PFP << 22); - } -#endif e->param.index = src->hw; e->param.shift = s; e->param.mask = m << (s % 32); + + e->inst[1] |= (((src->type == P_IMMD) ? 0 : 1) << 22); } static void @@ -405,12 +479,11 @@ emit_mov(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src) set_dst(pc, dst, e); - if (0 && dst->type != P_RESULT && src->type == P_IMMD) { + if (pc->allow32 && dst->type != P_RESULT && src->type == P_IMMD) { set_immd(pc, src, e); /*XXX: 32-bit, but steals part of "half" reg space - need to * catch and handle this case if/when we do half-regs */ - e->inst[0] |= 0x00008000; } else if (src->type == P_IMMD || src->type == P_CONST) { set_long(pc, e); @@ -426,18 +499,25 @@ emit_mov(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src) e->inst[0] |= (src->hw << 9); } - /* We really should support "half" instructions here at some point, - * but I don't feel confident enough about them yet. - */ - set_long(pc, e); if (is_long(e) && !is_immd(e)) { e->inst[1] |= 0x04000000; /* 32-bit */ - e->inst[1] |= 0x0003c000; /* "subsubop" 0xf == mov */ - } + e->inst[1] |= 0x0000c000; /* "subsubop" 0x3 */ + if (!(e->inst[1] & 0x20000000)) + e->inst[1] |= 0x00030000; /* "subsubop" 0xf */ + } else + e->inst[0] |= 0x00008000; emit(pc, e); } +static INLINE void +emit_mov_immdval(struct nv50_pc *pc, struct nv50_reg *dst, float f) +{ + struct nv50_reg *imm = alloc_immd(pc, f); + emit_mov(pc, dst, imm); + FREE(imm); +} + static boolean check_swap_src_0_1(struct nv50_pc *pc, struct nv50_reg **s0, struct nv50_reg **s1) @@ -541,12 +621,26 @@ emit_mul(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0, struct nv50_program_exec *e = exec(pc); e->inst[0] |= 0xc0000000; - set_long(pc, e); + + if (!pc->allow32) + set_long(pc, e); check_swap_src_0_1(pc, &src0, &src1); set_dst(pc, dst, e); set_src_0(pc, src0, e); - set_src_1(pc, src1, e); + if (src1->type == P_IMMD && !is_long(e)) { + if (src0->neg) + e->inst[0] |= 0x00008000; + set_immd(pc, src1, e); + } else { + set_src_1(pc, src1, e); + if (src0->neg ^ src1->neg) { + if (is_long(e)) + e->inst[1] |= 0x08000000; + else + e->inst[0] |= 0x00008000; + } + } emit(pc, e); } @@ -560,11 +654,20 @@ emit_add(struct nv50_pc *pc, struct nv50_reg *dst, e->inst[0] |= 0xb0000000; check_swap_src_0_1(pc, &src0, &src1); + + if (!pc->allow32 || src0->neg || src1->neg) { + set_long(pc, e); + e->inst[1] |= (src0->neg << 26) | (src1->neg << 27); + } + set_dst(pc, dst, e); set_src_0(pc, src0, e); - if (is_long(e)) + if (src1->type == P_CONST || src1->type == P_ATTR || is_long(e)) set_src_2(pc, src1, e); else + if (src1->type == P_IMMD) + set_immd(pc, src1, e); + else set_src_1(pc, src1, e); emit(pc, e); @@ -588,25 +691,13 @@ emit_minmax(struct nv50_pc *pc, unsigned sub, struct nv50_reg *dst, emit(pc, e); } -static void +static INLINE void emit_sub(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0, struct nv50_reg *src1) { - struct nv50_program_exec *e = exec(pc); - - e->inst[0] |= 0xb0000000; - - set_long(pc, e); - if (check_swap_src_0_1(pc, &src0, &src1)) - e->inst[1] |= 0x04000000; - else - e->inst[1] |= 0x08000000; - - set_dst(pc, dst, e); - set_src_0(pc, src0, e); - set_src_2(pc, src1, e); - - emit(pc, e); + src1->neg ^= 1; + emit_add(pc, dst, src0, src1); + src1->neg ^= 1; } static void @@ -623,26 +714,21 @@ emit_mad(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0, set_src_1(pc, src1, e); set_src_2(pc, src2, e); + if (src0->neg ^ src1->neg) + e->inst[1] |= 0x04000000; + if (src2->neg) + e->inst[1] |= 0x08000000; + emit(pc, e); } -static void +static INLINE void emit_msb(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src0, struct nv50_reg *src1, struct nv50_reg *src2) { - struct nv50_program_exec *e = exec(pc); - - e->inst[0] |= 0xe0000000; - set_long(pc, e); - e->inst[1] |= 0x08000000; /* src0 * src1 - src2 */ - - check_swap_src_0_1(pc, &src0, &src1); - set_dst(pc, dst, e); - set_src_0(pc, src0, e); - set_src_1(pc, src1, e); - set_src_2(pc, src2, e); - - emit(pc, e); + src2->neg ^= 1; + emit_mad(pc, dst, src0, src1, src2); + src2->neg ^= 1; } static void @@ -693,6 +779,48 @@ emit_precossin(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src) emit(pc, e); } +#define CVTOP_RN 0x01 +#define CVTOP_FLOOR 0x03 +#define CVTOP_CEIL 0x05 +#define CVTOP_TRUNC 0x07 +#define CVTOP_SAT 0x08 +#define CVTOP_ABS 0x10 + +#define CVT_F32_F32 0xc4 +#define CVT_F32_S32 0x44 +#define CVT_F32_U32 0x64 +#define CVT_S32_F32 0x8c +#define CVT_S32_S32 0x0c +#define CVT_F32_F32_ROP 0xcc + +static void +emit_cvt(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src, + int wp, unsigned cop, unsigned fmt) +{ + struct nv50_program_exec *e; + + e = exec(pc); + set_long(pc, e); + + e->inst[0] |= 0xa0000000; + e->inst[1] |= 0x00004000; + e->inst[1] |= (cop << 16); + e->inst[1] |= (fmt << 24); + set_src_0(pc, src, e); + + if (wp >= 0) + set_pred_wr(pc, 1, wp, e); + + if (dst) + set_dst(pc, dst, e); + else { + e->inst[0] |= 0x000001fc; + e->inst[1] |= 0x00000008; + } + + emit(pc, e); +} + static void emit_set(struct nv50_pc *pc, unsigned c_op, struct nv50_reg *dst, struct nv50_reg *src0, struct nv50_reg *src1) @@ -736,22 +864,10 @@ emit_set(struct nv50_pc *pc, unsigned c_op, struct nv50_reg *dst, free_temp(pc, dst); } -static void +static INLINE void emit_flr(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src) { - struct nv50_program_exec *e = exec(pc); - - e->inst[0] = 0xa0000000; /* cvt */ - set_long(pc, e); - e->inst[1] |= (6 << 29); /* cvt */ - e->inst[1] |= 0x08000000; /* integer mode */ - e->inst[1] |= 0x04000000; /* 32 bit */ - e->inst[1] |= ((0x1 << 3)) << 14; /* .rn */ - e->inst[1] |= (1 << 14); /* src .f32 */ - set_dst(pc, dst, e); - set_src_0(pc, src, e); - - emit(pc, e); + emit_cvt(pc, dst, src, -1, CVTOP_FLOOR, CVT_F32_F32_ROP); } static void @@ -768,21 +884,10 @@ emit_pow(struct nv50_pc *pc, struct nv50_reg *dst, free_temp(pc, temp); } -static void +static INLINE void emit_abs(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src) { - struct nv50_program_exec *e = exec(pc); - - e->inst[0] = 0xa0000000; /* cvt */ - set_long(pc, e); - e->inst[1] |= (6 << 29); /* cvt */ - e->inst[1] |= 0x04000000; /* 32 bit */ - e->inst[1] |= (1 << 14); /* src .f32 */ - e->inst[1] |= ((1 << 6) << 14); /* .abs */ - set_dst(pc, dst, e); - set_src_0(pc, src, e); - - emit(pc, e); + emit_cvt(pc, dst, src, -1, CVTOP_ABS, CVT_F32_F32); } static void @@ -794,18 +899,12 @@ emit_lit(struct nv50_pc *pc, struct nv50_reg **dst, unsigned mask, struct nv50_reg *neg128 = alloc_immd(pc, -127.999999); struct nv50_reg *pos128 = alloc_immd(pc, 127.999999); struct nv50_reg *tmp[4]; + boolean allow32 = pc->allow32; - if (mask & (1 << 0)) - emit_mov(pc, dst[0], one); - - if (mask & (1 << 3)) - emit_mov(pc, dst[3], one); + pc->allow32 = FALSE; if (mask & (3 << 1)) { - if (mask & (1 << 1)) - tmp[0] = dst[1]; - else - tmp[0] = temp_temp(pc); + tmp[0] = alloc_temp(pc, NULL); emit_minmax(pc, 4, tmp[0], src[0], zero); } @@ -823,6 +922,26 @@ emit_lit(struct nv50_pc *pc, struct nv50_reg **dst, unsigned mask, emit_mov(pc, dst[2], zero); set_pred(pc, 3, 0, pc->p->exec_tail); } + + if (mask & (1 << 1)) + assimilate_temp(pc, dst[1], tmp[0]); + else + if (mask & (1 << 2)) + free_temp(pc, tmp[0]); + + pc->allow32 = allow32; + + /* do this last, in case src[i,j] == dst[0,3] */ + if (mask & (1 << 0)) + emit_mov(pc, dst[0], one); + + if (mask & (1 << 3)) + emit_mov(pc, dst[3], one); + + FREE(pos128); + FREE(neg128); + FREE(zero); + FREE(one); } static void @@ -853,6 +972,8 @@ emit_kil(struct nv50_pc *pc, struct nv50_reg *src) e->inst[1] = 0xc4014788; set_src_0(pc, src, e); set_pred_wr(pc, 1, r_pred, e); + if (src->neg) + e->inst[1] |= 0x20000000; emit(pc, e); /* This is probably KILP */ @@ -863,6 +984,180 @@ emit_kil(struct nv50_pc *pc, struct nv50_reg *src) emit(pc, e); } +static void +emit_tex(struct nv50_pc *pc, struct nv50_reg **dst, unsigned mask, + struct nv50_reg **src, unsigned unit, unsigned type, boolean proj) +{ + struct nv50_reg *temp, *t[4]; + struct nv50_program_exec *e; + + unsigned c, mode, dim; + + switch (type) { + case TGSI_TEXTURE_1D: + dim = 1; + break; + case TGSI_TEXTURE_UNKNOWN: + case TGSI_TEXTURE_2D: + case TGSI_TEXTURE_SHADOW1D: /* XXX: x, z */ + case TGSI_TEXTURE_RECT: + dim = 2; + break; + case TGSI_TEXTURE_3D: + case TGSI_TEXTURE_CUBE: + case TGSI_TEXTURE_SHADOW2D: + case TGSI_TEXTURE_SHADOWRECT: /* XXX */ + dim = 3; + break; + default: + assert(0); + break; + } + + alloc_temp4(pc, t, 0); + + if (proj) { + if (src[0]->type == P_TEMP && src[0]->rhw != -1) { + mode = pc->interp_mode[src[0]->index]; + + t[3]->rhw = src[3]->rhw; + emit_interp(pc, t[3], NULL, (mode & INTERP_CENTROID)); + emit_flop(pc, 0, t[3], t[3]); + + for (c = 0; c < dim; c++) { + t[c]->rhw = src[c]->rhw; + emit_interp(pc, t[c], t[3], + (mode | INTERP_PERSPECTIVE)); + } + } else { + emit_flop(pc, 0, t[3], src[3]); + for (c = 0; c < dim; c++) + emit_mul(pc, t[c], src[c], t[3]); + + /* XXX: for some reason the blob sometimes uses MAD: + * emit_mad(pc, t[c], src[0][c], t[3], t[3]) + * pc->p->exec_tail->inst[1] |= 0x080fc000; + */ + } + } else { + if (type == TGSI_TEXTURE_CUBE) { + temp = temp_temp(pc); + emit_minmax(pc, 4, temp, src[0], src[1]); + emit_minmax(pc, 4, temp, temp, src[2]); + emit_flop(pc, 0, temp, temp); + for (c = 0; c < 3; c++) + emit_mul(pc, t[c], src[c], temp); + } else { + for (c = 0; c < dim; c++) + emit_mov(pc, t[c], src[c]); + } + } + + e = exec(pc); + set_long(pc, e); + e->inst[0] |= 0xf0000000; + e->inst[1] |= 0x00000004; + set_dst(pc, t[0], e); + e->inst[0] |= (unit << 9); + + if (dim == 2) + e->inst[0] |= 0x00400000; + else + if (dim == 3) + e->inst[0] |= 0x00800000; + + e->inst[0] |= (mask & 0x3) << 25; + e->inst[1] |= (mask & 0xc) << 12; + + emit(pc, e); + +#if 1 + if (mask & 1) emit_mov(pc, dst[0], t[0]); + if (mask & 2) emit_mov(pc, dst[1], t[1]); + if (mask & 4) emit_mov(pc, dst[2], t[2]); + if (mask & 8) emit_mov(pc, dst[3], t[3]); + + free_temp4(pc, t); +#else + /* XXX: if p.e. MUL is used directly after TEX, it would still use + * the texture coordinates, not the fetched values: latency ? */ + + for (c = 0; c < 4; c++) { + if (mask & (1 << c)) + assimilate_temp(pc, dst[c], t[c]); + else + free_temp(pc, t[c]); + } +#endif +} + +static void +convert_to_long(struct nv50_pc *pc, struct nv50_program_exec *e) +{ + unsigned q = 0, m = ~0; + + assert(!is_long(e)); + + switch (e->inst[0] >> 28) { + case 0x1: + /* MOV */ + q = 0x0403c000; + m = 0xffff7fff; + break; + case 0x8: + /* INTERP */ + m = ~0x02000000; + if (e->inst[0] & 0x02000000) + q = 0x00020000; + break; + case 0x9: + /* RCP */ + break; + case 0xB: + /* ADD */ + m = ~(127 << 16); + q = ((e->inst[0] & (~m)) >> 2); + break; + case 0xC: + /* MUL */ + m = ~0x00008000; + q = ((e->inst[0] & (~m)) << 12); + break; + case 0xE: + /* MAD (if src2 == dst) */ + q = ((e->inst[0] & 0x1fc) << 12); + break; + default: + assert(0); + break; + } + + set_long(pc, e); + pc->p->exec_size++; + + e->inst[0] &= m; + e->inst[1] |= q; +} + +static boolean +negate_supported(const struct tgsi_full_instruction *insn, int i) +{ + switch (insn->Instruction.Opcode) { + case TGSI_OPCODE_DP3: + case TGSI_OPCODE_DP4: + case TGSI_OPCODE_MUL: + case TGSI_OPCODE_KIL: + case TGSI_OPCODE_ADD: + case TGSI_OPCODE_SUB: + case TGSI_OPCODE_MAD: + return TRUE; + case TGSI_OPCODE_POW: + return (i == 1) ? TRUE : FALSE; + default: + return FALSE; + } +} + static struct nv50_reg * tgsi_dst(struct nv50_pc *pc, int c, const struct tgsi_full_dst_register *dst) { @@ -881,11 +1176,14 @@ tgsi_dst(struct nv50_pc *pc, int c, const struct tgsi_full_dst_register *dst) } static struct nv50_reg * -tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src) +tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src, + boolean neg) { struct nv50_reg *r = NULL; struct nv50_reg *temp; - unsigned c; + unsigned sgn, c; + + sgn = tgsi_util_get_full_src_register_sign_mode(src, chan); c = tgsi_util_get_full_src_register_extswizzle(src, chan); switch (c) { @@ -915,16 +1213,17 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src) break; case TGSI_EXTSWIZZLE_ZERO: r = alloc_immd(pc, 0.0); - break; + return r; case TGSI_EXTSWIZZLE_ONE: - r = alloc_immd(pc, 1.0); - break; + if (sgn == TGSI_UTIL_SIGN_TOGGLE || sgn == TGSI_UTIL_SIGN_SET) + return alloc_immd(pc, -1.0); + return alloc_immd(pc, 1.0); default: assert(0); break; } - switch (tgsi_util_get_full_src_register_sign_mode(src, chan)) { + switch (sgn) { case TGSI_UTIL_SIGN_KEEP: break; case TGSI_UTIL_SIGN_CLEAR: @@ -933,14 +1232,21 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src) r = temp; break; case TGSI_UTIL_SIGN_TOGGLE: - temp = temp_temp(pc); - emit_neg(pc, temp, r); - r = temp; + if (neg) + r->neg = 1; + else { + temp = temp_temp(pc); + emit_neg(pc, temp, r); + r = temp; + } break; case TGSI_UTIL_SIGN_SET: temp = temp_temp(pc); emit_abs(pc, temp, r); - emit_neg(pc, temp, r); + if (neg) + temp->neg = 1; + else + emit_neg(pc, temp, temp); r = temp; break; default: @@ -951,12 +1257,40 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src) return r; } +/* returns TRUE if instruction can overwrite sources before they're read */ +static boolean +direct2dest_op(const struct tgsi_full_instruction *insn) +{ + if (insn->Instruction.Saturate) + return FALSE; + + switch (insn->Instruction.Opcode) { + case TGSI_OPCODE_COS: + case TGSI_OPCODE_DP3: + case TGSI_OPCODE_DP4: + case TGSI_OPCODE_DPH: + case TGSI_OPCODE_KIL: + case TGSI_OPCODE_LIT: + case TGSI_OPCODE_POW: + case TGSI_OPCODE_RCP: + case TGSI_OPCODE_RSQ: + case TGSI_OPCODE_SCS: + case TGSI_OPCODE_SIN: + case TGSI_OPCODE_TEX: + case TGSI_OPCODE_TXP: + return FALSE; + default: + return TRUE; + } +} + static boolean nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) { const struct tgsi_full_instruction *inst = &tok->FullInstruction; struct nv50_reg *rdst[4], *dst[4], *src[3][4], *temp; unsigned mask, sat, unit; + boolean assimilate = FALSE; int i, c; mask = inst->FullDstRegisters[0].DstRegister.WriteMask; @@ -967,6 +1301,10 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) dst[c] = tgsi_dst(pc, c, &inst->FullDstRegisters[0]); else dst[c] = NULL; + rdst[c] = NULL; + src[0][c] = NULL; + src[1][c] = NULL; + src[2][c] = NULL; } for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { @@ -976,7 +1314,8 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) unit = fs->SrcRegister.Index; for (c = 0; c < 4; c++) - src[i][c] = tgsi_src(pc, c, fs); + src[i][c] = tgsi_src(pc, c, fs, + negate_supported(inst, i)); } if (sat) { @@ -984,6 +1323,25 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) rdst[c] = dst[c]; dst[c] = temp_temp(pc); } + } else + if (direct2dest_op(inst)) { + for (c = 0; c < 4; c++) { + if (!dst[c] || dst[c]->type != P_TEMP) + continue; + + for (i = c + 1; i < 4; i++) { + if (dst[c] == src[0][i] || + dst[c] == src[1][i] || + dst[c] == src[2][i]) + break; + } + if (i == 4) + continue; + + assimilate = TRUE; + rdst[c] = dst[c]; + dst[c] = alloc_temp(pc, NULL); + } } switch (inst->Instruction.Opcode) { @@ -1002,7 +1360,7 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) } break; case TGSI_OPCODE_COS: - temp = alloc_temp(pc, NULL); + temp = temp_temp(pc); emit_precossin(pc, temp, src[0][0]); emit_flop(pc, 5, temp, temp); for (c = 0; c < 4; c++) { @@ -1012,7 +1370,7 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) } break; case TGSI_OPCODE_DP3: - temp = alloc_temp(pc, NULL); + temp = temp_temp(pc); emit_mul(pc, temp, src[0][0], src[1][0]); emit_mad(pc, temp, src[0][1], src[1][1], temp); emit_mad(pc, temp, src[0][2], src[1][2], temp); @@ -1021,10 +1379,9 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) continue; emit_mov(pc, dst[c], temp); } - free_temp(pc, temp); break; case TGSI_OPCODE_DP4: - temp = alloc_temp(pc, NULL); + temp = temp_temp(pc); emit_mul(pc, temp, src[0][0], src[1][0]); emit_mad(pc, temp, src[0][1], src[1][1], temp); emit_mad(pc, temp, src[0][2], src[1][2], temp); @@ -1034,10 +1391,9 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) continue; emit_mov(pc, dst[c], temp); } - free_temp(pc, temp); break; case TGSI_OPCODE_DPH: - temp = alloc_temp(pc, NULL); + temp = temp_temp(pc); emit_mul(pc, temp, src[0][0], src[1][0]); emit_mad(pc, temp, src[0][1], src[1][1], temp); emit_mad(pc, temp, src[0][2], src[1][2], temp); @@ -1047,7 +1403,6 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) continue; emit_mov(pc, dst[c], temp); } - free_temp(pc, temp); break; case TGSI_OPCODE_DST: { @@ -1064,7 +1419,7 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) } break; case TGSI_OPCODE_EX2: - temp = alloc_temp(pc, NULL); + temp = temp_temp(pc); emit_preex2(pc, temp, src[0][0]); emit_flop(pc, 6, temp, temp); for (c = 0; c < 4; c++) { @@ -1072,7 +1427,6 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) continue; emit_mov(pc, dst[c], temp); } - free_temp(pc, temp); break; case TGSI_OPCODE_FLR: for (c = 0; c < 4; c++) { @@ -1082,26 +1436,26 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) } break; case TGSI_OPCODE_FRC: - temp = alloc_temp(pc, NULL); + temp = temp_temp(pc); for (c = 0; c < 4; c++) { if (!(mask & (1 << c))) continue; emit_flr(pc, temp, src[0][c]); emit_sub(pc, dst[c], src[0][c], temp); } - free_temp(pc, temp); break; case TGSI_OPCODE_KIL: emit_kil(pc, src[0][0]); emit_kil(pc, src[0][1]); emit_kil(pc, src[0][2]); emit_kil(pc, src[0][3]); + pc->p->cfg.fp.regs[2] |= 0x00100000; break; case TGSI_OPCODE_LIT: emit_lit(pc, &dst[0], mask, &src[0][0]); break; case TGSI_OPCODE_LG2: - temp = alloc_temp(pc, NULL); + temp = temp_temp(pc); emit_flop(pc, 3, temp, src[0][0]); for (c = 0; c < 4; c++) { if (!(mask & (1 << c))) @@ -1110,15 +1464,12 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) } break; case TGSI_OPCODE_LRP: + temp = temp_temp(pc); for (c = 0; c < 4; c++) { if (!(mask & (1 << c))) continue; - /*XXX: we can do better than this */ - temp = alloc_temp(pc, NULL); - emit_neg(pc, temp, src[0][c]); - emit_mad(pc, temp, temp, src[2][c], src[2][c]); - emit_mad(pc, dst[c], src[0][c], src[1][c], temp); - free_temp(pc, temp); + emit_sub(pc, temp, src[1][c], src[2][c]); + emit_mad(pc, dst[c], temp, src[0][c], src[2][c]); } break; case TGSI_OPCODE_MAD: @@ -1157,36 +1508,39 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) } break; case TGSI_OPCODE_POW: - temp = alloc_temp(pc, NULL); + temp = temp_temp(pc); emit_pow(pc, temp, src[0][0], src[1][0]); for (c = 0; c < 4; c++) { if (!(mask & (1 << c))) continue; emit_mov(pc, dst[c], temp); } - free_temp(pc, temp); break; case TGSI_OPCODE_RCP: - for (c = 0; c < 4; c++) { + for (c = 3; c >= 0; c--) { if (!(mask & (1 << c))) continue; emit_flop(pc, 0, dst[c], src[0][0]); } break; case TGSI_OPCODE_RSQ: - for (c = 0; c < 4; c++) { + for (c = 3; c >= 0; c--) { if (!(mask & (1 << c))) continue; emit_flop(pc, 2, dst[c], src[0][0]); } break; case TGSI_OPCODE_SCS: - temp = alloc_temp(pc, NULL); + temp = temp_temp(pc); emit_precossin(pc, temp, src[0][0]); if (mask & (1 << 0)) emit_flop(pc, 5, dst[0], temp); if (mask & (1 << 1)) emit_flop(pc, 4, dst[1], temp); + if (mask & (1 << 2)) + emit_mov_immdval(pc, dst[2], 0.0); + if (mask & (1 << 3)) + emit_mov_immdval(pc, dst[3], 1.0); break; case TGSI_OPCODE_SGE: for (c = 0; c < 4; c++) { @@ -1196,7 +1550,7 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) } break; case TGSI_OPCODE_SIN: - temp = alloc_temp(pc, NULL); + temp = temp_temp(pc); emit_precossin(pc, temp, src[0][0]); emit_flop(pc, 4, temp, temp); for (c = 0; c < 4; c++) { @@ -1220,33 +1574,15 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) } break; case TGSI_OPCODE_TEX: + emit_tex(pc, dst, mask, src[0], unit, + inst->InstructionExtTexture.Texture, FALSE); + break; case TGSI_OPCODE_TXP: - { - struct nv50_reg *t[4]; - struct nv50_program_exec *e; - - alloc_temp4(pc, t, 0); - emit_mov(pc, t[0], src[0][0]); - emit_mov(pc, t[1], src[0][1]); - - e = exec(pc); - e->inst[0] = 0xf6400000; - e->inst[0] |= (unit << 9); - set_long(pc, e); - e->inst[1] |= 0x0000c004; - set_dst(pc, t[0], e); - emit(pc, e); - - if (mask & (1 << 0)) emit_mov(pc, dst[0], t[0]); - if (mask & (1 << 1)) emit_mov(pc, dst[1], t[1]); - if (mask & (1 << 2)) emit_mov(pc, dst[2], t[2]); - if (mask & (1 << 3)) emit_mov(pc, dst[3], t[3]); - - free_temp4(pc, t); - } + emit_tex(pc, dst, mask, src[0], unit, + inst->InstructionExtTexture.Texture, TRUE); break; case TGSI_OPCODE_XPD: - temp = alloc_temp(pc, NULL); + temp = temp_temp(pc); if (mask & (1 << 0)) { emit_mul(pc, temp, src[0][2], src[1][1]); emit_msb(pc, dst[0], src[0][1], src[1][2], temp); @@ -1259,7 +1595,8 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) emit_mul(pc, temp, src[0][1], src[1][0]); emit_msb(pc, dst[2], src[0][0], src[1][1], temp); } - free_temp(pc, temp); + if (mask & (1 << 3)) + emit_mov_immdval(pc, dst[3], 1.0); break; case TGSI_OPCODE_END: break; @@ -1270,21 +1607,26 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) if (sat) { for (c = 0; c < 4; c++) { - struct nv50_program_exec *e; - if (!(mask & (1 << c))) continue; - e = exec(pc); + emit_cvt(pc, rdst[c], dst[c], -1, CVTOP_SAT, + CVT_F32_F32); + } + } else if (assimilate) { + for (c = 0; c < 4; c++) + if (rdst[c]) + assimilate_temp(pc, rdst[c], dst[c]); + } - e->inst[0] = 0xa0000000; /* cvt */ - set_long(pc, e); - e->inst[1] |= (6 << 29); /* cvt */ - e->inst[1] |= 0x04000000; /* 32 bit */ - e->inst[1] |= (1 << 14); /* src .f32 */ - e->inst[1] |= ((1 << 5) << 14); /* .sat */ - set_dst(pc, rdst[c], e); - set_src_0(pc, dst[c], e); - emit(pc, e); + for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { + for (c = 0; c < 4; c++) { + if (!src[i][c]) + continue; + if (src[i][c]->index == -1 && src[i][c]->type == P_IMMD) + FREE(src[i][c]); + else + if (src[i][c]->acc == pc->insn_cur) + release_hw(pc, src[i][c]); } } @@ -1292,12 +1634,169 @@ nv50_program_tx_insn(struct nv50_pc *pc, const union tgsi_full_token *tok) return TRUE; } +/* Adjust a bitmask that indicates what components of a source are used, + * we use this in tx_prep so we only load interpolants that are needed. + */ +static void +insn_adjust_mask(const struct tgsi_full_instruction *insn, unsigned *mask) +{ + const struct tgsi_instruction_ext_texture *tex; + + switch (insn->Instruction.Opcode) { + case TGSI_OPCODE_DP3: + *mask = 0x7; + break; + case TGSI_OPCODE_DP4: + case TGSI_OPCODE_DPH: + *mask = 0xF; + break; + case TGSI_OPCODE_LIT: + *mask = 0xB; + break; + case TGSI_OPCODE_RCP: + case TGSI_OPCODE_RSQ: + *mask = 0x1; + break; + case TGSI_OPCODE_TEX: + case TGSI_OPCODE_TXP: + assert(insn->Instruction.Extended); + tex = &insn->InstructionExtTexture; + + *mask = 0x7; + if (tex->Texture == TGSI_TEXTURE_1D) + *mask = 0x1; + else + if (tex->Texture == TGSI_TEXTURE_2D) + *mask = 0x3; + + if (insn->Instruction.Opcode == TGSI_OPCODE_TXP) + *mask |= 0x8; + break; + default: + break; + } +} + +static void +prep_inspect_insn(struct nv50_pc *pc, const union tgsi_full_token *tok, + unsigned *r_usage[2]) +{ + const struct tgsi_full_instruction *insn; + const struct tgsi_full_src_register *src; + const struct tgsi_dst_register *dst; + + unsigned i, c, k, n, mask, *acc_p; + + insn = &tok->FullInstruction; + dst = &insn->FullDstRegisters[0].DstRegister; + mask = dst->WriteMask; + + if (!r_usage[0]) + r_usage[0] = CALLOC(pc->temp_nr * 4, sizeof(unsigned)); + if (!r_usage[1]) + r_usage[1] = CALLOC(pc->attr_nr * 4, sizeof(unsigned)); + + if (dst->File == TGSI_FILE_TEMPORARY) { + for (c = 0; c < 4; c++) { + if (!(mask & (1 << c))) + continue; + r_usage[0][dst->Index * 4 + c] = pc->insn_nr; + } + } + + for (i = 0; i < insn->Instruction.NumSrcRegs; i++) { + src = &insn->FullSrcRegisters[i]; + + switch (src->SrcRegister.File) { + case TGSI_FILE_TEMPORARY: + acc_p = r_usage[0]; + break; + case TGSI_FILE_INPUT: + acc_p = r_usage[1]; + break; + default: + continue; + } + + insn_adjust_mask(insn, &mask); + + for (c = 0; c < 4; c++) { + if (!(mask & (1 << c))) + continue; + + k = tgsi_util_get_full_src_register_extswizzle(src, c); + switch (k) { + case TGSI_EXTSWIZZLE_X: + case TGSI_EXTSWIZZLE_Y: + case TGSI_EXTSWIZZLE_Z: + case TGSI_EXTSWIZZLE_W: + n = src->SrcRegister.Index * 4 + k; + acc_p[n] = pc->insn_nr; + break; + default: + break; + } + } + } +} + +static unsigned +load_fp_attrib(struct nv50_pc *pc, int i, unsigned *acc, int *mid, + int *aid, int *p_oid) +{ + struct nv50_reg *iv; + int oid, c, n; + unsigned mask = 0; + + iv = (pc->interp_mode[i] & INTERP_CENTROID) ? pc->iv_c : pc->iv_p; + + for (c = 0, n = i * 4; c < 4; c++, n++) { + oid = (*p_oid)++; + pc->attr[n].type = P_TEMP; + pc->attr[n].index = i; + + if (pc->attr[n].acc == acc[n]) + continue; + mask |= (1 << c); + + pc->attr[n].acc = acc[n]; + pc->attr[n].rhw = pc->attr[n].hw = -1; + alloc_reg(pc, &pc->attr[n]); + + pc->attr[n].rhw = (*aid)++; + emit_interp(pc, &pc->attr[n], iv, pc->interp_mode[i]); + + pc->p->cfg.fp.map[(*mid) / 4] |= oid << (8 * ((*mid) % 4)); + (*mid)++; + pc->p->cfg.fp.regs[1] += 0x00010001; + } + + return mask; +} + static boolean nv50_program_tx_prep(struct nv50_pc *pc) { struct tgsi_parse_context p; boolean ret = FALSE; unsigned i, c; + unsigned fcol, bcol, fcrd, depr; + + /* count (centroid) perspective interpolations */ + unsigned centroid_loads = 0; + unsigned perspect_loads = 0; + + /* track register access for temps and attrs */ + unsigned *r_usage[2]; + r_usage[0] = NULL; + r_usage[1] = NULL; + + depr = fcol = bcol = fcrd = 0xffff; + + if (pc->p->type == PIPE_SHADER_FRAGMENT) { + pc->p->cfg.fp.regs[0] = 0x01000404; + pc->p->cfg.fp.regs[1] = 0x00000400; + } tgsi_parse_init(&p, pc->p->pipe.tokens); while (!tgsi_parse_end_of_tokens(&p)) { @@ -1310,18 +1809,19 @@ nv50_program_tx_prep(struct nv50_pc *pc) const struct tgsi_full_immediate *imm = &p.FullToken.FullImmediate; - ctor_immd(pc, imm->u.ImmediateFloat32[0].Float, - imm->u.ImmediateFloat32[1].Float, - imm->u.ImmediateFloat32[2].Float, - imm->u.ImmediateFloat32[3].Float); + ctor_immd(pc, imm->u[0].Float, + imm->u[1].Float, + imm->u[2].Float, + imm->u[3].Float); } break; case TGSI_TOKEN_TYPE_DECLARATION: { const struct tgsi_full_declaration *d; - unsigned last; + unsigned last, first, mode; d = &p.FullToken.FullDeclaration; + first = d->DeclarationRange.First; last = d->DeclarationRange.Last; switch (d->Declaration.File) { @@ -1332,10 +1832,69 @@ nv50_program_tx_prep(struct nv50_pc *pc) case TGSI_FILE_OUTPUT: if (pc->result_nr < (last + 1)) pc->result_nr = last + 1; + + if (!d->Declaration.Semantic) + break; + + switch (d->Semantic.SemanticName) { + case TGSI_SEMANTIC_POSITION: + depr = first; + pc->p->cfg.fp.regs[2] |= 0x00000100; + pc->p->cfg.fp.regs[3] |= 0x00000011; + break; + default: + break; + } + break; case TGSI_FILE_INPUT: + { if (pc->attr_nr < (last + 1)) pc->attr_nr = last + 1; + + if (pc->p->type != PIPE_SHADER_FRAGMENT) + break; + + switch (d->Declaration.Interpolate) { + case TGSI_INTERPOLATE_CONSTANT: + mode = INTERP_FLAT; + break; + case TGSI_INTERPOLATE_PERSPECTIVE: + mode = INTERP_PERSPECTIVE; + break; + default: + mode = INTERP_LINEAR; + break; + } + + if (d->Declaration.Semantic) { + switch (d->Semantic.SemanticName) { + case TGSI_SEMANTIC_POSITION: + fcrd = first; + break; + case TGSI_SEMANTIC_COLOR: + fcol = first; + mode = INTERP_PERSPECTIVE; + break; + case TGSI_SEMANTIC_BCOLOR: + bcol = first; + mode = INTERP_PERSPECTIVE; + break; + } + } + + if (d->Declaration.Centroid) { + mode |= INTERP_CENTROID; + if (mode & INTERP_PERSPECTIVE) + centroid_loads++; + } else + if (mode & INTERP_PERSPECTIVE) + perspect_loads++; + + assert(last < 32); + for (i = first; i <= last; i++) + pc->interp_mode[i] = mode; + } break; case TGSI_FILE_CONSTANT: if (pc->param_nr < (last + 1)) @@ -1351,6 +1910,8 @@ nv50_program_tx_prep(struct nv50_pc *pc) } break; case TGSI_TOKEN_TYPE_INSTRUCTION: + pc->insn_nr++; + prep_inspect_insn(pc, tok, r_usage); break; default: break; @@ -1366,56 +1927,95 @@ nv50_program_tx_prep(struct nv50_pc *pc) for (c = 0; c < 4; c++) { pc->temp[i*4+c].type = P_TEMP; pc->temp[i*4+c].hw = -1; + pc->temp[i*4+c].rhw = -1; pc->temp[i*4+c].index = i; + pc->temp[i*4+c].acc = r_usage[0][i*4+c]; } } } if (pc->attr_nr) { - struct nv50_reg *iv = NULL; - int aid = 0; + int oid = 4, mid = 4, aid = 0; + /* oid = VP output id + * aid = FP attribute/interpolant id + * mid = VP output mapping field ID + */ pc->attr = CALLOC(pc->attr_nr * 4, sizeof(struct nv50_reg)); if (!pc->attr) goto out_err; if (pc->p->type == PIPE_SHADER_FRAGMENT) { - iv = alloc_temp(pc, NULL); - emit_interp(pc, iv, iv, NULL); - emit_flop(pc, 0, iv, iv); - aid++; - } + /* position should be loaded first */ + if (fcrd != 0xffff) { + unsigned mask; + mid = 0; + mask = load_fp_attrib(pc, fcrd, r_usage[1], + &mid, &aid, &oid); + oid = 0; + pc->p->cfg.fp.regs[1] |= (mask << 24); + pc->p->cfg.fp.map[0] = 0x04040404 * fcrd; + } + pc->p->cfg.fp.map[0] += 0x03020100; - for (i = 0; i < pc->attr_nr; i++) { - struct nv50_reg *a = &pc->attr[i*4]; + /* should do MAD fcrd.xy, fcrd, SOME_CONST, fcrd */ - for (c = 0; c < 4; c++) { - if (pc->p->type == PIPE_SHADER_FRAGMENT) { - struct nv50_reg *at = - alloc_temp(pc, NULL); - pc->attr[i*4+c].type = at->type; - pc->attr[i*4+c].hw = at->hw; - pc->attr[i*4+c].index = at->index; + if (perspect_loads) { + pc->iv_p = alloc_temp(pc, NULL); + + if (!(pc->p->cfg.fp.regs[1] & 0x08000000)) { + pc->p->cfg.fp.regs[1] |= 0x08000000; + pc->iv_p->rhw = aid++; + emit_interp(pc, pc->iv_p, NULL, + INTERP_LINEAR); + emit_flop(pc, 0, pc->iv_p, pc->iv_p); } else { - pc->p->cfg.vp.attr[aid/32] |= - (1 << (aid % 32)); - pc->attr[i*4+c].type = P_ATTR; - pc->attr[i*4+c].hw = aid++; - pc->attr[i*4+c].index = i; + pc->iv_p->rhw = aid - 1; + emit_flop(pc, 0, pc->iv_p, + &pc->attr[fcrd * 4 + 3]); } } - if (pc->p->type != PIPE_SHADER_FRAGMENT) - continue; + if (centroid_loads) { + pc->iv_c = alloc_temp(pc, NULL); + pc->iv_c->rhw = pc->iv_p ? aid - 1 : aid++; + emit_interp(pc, pc->iv_c, NULL, + INTERP_CENTROID); + emit_flop(pc, 0, pc->iv_c, pc->iv_c); + pc->p->cfg.fp.regs[1] |= 0x08000000; + } - emit_interp(pc, &a[0], &a[0], iv); - emit_interp(pc, &a[1], &a[1], iv); - emit_interp(pc, &a[2], &a[2], iv); - emit_interp(pc, &a[3], &a[3], iv); - } + for (c = 0; c < 4; c++) { + /* I don't know what these values do, but + * let's set them like the blob does: + */ + if (fcol != 0xffff && r_usage[1][fcol * 4 + c]) + pc->p->cfg.fp.regs[0] += 0x00010000; + if (bcol != 0xffff && r_usage[1][bcol * 4 + c]) + pc->p->cfg.fp.regs[0] += 0x00010000; + } - if (iv) - free_temp(pc, iv); + for (i = 0; i < pc->attr_nr; i++) + load_fp_attrib(pc, i, r_usage[1], + &mid, &aid, &oid); + + if (pc->iv_p) + free_temp(pc, pc->iv_p); + if (pc->iv_c) + free_temp(pc, pc->iv_c); + + pc->p->cfg.fp.high_map = (mid / 4); + pc->p->cfg.fp.high_map += ((mid % 4) ? 1 : 0); + } else { + /* vertex program */ + for (i = 0; i < pc->attr_nr * 4; i++) { + pc->p->cfg.vp.attr[aid / 32] |= + (1 << (aid % 32)); + pc->attr[i].type = P_ATTR; + pc->attr[i].hw = aid++; + pc->attr[i].index = i / 4; + } + } } if (pc->result_nr) { @@ -1430,12 +2030,20 @@ nv50_program_tx_prep(struct nv50_pc *pc) if (pc->p->type == PIPE_SHADER_FRAGMENT) { pc->result[i*4+c].type = P_TEMP; pc->result[i*4+c].hw = -1; + pc->result[i*4+c].rhw = (i == depr) ? + -1 : rid++; } else { pc->result[i*4+c].type = P_RESULT; pc->result[i*4+c].hw = rid++; } pc->result[i*4+c].index = i; } + + if (pc->p->type == PIPE_SHADER_FRAGMENT && + depr != 0xffff) { + pc->result[depr * 4 + 2].rhw = + (pc->result_nr - 1) * 4; + } } } @@ -1456,7 +2064,7 @@ nv50_program_tx_prep(struct nv50_pc *pc) } if (pc->immd_nr) { - int rid = pc->param_nr * 4; + int rid = 0; pc->immd = CALLOC(pc->immd_nr * 4, sizeof(struct nv50_reg)); if (!pc->immd) @@ -1473,15 +2081,38 @@ nv50_program_tx_prep(struct nv50_pc *pc) ret = TRUE; out_err: + if (r_usage[0]) + FREE(r_usage[0]); + if (r_usage[1]) + FREE(r_usage[1]); + tgsi_parse_free(&p); return ret; } +static void +free_nv50_pc(struct nv50_pc *pc) +{ + if (pc->immd) + FREE(pc->immd); + if (pc->param) + FREE(pc->param); + if (pc->result) + FREE(pc->result); + if (pc->attr) + FREE(pc->attr); + if (pc->temp) + FREE(pc->temp); + + FREE(pc); +} + static boolean nv50_program_tx(struct nv50_program *p) { struct tgsi_parse_context parse; struct nv50_pc *pc; + unsigned k; boolean ret; pc = CALLOC_STRUCT(nv50_pc); @@ -1498,10 +2129,16 @@ nv50_program_tx(struct nv50_program *p) while (!tgsi_parse_end_of_tokens(&parse)) { const union tgsi_full_token *tok = &parse.FullToken; + /* don't allow half insn/immd on first and last instruction */ + pc->allow32 = TRUE; + if (pc->insn_cur == 0 || pc->insn_cur + 2 == pc->insn_nr) + pc->allow32 = FALSE; + tgsi_parse_token(&parse); switch (tok->Token.Type) { case TGSI_TOKEN_TYPE_INSTRUCTION: + ++pc->insn_cur; ret = nv50_program_tx_insn(pc, tok); if (ret == FALSE) goto out_err; @@ -1515,8 +2152,40 @@ nv50_program_tx(struct nv50_program *p) struct nv50_reg out; out.type = P_TEMP; - for (out.hw = 0; out.hw < pc->result_nr * 4; out.hw++) - emit_mov(pc, &out, &pc->result[out.hw]); + for (k = 0; k < pc->result_nr * 4; k++) { + if (pc->result[k].rhw == -1) + continue; + if (pc->result[k].hw != pc->result[k].rhw) { + out.hw = pc->result[k].rhw; + emit_mov(pc, &out, &pc->result[k]); + } + if (pc->p->cfg.high_result < (pc->result[k].rhw + 1)) + pc->p->cfg.high_result = pc->result[k].rhw + 1; + } + } + + /* look for single half instructions and make them long */ + struct nv50_program_exec *e, *e_prev; + + for (k = 0, e = pc->p->exec_head, e_prev = NULL; e; e = e->next) { + if (!is_long(e)) + k++; + + if (!e->next || is_long(e->next)) { + if (k & 1) + convert_to_long(pc, e); + k = 0; + } + + if (e->next) + e_prev = e; + } + + if (!is_long(pc->p->exec_tail)) { + /* this may occur if moving FP results */ + assert(e_prev && !is_long(e_prev)); + convert_to_long(pc, e_prev); + convert_to_long(pc, pc->p->exec_tail); } assert(is_long(pc->p->exec_tail) && !is_immd(pc->p->exec_head)); @@ -1530,6 +2199,7 @@ out_err: tgsi_parse_free(&parse); out_cleanup: + free_nv50_pc(pc); return ret; } @@ -1543,16 +2213,16 @@ nv50_program_validate(struct nv50_context *nv50, struct nv50_program *p) static void nv50_program_upload_data(struct nv50_context *nv50, float *map, - unsigned start, unsigned count) + unsigned start, unsigned count, unsigned cbuf) { - struct nouveau_channel *chan = nv50->screen->nvws->channel; + struct nouveau_channel *chan = nv50->screen->base.channel; struct nouveau_grobj *tesla = nv50->screen->tesla; while (count) { unsigned nr = count > 2047 ? 2047 : count; BEGIN_RING(chan, tesla, 0x00000f00, 1); - OUT_RING (chan, (NV50_CB_PMISC << 0) | (start << 8)); + OUT_RING (chan, (cbuf << 0) | (start << 8)); BEGIN_RING(chan, tesla, 0x40000f04, nr); OUT_RINGp (chan, map, nr); @@ -1565,70 +2235,93 @@ nv50_program_upload_data(struct nv50_context *nv50, float *map, static void nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p) { - struct nouveau_winsys *nvws = nv50->screen->nvws; - struct pipe_winsys *ws = nv50->pipe.winsys; - unsigned nr = p->param_nr + p->immd_nr; + struct pipe_screen *pscreen = nv50->pipe.screen; - if (!p->data && nr) { - struct nouveau_resource *heap = nv50->screen->vp_data_heap; + if (!p->data[0] && p->immd_nr) { + struct nouveau_resource *heap = nv50->screen->immd_heap[0]; - if (nvws->res_alloc(heap, nr, p, &p->data)) { - while (heap->next && heap->size < nr) { + if (nouveau_resource_alloc(heap, p->immd_nr, p, &p->data[0])) { + while (heap->next && heap->size < p->immd_nr) { struct nv50_program *evict = heap->next->priv; - nvws->res_free(&evict->data); + nouveau_resource_free(&evict->data[0]); } - if (nvws->res_alloc(heap, nr, p, &p->data)) + if (nouveau_resource_alloc(heap, p->immd_nr, p, + &p->data[0])) assert(0); } + + /* immediates only need to be uploaded again when freed */ + nv50_program_upload_data(nv50, p->immd, p->data[0]->start, + p->immd_nr, NV50_CB_PMISC); } - if (p->param_nr) { - float *map = ws->buffer_map(ws, nv50->constbuf[p->type], - PIPE_BUFFER_USAGE_CPU_READ); - nv50_program_upload_data(nv50, map, p->data->start, - p->param_nr); - ws->buffer_unmap(ws, nv50->constbuf[p->type]); + if (!p->data[1] && p->param_nr) { + struct nouveau_resource *heap = + nv50->screen->parm_heap[p->type]; + + if (nouveau_resource_alloc(heap, p->param_nr, p, &p->data[1])) { + while (heap->next && heap->size < p->param_nr) { + struct nv50_program *evict = heap->next->priv; + nouveau_resource_free(&evict->data[1]); + } + + if (nouveau_resource_alloc(heap, p->param_nr, p, + &p->data[1])) + assert(0); + } } - if (p->immd_nr) { - nv50_program_upload_data(nv50, p->immd, - p->data->start + p->param_nr, - p->immd_nr); + if (p->param_nr) { + unsigned cbuf = NV50_CB_PVP; + float *map = pipe_buffer_map(pscreen, nv50->constbuf[p->type], + PIPE_BUFFER_USAGE_CPU_READ); + if (p->type == PIPE_SHADER_FRAGMENT) + cbuf = NV50_CB_PFP; + nv50_program_upload_data(nv50, map, p->data[1]->start, + p->param_nr, cbuf); + pipe_buffer_unmap(pscreen, nv50->constbuf[p->type]); } } static void nv50_program_validate_code(struct nv50_context *nv50, struct nv50_program *p) { - struct nouveau_channel *chan = nv50->screen->nvws->channel; + struct nouveau_channel *chan = nv50->screen->base.channel; struct nouveau_grobj *tesla = nv50->screen->tesla; - struct pipe_screen *screen = nv50->pipe.screen; struct nv50_program_exec *e; struct nouveau_stateobj *so; const unsigned flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR; unsigned start, count, *up, *ptr; boolean upload = FALSE; - if (!p->buffer) { - p->buffer = screen->buffer_create(screen, 0x100, 0, p->exec_size * 4); + if (!p->bo) { + nouveau_bo_new(chan->device, NOUVEAU_BO_VRAM, 0x100, + p->exec_size * 4, &p->bo); upload = TRUE; } - if (p->data && p->data->start != p->data_start) { + if ((p->data[0] && p->data[0]->start != p->data_start[0]) || + (p->data[1] && p->data[1]->start != p->data_start[1])) { for (e = p->exec_head; e; e = e->next) { - unsigned ei, ci; + unsigned ei, ci, bs; if (e->param.index < 0) continue; + bs = (e->inst[1] >> 22) & 0x07; + assert(bs < 2); ei = e->param.shift >> 5; - ci = e->param.index + p->data->start; + ci = e->param.index + p->data[bs]->start; e->inst[ei] &= ~e->param.mask; e->inst[ei] |= (ci << e->param.shift); } - p->data_start = p->data->start; + if (p->data[0]) + p->data_start[0] = p->data[0]->start; + if (p->data[1]) + p->data_start[1] = p->data[1]->start; + upload = TRUE; } @@ -1637,13 +2330,11 @@ nv50_program_validate_code(struct nv50_context *nv50, struct nv50_program *p) #ifdef NV50_PROGRAM_DUMP NOUVEAU_ERR("-------\n"); - up = ptr = MALLOC(p->exec_size * 4); for (e = p->exec_head; e; e = e->next) { NOUVEAU_ERR("0x%08x\n", e->inst[0]); if (is_long(e)) NOUVEAU_ERR("0x%08x\n", e->inst[1]); } - #endif up = ptr = MALLOC(p->exec_size * 4); @@ -1655,20 +2346,20 @@ nv50_program_validate_code(struct nv50_context *nv50, struct nv50_program *p) so = so_new(4,2); so_method(so, nv50->screen->tesla, 0x1280, 3); - so_reloc (so, p->buffer, 0, flags | NOUVEAU_BO_HIGH, 0, 0); - so_reloc (so, p->buffer, 0, flags | NOUVEAU_BO_LOW, 0, 0); + so_reloc (so, p->bo, 0, flags | NOUVEAU_BO_HIGH, 0, 0); + so_reloc (so, p->bo, 0, flags | NOUVEAU_BO_LOW, 0, 0); so_data (so, (NV50_CB_PUPLOAD << 16) | 0x0800); //(p->exec_size * 4)); start = 0; count = p->exec_size; while (count) { - struct nouveau_winsys *nvws = nv50->screen->nvws; + struct nouveau_channel *chan = nv50->screen->base.channel; unsigned nr; - so_emit(nvws, so); + so_emit(chan, so); nr = MIN2(count, 2047); - nr = MIN2(nvws->channel->pushbuf->remaining, nr); - if (nvws->channel->pushbuf->remaining < (nr + 3)) { + nr = MIN2(chan->pushbuf->remaining, nr); + if (chan->pushbuf->remaining < (nr + 3)) { FIRE_RING(chan); continue; } @@ -1704,10 +2395,10 @@ nv50_vertprog_validate(struct nv50_context *nv50) so = so_new(13, 2); so_method(so, tesla, NV50TCL_VP_ADDRESS_HIGH, 2); - so_reloc (so, p->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | - NOUVEAU_BO_HIGH, 0, 0); - so_reloc (so, p->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | - NOUVEAU_BO_LOW, 0, 0); + so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | + NOUVEAU_BO_HIGH, 0, 0); + so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | + NOUVEAU_BO_LOW, 0, 0); so_method(so, tesla, 0x1650, 2); so_data (so, p->cfg.vp.attr[0]); so_data (so, p->cfg.vp.attr[1]); @@ -1728,6 +2419,7 @@ nv50_fragprog_validate(struct nv50_context *nv50) struct nouveau_grobj *tesla = nv50->screen->tesla; struct nv50_program *p = nv50->fragprog; struct nouveau_stateobj *so; + unsigned i; if (!p->translated) { nv50_program_validate(nv50, p); @@ -1740,22 +2432,27 @@ nv50_fragprog_validate(struct nv50_context *nv50) so = so_new(64, 2); so_method(so, tesla, NV50TCL_FP_ADDRESS_HIGH, 2); - so_reloc (so, p->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | - NOUVEAU_BO_HIGH, 0, 0); - so_reloc (so, p->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | - NOUVEAU_BO_LOW, 0, 0); + so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | + NOUVEAU_BO_HIGH, 0, 0); + so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | + NOUVEAU_BO_LOW, 0, 0); so_method(so, tesla, 0x1904, 4); - so_data (so, 0x00040404); /* p: 0x01000404 */ + so_data (so, p->cfg.fp.regs[0]); /* 0x01000404 / 0x00040404 */ so_data (so, 0x00000004); so_data (so, 0x00000000); so_data (so, 0x00000000); - so_method(so, tesla, 0x16bc, 3); /*XXX: fixme */ - so_data (so, 0x03020100); - so_data (so, 0x07060504); - so_data (so, 0x0b0a0908); + so_method(so, tesla, 0x16bc, p->cfg.fp.high_map); + for (i = 0; i < p->cfg.fp.high_map; i++) + so_data(so, p->cfg.fp.map[i]); so_method(so, tesla, 0x1988, 2); - so_data (so, 0x08080408); //0x08040404); /* p: 0x0f000401 */ + so_data (so, p->cfg.fp.regs[1]); /* 0x08040404 / 0x0f000401 */ so_data (so, p->cfg.high_temp); + so_method(so, tesla, 0x1298, 1); + so_data (so, p->cfg.high_result); + so_method(so, tesla, 0x19a8, 1); + so_data (so, p->cfg.fp.regs[2]); + so_method(so, tesla, 0x196c, 1); + so_data (so, p->cfg.fp.regs[3]); so_method(so, tesla, 0x1414, 1); so_data (so, 0); /* program start offset */ so_ref(so, &nv50->state.fragprog); @@ -1765,8 +2462,6 @@ nv50_fragprog_validate(struct nv50_context *nv50) void nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p) { - struct pipe_screen *pscreen = nv50->pipe.screen; - while (p->exec_head) { struct nv50_program_exec *e = p->exec_head; @@ -1776,10 +2471,10 @@ nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p) p->exec_tail = NULL; p->exec_size = 0; - if (p->buffer) - pipe_buffer_reference(&p->buffer, NULL); + nouveau_bo_ref(NULL, &p->bo); - nv50->screen->nvws->res_free(&p->data); + nouveau_resource_free(&p->data[0]); + nouveau_resource_free(&p->data[1]); p->translated = 0; } diff --git a/src/gallium/drivers/nv50/nv50_program.h b/src/gallium/drivers/nv50/nv50_program.h index 78deed6a384..096e0476aab 100644 --- a/src/gallium/drivers/nv50/nv50_program.h +++ b/src/gallium/drivers/nv50/nv50_program.h @@ -24,10 +24,10 @@ struct nv50_program { struct nv50_program_exec *exec_head; struct nv50_program_exec *exec_tail; unsigned exec_size; - struct nouveau_resource *data; - unsigned data_start; + struct nouveau_resource *data[2]; + unsigned data_start[2]; - struct pipe_buffer *buffer; + struct nouveau_bo *bo; float *immd; unsigned immd_nr; @@ -39,6 +39,11 @@ struct nv50_program { struct { unsigned attr[2]; } vp; + struct { + unsigned regs[4]; + unsigned map[5]; + unsigned high_map; + } fp; } cfg; }; diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c index 35cebdbdc32..c354e10b0f8 100644 --- a/src/gallium/drivers/nv50/nv50_query.c +++ b/src/gallium/drivers/nv50/nv50_query.c @@ -26,7 +26,7 @@ #include "nv50_context.h" struct nv50_query { - struct pipe_buffer *buffer; + struct nouveau_bo *bo; unsigned type; boolean ready; uint64_t result; @@ -41,14 +41,16 @@ nv50_query(struct pipe_query *pipe) static struct pipe_query * nv50_query_create(struct pipe_context *pipe, unsigned type) { - struct pipe_screen *screen = pipe->screen; + struct nouveau_device *dev = nouveau_screen(pipe->screen)->device; struct nv50_query *q = CALLOC_STRUCT(nv50_query); + int ret; assert (q->type == PIPE_QUERY_OCCLUSION_COUNTER); q->type = type; - q->buffer = screen->buffer_create(screen, 256, 0, 16); - if (!q->buffer) { + ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, 256, + 16, &q->bo); + if (ret) { FREE(q); return NULL; } @@ -62,7 +64,7 @@ nv50_query_destroy(struct pipe_context *pipe, struct pipe_query *pq) struct nv50_query *q = nv50_query(pq); if (q) { - pipe_buffer_reference(&q->buffer, NULL); + nouveau_bo_ref(NULL, &q->bo); FREE(q); } } @@ -71,7 +73,7 @@ static void nv50_query_begin(struct pipe_context *pipe, struct pipe_query *pq) { struct nv50_context *nv50 = nv50_context(pipe); - struct nouveau_channel *chan = nv50->screen->nvws->channel; + struct nouveau_channel *chan = nv50->screen->base.channel; struct nouveau_grobj *tesla = nv50->screen->tesla; struct nv50_query *q = nv50_query(pq); @@ -87,15 +89,14 @@ static void nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq) { struct nv50_context *nv50 = nv50_context(pipe); - struct nouveau_channel *chan = nv50->screen->nvws->channel; + struct nouveau_channel *chan = nv50->screen->base.channel; struct nouveau_grobj *tesla = nv50->screen->tesla; struct nv50_query *q = nv50_query(pq); - struct nouveau_bo *bo = nv50->screen->nvws->get_bo(q->buffer); WAIT_RING (chan, 5); BEGIN_RING(chan, tesla, 0x1b00, 4); - OUT_RELOCh(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + OUT_RELOCh(chan, q->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + OUT_RELOCl(chan, q->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); OUT_RING (chan, 0x00000000); OUT_RING (chan, 0x0100f002); FIRE_RING (chan); @@ -105,19 +106,17 @@ static boolean nv50_query_result(struct pipe_context *pipe, struct pipe_query *pq, boolean wait, uint64_t *result) { - struct pipe_winsys *ws = pipe->winsys; struct nv50_query *q = nv50_query(pq); - - /*XXX: Want to be able to return FALSE here instead of blocking - * until the result is available.. - */ + int ret; if (!q->ready) { - uint32_t *map = ws->buffer_map(ws, q->buffer, - PIPE_BUFFER_USAGE_CPU_READ); - q->result = map[1]; + ret = nouveau_bo_map(q->bo, NOUVEAU_BO_RD | + wait ? 0 : NOUVEAU_BO_NOWAIT); + if (ret) + return false; + q->result = ((uint32_t *)q->bo->map)[1]; q->ready = TRUE; - ws->buffer_unmap(ws, q->buffer); + nouveau_bo_unmap(q->bo); } *result = q->result; diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index 29805645948..0f6b1aed96c 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -22,8 +22,6 @@ #include "pipe/p_screen.h" -#include "util/u_simple_screen.h" - #include "nv50_context.h" #include "nv50_screen.h" @@ -39,8 +37,17 @@ nv50_screen_is_format_supported(struct pipe_screen *pscreen, switch (format) { case PIPE_FORMAT_A8R8G8B8_UNORM: case PIPE_FORMAT_R5G6B5_UNORM: + return TRUE; + default: + break; + } + } else + if (tex_usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL) { + switch (format) { + case PIPE_FORMAT_Z32_FLOAT: case PIPE_FORMAT_Z24S8_UNORM: - case PIPE_FORMAT_Z16_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + case PIPE_FORMAT_S8Z24_UNORM: return TRUE; default: break; @@ -68,23 +75,6 @@ nv50_screen_is_format_supported(struct pipe_screen *pscreen, return FALSE; } -static const char * -nv50_screen_get_name(struct pipe_screen *pscreen) -{ - struct nv50_screen *screen = nv50_screen(pscreen); - struct nouveau_device *dev = screen->nvws->channel->device; - static char buffer[128]; - - snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset); - return buffer; -} - -static const char * -nv50_screen_get_vendor(struct pipe_screen *pscreen) -{ - return "nouveau"; -} - static int nv50_screen_get_param(struct pipe_screen *pscreen, int param) { @@ -120,6 +110,10 @@ nv50_screen_get_param(struct pipe_screen *pscreen, int param) return 1; case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: return 0; + case PIPE_CAP_TGSI_CONT_SUPPORTED: + return 0; + case PIPE_CAP_BLEND_EQUATION_SEPARATE: + return 1; case NOUVEAU_CAP_HW_VTXBUF: return 1; case NOUVEAU_CAP_HW_IDXBUF: @@ -153,37 +147,64 @@ nv50_screen_get_paramf(struct pipe_screen *pscreen, int param) static void nv50_screen_destroy(struct pipe_screen *pscreen) { - FREE(pscreen); + struct nv50_screen *screen = nv50_screen(pscreen); + + nouveau_notifier_free(&screen->sync); + nouveau_grobj_free(&screen->tesla); + nouveau_grobj_free(&screen->eng2d); + nouveau_grobj_free(&screen->m2mf); + nouveau_screen_fini(&screen->base); + FREE(screen); } struct pipe_screen * -nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) +nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) { struct nv50_screen *screen = CALLOC_STRUCT(nv50_screen); + struct nouveau_channel *chan; + struct pipe_screen *pscreen; struct nouveau_stateobj *so; - unsigned tesla_class = 0, ret; - unsigned chipset = nvws->channel->device->chipset; - int i; + unsigned chipset = dev->chipset; + unsigned tesla_class = 0; + int ret, i; if (!screen) return NULL; - screen->nvws = nvws; + pscreen = &screen->base.base; + + ret = nouveau_screen_init(&screen->base, dev); + if (ret) { + nv50_screen_destroy(pscreen); + return NULL; + } + chan = screen->base.channel; + + pscreen->winsys = ws; + pscreen->destroy = nv50_screen_destroy; + pscreen->get_param = nv50_screen_get_param; + pscreen->get_paramf = nv50_screen_get_paramf; + pscreen->is_format_supported = nv50_screen_is_format_supported; + + nv50_screen_init_miptree_functions(pscreen); + nv50_transfer_init_screen_functions(pscreen); /* DMA engine object */ - ret = nvws->grobj_alloc(nvws, 0x5039, &screen->m2mf); + ret = nouveau_grobj_alloc(chan, 0xbeef5039, 0x5039, &screen->m2mf); if (ret) { NOUVEAU_ERR("Error creating M2MF object: %d\n", ret); - nv50_screen_destroy(&screen->pipe); + nv50_screen_destroy(pscreen); return NULL; } + BIND_RING(chan, screen->m2mf, 1); /* 2D object */ - ret = nvws->grobj_alloc(nvws, NV50_2D, &screen->eng2d); + ret = nouveau_grobj_alloc(chan, 0xbeef502d, 0x502d, &screen->eng2d); if (ret) { NOUVEAU_ERR("Error creating 2D object: %d\n", ret); - nv50_screen_destroy(&screen->pipe); + nv50_screen_destroy(pscreen); return NULL; } + BIND_RING(chan, screen->eng2d, 2); /* 3D object */ switch (chipset & 0xf0) { @@ -199,70 +220,55 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) break; default: NOUVEAU_ERR("Not a known NV50 chipset: NV%02x\n", chipset); - nv50_screen_destroy(&screen->pipe); + nv50_screen_destroy(pscreen); return NULL; } if (tesla_class == 0) { NOUVEAU_ERR("Unknown G8x chipset: NV%02x\n", chipset); - nv50_screen_destroy(&screen->pipe); + nv50_screen_destroy(pscreen); return NULL; } - ret = nvws->grobj_alloc(nvws, tesla_class, &screen->tesla); + ret = nouveau_grobj_alloc(chan, 0xbeef5097, tesla_class, &screen->tesla); if (ret) { NOUVEAU_ERR("Error creating 3D object: %d\n", ret); - nv50_screen_destroy(&screen->pipe); + nv50_screen_destroy(pscreen); return NULL; } + BIND_RING(chan, screen->tesla, 3); /* Sync notifier */ - ret = nvws->notifier_alloc(nvws, 1, &screen->sync); + ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); if (ret) { NOUVEAU_ERR("Error creating notifier object: %d\n", ret); - nv50_screen_destroy(&screen->pipe); + nv50_screen_destroy(pscreen); return NULL; } - /* Setup the pipe */ - screen->pipe.winsys = ws; - - screen->pipe.destroy = nv50_screen_destroy; - - screen->pipe.get_name = nv50_screen_get_name; - screen->pipe.get_vendor = nv50_screen_get_vendor; - screen->pipe.get_param = nv50_screen_get_param; - screen->pipe.get_paramf = nv50_screen_get_paramf; - - screen->pipe.is_format_supported = nv50_screen_is_format_supported; - - nv50_screen_init_miptree_functions(&screen->pipe); - nv50_transfer_init_screen_functions(&screen->pipe); - u_simple_screen_init(&screen->pipe); - /* Static M2MF init */ so = so_new(32, 0); so_method(so, screen->m2mf, 0x0180, 3); so_data (so, screen->sync->handle); - so_data (so, screen->nvws->channel->vram->handle); - so_data (so, screen->nvws->channel->vram->handle); - so_emit(nvws, so); + so_data (so, chan->vram->handle); + so_data (so, chan->vram->handle); + so_emit(chan, so); so_ref (NULL, &so); /* Static 2D init */ so = so_new(64, 0); so_method(so, screen->eng2d, NV50_2D_DMA_NOTIFY, 4); so_data (so, screen->sync->handle); - so_data (so, screen->nvws->channel->vram->handle); - so_data (so, screen->nvws->channel->vram->handle); - so_data (so, screen->nvws->channel->vram->handle); + so_data (so, chan->vram->handle); + so_data (so, chan->vram->handle); + so_data (so, chan->vram->handle); so_method(so, screen->eng2d, NV50_2D_OPERATION, 1); so_data (so, NV50_2D_OPERATION_SRCCOPY); so_method(so, screen->eng2d, 0x0290, 1); so_data (so, 0); so_method(so, screen->eng2d, 0x0888, 1); so_data (so, 1); - so_emit(nvws, so); + so_emit(chan, so); so_ref(NULL, &so); /* Static tesla init */ @@ -275,11 +281,11 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) so_method(so, screen->tesla, NV50TCL_DMA_UNK0(0), NV50TCL_DMA_UNK0__SIZE); for (i = 0; i < NV50TCL_DMA_UNK0__SIZE; i++) - so_data(so, nvws->channel->vram->handle); + so_data(so, chan->vram->handle); so_method(so, screen->tesla, NV50TCL_DMA_UNK1(0), NV50TCL_DMA_UNK1__SIZE); for (i = 0; i < NV50TCL_DMA_UNK1__SIZE; i++) - so_data(so, nvws->channel->vram->handle); + so_data(so, chan->vram->handle); so_method(so, screen->tesla, 0x121c, 1); so_data (so, 1); @@ -290,27 +296,81 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) so_method(so, screen->tesla, 0x16b8, 1); so_data (so, 8); - /* Shared constant buffer */ - screen->constbuf = screen->pipe.buffer_create(&screen->pipe, 0, 0, 128 * 4 * 4); - if (nvws->res_init(&screen->vp_data_heap, 0, 128)) { - NOUVEAU_ERR("Error initialising constant buffer\n"); - nv50_screen_destroy(&screen->pipe); + /* constant buffers for immediates and VP/FP parameters */ + ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 128*4*4, + &screen->constbuf_misc[0]); + if (ret) { + nv50_screen_destroy(pscreen); + return NULL; + } + + for (i = 0; i < 2; i++) { + ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 128*4*4, + &screen->constbuf_parm[i]); + if (ret) { + nv50_screen_destroy(pscreen); + return NULL; + } + } + + if (nouveau_resource_init(&screen->immd_heap[0], 0, 128) || + nouveau_resource_init(&screen->parm_heap[0], 0, 128) || + nouveau_resource_init(&screen->parm_heap[1], 0, 128)) + { + NOUVEAU_ERR("Error initialising constant buffers.\n"); + nv50_screen_destroy(pscreen); return NULL; } + /* + // map constant buffers: + // B = buffer ID (maybe more than 1 byte) + // N = CB index used in shader instruction + // P = program type (0 = VP, 2 = GP, 3 = FP) + so_method(so, screen->tesla, 0x1694, 1); + so_data (so, 0x000BBNP1); + */ + + so_method(so, screen->tesla, 0x1280, 3); + so_reloc (so, screen->constbuf_misc[0], 0, NOUVEAU_BO_VRAM | + NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); + so_reloc (so, screen->constbuf_misc[0], 0, NOUVEAU_BO_VRAM | + NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); + so_data (so, (NV50_CB_PMISC << 16) | 0x00000800); + so_method(so, screen->tesla, 0x1694, 1); + so_data (so, 0x00000001 | (NV50_CB_PMISC << 12)); + so_method(so, screen->tesla, 0x1694, 1); + so_data (so, 0x00000031 | (NV50_CB_PMISC << 12)); + so_method(so, screen->tesla, 0x1280, 3); - so_reloc (so, screen->constbuf, 0, NOUVEAU_BO_VRAM | + so_reloc (so, screen->constbuf_parm[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); - so_reloc (so, screen->constbuf, 0, NOUVEAU_BO_VRAM | + so_reloc (so, screen->constbuf_parm[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); - so_data (so, (NV50_CB_PMISC << 16) | 0x00001000); + so_data (so, (NV50_CB_PVP << 16) | 0x00000800); + so_method(so, screen->tesla, 0x1694, 1); + so_data (so, 0x00000101 | (NV50_CB_PVP << 12)); + + so_method(so, screen->tesla, 0x1280, 3); + so_reloc (so, screen->constbuf_parm[1], 0, NOUVEAU_BO_VRAM | + NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); + so_reloc (so, screen->constbuf_parm[1], 0, NOUVEAU_BO_VRAM | + NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); + so_data (so, (NV50_CB_PFP << 16) | 0x00000800); + so_method(so, screen->tesla, 0x1694, 1); + so_data (so, 0x00000131 | (NV50_CB_PFP << 12)); /* Texture sampler/image unit setup - we abuse the constant buffer * upload mechanism for the moment to upload data to the tex config * blocks. At some point we *may* want to go the NVIDIA way of doing * things? */ - screen->tic = screen->pipe.buffer_create(&screen->pipe, 0, 0, 32 * 8 * 4); + ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 32*8*4, &screen->tic); + if (ret) { + nv50_screen_destroy(pscreen); + return NULL; + } + so_method(so, screen->tesla, 0x1280, 3); so_reloc (so, screen->tic, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); @@ -324,7 +384,12 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); so_data (so, 0x00000800); - screen->tsc = screen->pipe.buffer_create(&screen->pipe, 0, 0, 32 * 8 * 4); + ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, 32*8*4, &screen->tsc); + if (ret) { + nv50_screen_destroy(pscreen); + return NULL; + } + so_method(so, screen->tesla, 0x1280, 3); so_reloc (so, screen->tsc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); @@ -352,14 +417,16 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *nvws) so_method(so, screen->tesla, 0x1234, 1); so_data (so, 1); - so_method(so, screen->tesla, 0x1458, 1); + + /* activate first scissor rectangle */ + so_method(so, screen->tesla, NV50TCL_SCISSOR_ENABLE, 1); so_data (so, 1); - so_emit(nvws, so); + so_emit(chan, so); so_ref (so, &screen->static_init); so_ref (NULL, &so); - nvws->push_flush(nvws, 0, NULL); + nouveau_pushbuf_flush(chan, 0); - return &screen->pipe; + return pscreen; } diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index db567aaac89..61e24a5b571 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -1,10 +1,10 @@ #ifndef __NV50_SCREEN_H__ #define __NV50_SCREEN_H__ -#include "pipe/p_screen.h" +#include "nouveau/nouveau_screen.h" struct nv50_screen { - struct pipe_screen pipe; + struct nouveau_screen base; struct nouveau_winsys *nvws; @@ -15,11 +15,14 @@ struct nv50_screen { struct nouveau_grobj *m2mf; struct nouveau_notifier *sync; - struct pipe_buffer *constbuf; - struct nouveau_resource *vp_data_heap; + struct nouveau_bo *constbuf_misc[1]; + struct nouveau_bo *constbuf_parm[2]; - struct pipe_buffer *tic; - struct pipe_buffer *tsc; + struct nouveau_resource *immd_heap[1]; + struct nouveau_resource *parm_heap[2]; + + struct nouveau_bo *tic; + struct nouveau_bo *tsc; struct nouveau_stateobj *static_init; }; diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c index ba852194cdd..c93694c60f5 100644 --- a/src/gallium/drivers/nv50/nv50_state.c +++ b/src/gallium/drivers/nv50/nv50_state.c @@ -136,9 +136,11 @@ static void * nv50_sampler_state_create(struct pipe_context *pipe, const struct pipe_sampler_state *cso) { - unsigned *tsc = CALLOC(8, sizeof(unsigned)); + struct nv50_sampler_stateobj *sso = CALLOC(1, sizeof(*sso)); + unsigned *tsc = sso->tsc; + float limit; - tsc[0] = (0x00024000 | + tsc[0] = (0x00026000 | (wrap_mode(cso->wrap_s) << 0) | (wrap_mode(cso->wrap_t) << 3) | (wrap_mode(cso->wrap_r) << 6)); @@ -202,7 +204,19 @@ nv50_sampler_state_create(struct pipe_context *pipe, tsc[0] |= (nvgl_comparison_op(cso->compare_func) & 0x7); } - return (void *)tsc; + limit = CLAMP(cso->lod_bias, -16.0, 15.0); + tsc[1] |= ((int)(limit * 256.0) & 0x1fff) << 12; + + tsc[2] |= ((int)CLAMP(cso->max_lod, 0.0, 15.0) << 20) | + ((int)CLAMP(cso->min_lod, 0.0, 15.0) << 8); + + tsc[4] = fui(cso->border_color[0]); + tsc[5] = fui(cso->border_color[1]); + tsc[6] = fui(cso->border_color[2]); + tsc[7] = fui(cso->border_color[3]); + + sso->normalized = cso->normalized_coords; + return (void *)sso; } static void diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c index c13d3de1cb9..4a49b107a5c 100644 --- a/src/gallium/drivers/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -32,6 +32,9 @@ nv50_state_validate_fb(struct nv50_context *nv50) unsigned i, w, h, gw = 0; for (i = 0; i < fb->nr_cbufs; i++) { + struct pipe_texture *pt = fb->cbufs[i]->texture; + struct nouveau_bo *bo = nv50_miptree(pt)->bo; + if (!gw) { w = fb->cbufs[i]->width; h = fb->cbufs[i]->height; @@ -46,12 +49,10 @@ nv50_state_validate_fb(struct nv50_context *nv50) so_data (so, fb->cbufs[i]->height); so_method(so, tesla, NV50TCL_RT_ADDRESS_HIGH(i), 5); - so_reloc (so, nv50_surface_buffer(fb->cbufs[i]), fb->cbufs[i]->offset, - NOUVEAU_BO_VRAM | NOUVEAU_BO_HIGH | - NOUVEAU_BO_RDWR, 0, 0); - so_reloc (so, nv50_surface_buffer(fb->cbufs[i]), fb->cbufs[i]->offset, - NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW | - NOUVEAU_BO_RDWR, 0, 0); + so_reloc (so, bo, fb->cbufs[i]->offset, NOUVEAU_BO_VRAM | + NOUVEAU_BO_HIGH | NOUVEAU_BO_RDWR, 0, 0); + so_reloc (so, bo, fb->cbufs[i]->offset, NOUVEAU_BO_VRAM | + NOUVEAU_BO_LOW | NOUVEAU_BO_RDWR, 0, 0); switch (fb->cbufs[i]->format) { case PIPE_FORMAT_A8R8G8B8_UNORM: so_data(so, 0xcf); @@ -65,7 +66,7 @@ nv50_state_validate_fb(struct nv50_context *nv50) so_data(so, 0xe6); break; } - so_data(so, 0x00000000); + so_data(so, bo->tile_mode << 4); so_data(so, 0x00000000); so_method(so, tesla, 0x1224, 1); @@ -73,6 +74,9 @@ nv50_state_validate_fb(struct nv50_context *nv50) } if (fb->zsbuf) { + struct pipe_texture *pt = fb->zsbuf->texture; + struct nouveau_bo *bo = nv50_miptree(pt)->bo; + if (!gw) { w = fb->zsbuf->width; h = fb->zsbuf->height; @@ -83,26 +87,30 @@ nv50_state_validate_fb(struct nv50_context *nv50) } so_method(so, tesla, NV50TCL_ZETA_ADDRESS_HIGH, 5); - so_reloc (so, nv50_surface_buffer(fb->zsbuf), fb->zsbuf->offset, - NOUVEAU_BO_VRAM | NOUVEAU_BO_HIGH | - NOUVEAU_BO_RDWR, 0, 0); - so_reloc (so, nv50_surface_buffer(fb->zsbuf), fb->zsbuf->offset, - NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW | - NOUVEAU_BO_RDWR, 0, 0); + so_reloc (so, bo, fb->zsbuf->offset, NOUVEAU_BO_VRAM | + NOUVEAU_BO_HIGH | NOUVEAU_BO_RDWR, 0, 0); + so_reloc (so, bo, fb->zsbuf->offset, NOUVEAU_BO_VRAM | + NOUVEAU_BO_LOW | NOUVEAU_BO_RDWR, 0, 0); switch (fb->zsbuf->format) { + case PIPE_FORMAT_Z32_FLOAT: + so_data(so, NV50TCL_ZETA_FORMAT_Z32_FLOAT); + break; case PIPE_FORMAT_Z24S8_UNORM: - so_data(so, 0x16); + so_data(so, NV50TCL_ZETA_FORMAT_Z24S8_UNORM); + break; + case PIPE_FORMAT_X8Z24_UNORM: + so_data(so, NV50TCL_ZETA_FORMAT_X8Z24_UNORM); break; - case PIPE_FORMAT_Z16_UNORM: - so_data(so, 0x15); + case PIPE_FORMAT_S8Z24_UNORM: + so_data(so, NV50TCL_ZETA_FORMAT_S8Z24_UNORM); break; default: NOUVEAU_ERR("AIIII unknown format %s\n", pf_name(fb->zsbuf->format)); - so_data(so, 0x16); + so_data(so, NV50TCL_ZETA_FORMAT_S8Z24_UNORM); break; } - so_data(so, 0x00000000); + so_data(so, bo->tile_mode << 4); so_data(so, 0x00000000); so_method(so, tesla, 0x1538, 1); @@ -116,12 +124,18 @@ nv50_state_validate_fb(struct nv50_context *nv50) so_method(so, tesla, NV50TCL_VIEWPORT_HORIZ, 2); so_data (so, w << 16); so_data (so, h << 16); - so_method(so, tesla, 0x0e04, 2); + /* set window scissor rectangle to window extents */ + so_method(so, tesla, NV50TCL_SCISSOR_HORIZ, 2); so_data (so, w << 16); so_data (so, h << 16); - so_method(so, tesla, 0xdf8, 2); + /* set window lower left corner */ + so_method(so, tesla, NV50TCL_WINDOW_LEFT, 2); so_data (so, 0); so_data (so, h); + /* set screen scissor rectangle */ + so_method(so, tesla, NV50TCL_SCREEN_SCISSOR_HORIZ, 2); + so_data (so, w << 16); + so_data (so, h << 16); so_ref(so, &nv50->state.fb); so_ref(NULL, &so); @@ -131,7 +145,7 @@ static void nv50_state_emit(struct nv50_context *nv50) { struct nv50_screen *screen = nv50->screen; - struct nouveau_winsys *nvws = screen->nvws; + struct nouveau_channel *chan = screen->base.channel; if (nv50->pctx_id != screen->cur_pctx) { nv50->state.dirty |= 0xffffffff; @@ -139,40 +153,40 @@ nv50_state_emit(struct nv50_context *nv50) } if (nv50->state.dirty & NV50_NEW_FRAMEBUFFER) - so_emit(nvws, nv50->state.fb); + so_emit(chan, nv50->state.fb); if (nv50->state.dirty & NV50_NEW_BLEND) - so_emit(nvws, nv50->state.blend); + so_emit(chan, nv50->state.blend); if (nv50->state.dirty & NV50_NEW_ZSA) - so_emit(nvws, nv50->state.zsa); + so_emit(chan, nv50->state.zsa); if (nv50->state.dirty & NV50_NEW_VERTPROG) - so_emit(nvws, nv50->state.vertprog); + so_emit(chan, nv50->state.vertprog); if (nv50->state.dirty & NV50_NEW_FRAGPROG) - so_emit(nvws, nv50->state.fragprog); + so_emit(chan, nv50->state.fragprog); if (nv50->state.dirty & NV50_NEW_RASTERIZER) - so_emit(nvws, nv50->state.rast); + so_emit(chan, nv50->state.rast); if (nv50->state.dirty & NV50_NEW_BLEND_COLOUR) - so_emit(nvws, nv50->state.blend_colour); + so_emit(chan, nv50->state.blend_colour); if (nv50->state.dirty & NV50_NEW_STIPPLE) - so_emit(nvws, nv50->state.stipple); + so_emit(chan, nv50->state.stipple); if (nv50->state.dirty & NV50_NEW_SCISSOR) - so_emit(nvws, nv50->state.scissor); + so_emit(chan, nv50->state.scissor); if (nv50->state.dirty & NV50_NEW_VIEWPORT) - so_emit(nvws, nv50->state.viewport); + so_emit(chan, nv50->state.viewport); if (nv50->state.dirty & NV50_NEW_SAMPLER) - so_emit(nvws, nv50->state.tsc_upload); + so_emit(chan, nv50->state.tsc_upload); if (nv50->state.dirty & NV50_NEW_TEXTURE) - so_emit(nvws, nv50->state.tic_upload); + so_emit(chan, nv50->state.tic_upload); if (nv50->state.dirty & NV50_NEW_ARRAYS) { - so_emit(nvws, nv50->state.vtxfmt); - so_emit(nvws, nv50->state.vtxbuf); + so_emit(chan, nv50->state.vtxfmt); + so_emit(chan, nv50->state.vtxbuf); } nv50->state.dirty = 0; - so_emit_reloc_markers(nvws, nv50->state.fb); - so_emit_reloc_markers(nvws, nv50->state.vertprog); - so_emit_reloc_markers(nvws, nv50->state.fragprog); - so_emit_reloc_markers(nvws, nv50->state.vtxbuf); - so_emit_reloc_markers(nvws, nv50->screen->static_init); + so_emit_reloc_markers(chan, nv50->state.fb); + so_emit_reloc_markers(chan, nv50->state.vertprog); + so_emit_reloc_markers(chan, nv50->state.fragprog); + so_emit_reloc_markers(chan, nv50->state.vtxbuf); + so_emit_reloc_markers(chan, nv50->screen->static_init); } boolean @@ -230,13 +244,16 @@ nv50_state_validate(struct nv50_context *nv50) nv50->state.scissor_enabled = rast->scissor; so = so_new(3, 0); - so_method(so, tesla, 0x0ff4, 2); + so_method(so, tesla, NV50TCL_SCISSOR_HORIZ, 2); if (nv50->state.scissor_enabled) { - so_data(so, ((s->maxx - s->minx) << 16) | s->minx); - so_data(so, ((s->maxy - s->miny) << 16) | s->miny); + /* the hw has y = 0 = bottom here */ + unsigned top = nv50->framebuffer.height - s->miny; + unsigned bottom = nv50->framebuffer.height - s->maxy; + so_data(so, (s->maxx << 16) | s->minx); + so_data(so, (top << 16) | bottom); } else { - so_data(so, (8192 << 16)); - so_data(so, (8192 << 16)); + so_data(so, (nv50->framebuffer.width << 16)); + so_data(so, (nv50->framebuffer.height << 16)); } so_ref(so, &nv50->state.scissor); so_ref(NULL, &so); @@ -246,6 +263,7 @@ scissor_uptodate: if (nv50->dirty & (NV50_NEW_VIEWPORT | NV50_NEW_RASTERIZER)) { unsigned bypass; + float y_translate = (float)nv50->framebuffer.height; if (!nv50->rasterizer->pipe.bypass_vs_clip_and_viewport) bypass = 0; @@ -259,25 +277,33 @@ scissor_uptodate: nv50->state.viewport_bypass = bypass; so = so_new(12, 0); + so_method(so, tesla, NV50TCL_VIEW_VOLUME_CLIP_CTRL, 1); if (!bypass) { - so_method(so, tesla, NV50TCL_VIEWPORT_UNK1(0), 3); + so_data(so, 0x0000); + y_translate -= nv50->viewport.translate[1]; + so_method(so, tesla, NV50TCL_VIEWPORT_TRANSLATE(0), 3); so_data (so, fui(nv50->viewport.translate[0])); - so_data (so, fui(nv50->viewport.translate[1])); + so_data (so, fui(y_translate)); so_data (so, fui(nv50->viewport.translate[2])); - so_method(so, tesla, NV50TCL_VIEWPORT_UNK0(0), 3); + so_method(so, tesla, NV50TCL_VIEWPORT_SCALE(0), 3); so_data (so, fui(nv50->viewport.scale[0])); so_data (so, fui(-nv50->viewport.scale[1])); so_data (so, fui(nv50->viewport.scale[2])); - so_method(so, tesla, 0x192c, 1); - so_data (so, 1); - so_method(so, tesla, 0x0f90, 1); - so_data (so, 0); } else { - so_method(so, tesla, 0x192c, 1); - so_data (so, 0); - so_method(so, tesla, 0x0f90, 1); - so_data (so, 1); + /* don't do xy-clipping in NDC space */ + so_data(so, 0x0800); + /* in bypass mode, y = 0 would be bottom */ + so_method(so, tesla, NV50TCL_VIEWPORT_TRANSLATE(0), 3); + so_data (so, fui(0.0f)); + so_data (so, fui(y_translate)); + so_data (so, fui(0.0f)); + so_method(so, tesla, NV50TCL_VIEWPORT_SCALE(0), 3); + so_data (so, fui(1.0f)); + so_data (so, fui(-1.0f)); + so_data (so, fui(1.0f)); } + so_method(so, tesla, NV50TCL_VIEWPORT_TRANSFORM_EN, 1); + so_data (so, 1); so_ref(so, &nv50->state.viewport); so_ref(NULL, &so); @@ -293,12 +319,12 @@ viewport_uptodate: so_data (so, NV50_CB_TSC); so_method(so, tesla, 0x40000f04, nv50->sampler_nr * 8); for (i = 0; i < nv50->sampler_nr; i++) - so_datap (so, nv50->sampler[i], 8); + so_datap (so, nv50->sampler[i]->tsc, 8); so_ref(so, &nv50->state.tsc_upload); so_ref(NULL, &so); } - if (nv50->dirty & NV50_NEW_TEXTURE) + if (nv50->dirty & (NV50_NEW_TEXTURE | NV50_NEW_SAMPLER)) nv50_tex_validate(nv50); if (nv50->dirty & NV50_NEW_ARRAYS) diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c index 0cc5168144d..31c36a12b73 100644 --- a/src/gallium/drivers/nv50/nv50_surface.c +++ b/src/gallium/drivers/nv50/nv50_surface.c @@ -35,14 +35,13 @@ nv50_format(enum pipe_format format) { switch (format) { case PIPE_FORMAT_A8R8G8B8_UNORM: - case PIPE_FORMAT_Z24S8_UNORM: - return NV50_2D_DST_FORMAT_32BPP; + return NV50_2D_DST_FORMAT_A8R8G8B8_UNORM; case PIPE_FORMAT_X8R8G8B8_UNORM: - return NV50_2D_DST_FORMAT_24BPP; + return NV50_2D_DST_FORMAT_X8R8G8B8_UNORM; case PIPE_FORMAT_R5G6B5_UNORM: - return NV50_2D_DST_FORMAT_16BPP; + return NV50_2D_DST_FORMAT_R5G6B5_UNORM; case PIPE_FORMAT_A8_UNORM: - return NV50_2D_DST_FORMAT_8BPP; + return NV50_2D_DST_FORMAT_R8_UNORM; default: return -1; } @@ -52,21 +51,17 @@ static int nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst) { struct nv50_miptree *mt = nv50_miptree(ps->texture); - struct nouveau_channel *chan = screen->nvws->channel; + struct nouveau_channel *chan = screen->eng2d->channel; struct nouveau_grobj *eng2d = screen->eng2d; - struct nouveau_bo *bo; + struct nouveau_bo *bo = nv50_miptree(ps->texture)->bo; int format, mthd = dst ? NV50_2D_DST_FORMAT : NV50_2D_SRC_FORMAT; int flags = NOUVEAU_BO_VRAM | (dst ? NOUVEAU_BO_WR : NOUVEAU_BO_RD); - - bo = screen->nvws->get_bo(nv50_miptree(ps->texture)->buffer); - if (!bo) - return 1; format = nv50_format(ps->format); if (format < 0) return 1; - if (!bo->tiled) { + if (!bo->tile_flags) { BEGIN_RING(chan, eng2d, mthd, 2); OUT_RING (chan, format); OUT_RING (chan, 1); @@ -80,7 +75,7 @@ nv50_surface_set(struct nv50_screen *screen, struct pipe_surface *ps, int dst) BEGIN_RING(chan, eng2d, mthd, 5); OUT_RING (chan, format); OUT_RING (chan, 0); - OUT_RING (chan, 0); + OUT_RING (chan, bo->tile_mode << 4); OUT_RING (chan, 1); OUT_RING (chan, 0); BEGIN_RING(chan, eng2d, mthd + 0x18, 4); @@ -108,7 +103,7 @@ nv50_surface_do_copy(struct nv50_screen *screen, struct pipe_surface *dst, int dx, int dy, struct pipe_surface *src, int sx, int sy, int w, int h) { - struct nouveau_channel *chan = screen->nvws->channel; + struct nouveau_channel *chan = screen->eng2d->channel; struct nouveau_grobj *eng2d = screen->eng2d; int ret; @@ -165,7 +160,7 @@ nv50_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, { struct nv50_context *nv50 = (struct nv50_context *)pipe; struct nv50_screen *screen = nv50->screen; - struct nouveau_channel *chan = screen->nvws->channel; + struct nouveau_channel *chan = screen->eng2d->channel; struct nouveau_grobj *eng2d = screen->eng2d; int format, ret; diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c index 223c8a3a456..46c3073defb 100644 --- a/src/gallium/drivers/nv50/nv50_tex.c +++ b/src/gallium/drivers/nv50/nv50_tex.c @@ -26,35 +26,36 @@ #include "nouveau/nouveau_stateobj.h" static int -nv50_tex_construct(struct nouveau_stateobj *so, struct nv50_miptree *mt) +nv50_tex_construct(struct nv50_context *nv50, struct nouveau_stateobj *so, + struct nv50_miptree *mt, int unit) { switch (mt->base.format) { case PIPE_FORMAT_A8R8G8B8_UNORM: so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM | - NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM | + NV50TIC_0_0_MAPR_C2 | NV50TIC_0_0_TYPER_UNORM | NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM | - NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM | + NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM | NV50TIC_0_0_FMT_8_8_8_8); break; case PIPE_FORMAT_A1R5G5B5_UNORM: so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM | - NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM | + NV50TIC_0_0_MAPR_C2 | NV50TIC_0_0_TYPER_UNORM | NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM | - NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM | + NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM | NV50TIC_0_0_FMT_1_5_5_5); break; case PIPE_FORMAT_A4R4G4B4_UNORM: so_data(so, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM | - NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM | + NV50TIC_0_0_MAPR_C2 | NV50TIC_0_0_TYPER_UNORM | NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM | - NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM | + NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM | NV50TIC_0_0_FMT_4_4_4_4); break; case PIPE_FORMAT_R5G6B5_UNORM: so_data(so, NV50TIC_0_0_MAPA_ONE | NV50TIC_0_0_TYPEA_UNORM | - NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM | + NV50TIC_0_0_MAPR_C2 | NV50TIC_0_0_TYPER_UNORM | NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEG_UNORM | - NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEB_UNORM | + NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEB_UNORM | NV50TIC_0_0_FMT_5_6_5); break; case PIPE_FORMAT_L8_UNORM: @@ -117,15 +118,18 @@ nv50_tex_construct(struct nouveau_stateobj *so, struct nv50_miptree *mt) return 1; } - so_reloc(so, mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW | + so_reloc(so, mt->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, 0); - so_data (so, 0xd0005000); + if (nv50->sampler[unit]->normalized) + so_data (so, 0xd0005000 | mt->bo->tile_mode << 22); + else + so_data (so, 0x5001d000 | mt->bo->tile_mode << 22); so_data (so, 0x00300000); so_data (so, mt->base.width[0]); - so_data (so, (mt->base.depth[0] << 16) | mt->base.height[0]); + so_data (so, (mt->base.last_level << 28) | + (mt->base.depth[0] << 16) | mt->base.height[0]); so_data (so, 0x03000000); - so_reloc(so, mt->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_HIGH | - NOUVEAU_BO_RD, 0, 0); + so_data (so, mt->base.last_level << 4); return 0; } @@ -135,23 +139,35 @@ nv50_tex_validate(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; struct nouveau_stateobj *so; - int unit; + int unit, push; - so = so_new(nv50->miptree_nr * 8 + 3, nv50->miptree_nr * 2); + push = nv50->miptree_nr * 9 + 2; + push += MAX2(nv50->miptree_nr, nv50->state.miptree_nr) * 2; + + so = so_new(push, nv50->miptree_nr * 2); so_method(so, tesla, 0x0f00, 1); so_data (so, NV50_CB_TIC); - so_method(so, tesla, 0x40000f04, nv50->miptree_nr * 8); for (unit = 0; unit < nv50->miptree_nr; unit++) { struct nv50_miptree *mt = nv50->miptree[unit]; - if (nv50_tex_construct(so, mt)) { + so_method(so, tesla, 0x40000f04, 8); + if (nv50_tex_construct(nv50, so, mt, unit)) { NOUVEAU_ERR("failed tex validate\n"); so_ref(NULL, &so); return; } + + so_method(so, tesla, 0x1458, 1); + so_data (so, (unit << 9) | (unit << 1) | 1); + } + + for (; unit < nv50->state.miptree_nr; unit++) { + so_method(so, tesla, 0x1458, 1); + so_data (so, (unit << 1) | 0); } so_ref(so, &nv50->state.tic_upload); so_ref(NULL, &so); + nv50->state.miptree_nr = nv50->miptree_nr; } diff --git a/src/gallium/drivers/nv50/nv50_texture.h b/src/gallium/drivers/nv50/nv50_texture.h index aca622c73b1..207fb039f70 100644 --- a/src/gallium/drivers/nv50/nv50_texture.h +++ b/src/gallium/drivers/nv50/nv50_texture.h @@ -14,13 +14,13 @@ #define NV50TIC_0_0_MAPA_C2 0x20000000 #define NV50TIC_0_0_MAPA_C3 0x28000000 #define NV50TIC_0_0_MAPA_ONE 0x38000000 -#define NV50TIC_0_0_MAPR_MASK 0x07000000 -#define NV50TIC_0_0_MAPR_ZERO 0x00000000 -#define NV50TIC_0_0_MAPR_C0 0x02000000 -#define NV50TIC_0_0_MAPR_C1 0x03000000 -#define NV50TIC_0_0_MAPR_C2 0x04000000 -#define NV50TIC_0_0_MAPR_C3 0x05000000 -#define NV50TIC_0_0_MAPR_ONE 0x07000000 +#define NV50TIC_0_0_MAPB_MASK 0x07000000 +#define NV50TIC_0_0_MAPB_ZERO 0x00000000 +#define NV50TIC_0_0_MAPB_C0 0x02000000 +#define NV50TIC_0_0_MAPB_C1 0x03000000 +#define NV50TIC_0_0_MAPB_C2 0x04000000 +#define NV50TIC_0_0_MAPB_C3 0x05000000 +#define NV50TIC_0_0_MAPB_ONE 0x07000000 #define NV50TIC_0_0_MAPG_MASK 0x00e00000 #define NV50TIC_0_0_MAPG_ZERO 0x00000000 #define NV50TIC_0_0_MAPG_C0 0x00400000 @@ -28,31 +28,49 @@ #define NV50TIC_0_0_MAPG_C2 0x00800000 #define NV50TIC_0_0_MAPG_C3 0x00a00000 #define NV50TIC_0_0_MAPG_ONE 0x00e00000 -#define NV50TIC_0_0_MAPB_MASK 0x001c0000 -#define NV50TIC_0_0_MAPB_ZERO 0x00000000 -#define NV50TIC_0_0_MAPB_C0 0x00080000 -#define NV50TIC_0_0_MAPB_C1 0x000c0000 -#define NV50TIC_0_0_MAPB_C2 0x00100000 -#define NV50TIC_0_0_MAPB_C3 0x00140000 -#define NV50TIC_0_0_MAPB_ONE 0x001c0000 +#define NV50TIC_0_0_MAPR_MASK 0x001c0000 +#define NV50TIC_0_0_MAPR_ZERO 0x00000000 +#define NV50TIC_0_0_MAPR_C0 0x00080000 +#define NV50TIC_0_0_MAPR_C1 0x000c0000 +#define NV50TIC_0_0_MAPR_C2 0x00100000 +#define NV50TIC_0_0_MAPR_C3 0x00140000 +#define NV50TIC_0_0_MAPR_ONE 0x001c0000 #define NV50TIC_0_0_TYPEA_MASK 0x00038000 #define NV50TIC_0_0_TYPEA_UNORM 0x00010000 -#define NV50TIC_0_0_TYPER_MASK 0x00007000 -#define NV50TIC_0_0_TYPER_UNORM 0x00002000 +#define NV50TIC_0_0_TYPEA_SNORM 0x00008000 +#define NV50TIC_0_0_TYPEA_FLOAT 0x00038000 +#define NV50TIC_0_0_TYPEB_MASK 0x00007000 +#define NV50TIC_0_0_TYPEB_UNORM 0x00002000 +#define NV50TIC_0_0_TYPEB_SNORM 0x00001000 +#define NV50TIC_0_0_TYPEB_FLOAT 0x00007000 #define NV50TIC_0_0_TYPEG_MASK 0x00000e00 #define NV50TIC_0_0_TYPEG_UNORM 0x00000400 -#define NV50TIC_0_0_TYPEB_MASK 0x000001c0 -#define NV50TIC_0_0_TYPEB_UNORM 0x00000080 -#define NV50TIC_0_0_FMT_MASK 0x0000003c +#define NV50TIC_0_0_TYPEG_SNORM 0x00000200 +#define NV50TIC_0_0_TYPEG_FLOAT 0x00000e00 +#define NV50TIC_0_0_TYPER_MASK 0x000001c0 +#define NV50TIC_0_0_TYPER_UNORM 0x00000080 +#define NV50TIC_0_0_TYPER_SNORM 0x00000040 +#define NV50TIC_0_0_TYPER_FLOAT 0x000001c0 +#define NV50TIC_0_0_FMT_MASK 0x0000003f +#define NV50TIC_0_0_FMT_32_32_32_32 0x00000001 +#define NV50TIC_0_0_FMT_16_16_16_16 0x00000003 +#define NV50TIC_0_0_FMT_32_32 0x00000004 #define NV50TIC_0_0_FMT_8_8_8_8 0x00000008 +#define NV50TIC_0_0_FMT_2_10_10_10 0x00000009 +#define NV50TIC_0_0_FMT_32 0x0000000f #define NV50TIC_0_0_FMT_4_4_4_4 0x00000012 -#define NV50TIC_0_0_FMT_1_5_5_5 0x00000013 +/* #define NV50TIC_0_0_FMT_1_5_5_5 0x00000013 */ +#define NV50TIC_0_0_FMT_1_5_5_5 0x00000014 #define NV50TIC_0_0_FMT_5_6_5 0x00000015 #define NV50TIC_0_0_FMT_8_8 0x00000018 +#define NV50TIC_0_0_FMT_16 0x0000001b #define NV50TIC_0_0_FMT_8 0x0000001d +#define NV50TIC_0_0_FMT_10_11_11 0x00000021 #define NV50TIC_0_0_FMT_DXT1 0x00000024 #define NV50TIC_0_0_FMT_DXT3 0x00000025 #define NV50TIC_0_0_FMT_DXT5 0x00000026 +#define NV50TIC_0_0_FMT_RGTC1 0x00000027 +#define NV50TIC_0_0_FMT_RGTC2 0x00000028 #define NV50TIC_0_1_OFFSET_LOW_MASK 0xffffffff #define NV50TIC_0_1_OFFSET_LOW_SHIFT 0 @@ -102,6 +120,7 @@ #define NV50TSC_1_0_WRAPR_MIRROR_CLAMP_TO_EDGE 0x00000140 #define NV50TSC_1_0_WRAPR_MIRROR_CLAMP_TO_BORDER 0x00000180 #define NV50TSC_1_0_WRAPR_MIRROR_CLAMP 0x000001c0 +#define NV50TSC_1_0_MAX_ANISOTROPY_MASK 0x00700000 #define NV50TSC_1_1_MAGF_MASK 0x00000003 #define NV50TSC_1_1_MAGF_NEAREST 0x00000001 @@ -113,17 +132,19 @@ #define NV50TSC_1_1_MIPF_NONE 0x00000040 #define NV50TSC_1_1_MIPF_NEAREST 0x00000080 #define NV50TSC_1_1_MIPF_LINEAR 0x000000c0 +#define NV50TSC_1_1_LOD_BIAS_MASK 0x01fff000 -#define NV50TSC_1_2_UNKNOWN_MASK 0xffffffff +#define NV50TSC_1_2_MIN_LOD_MASK 0x00000f00 +#define NV50TSC_1_2_MAX_LOD_MASK 0x00f00000 #define NV50TSC_1_3_UNKNOWN_MASK 0xffffffff -#define NV50TSC_1_4_UNKNOWN_MASK 0xffffffff +#define NV50TSC_1_4_BORDER_COLOR_RED_MASK 0xffffffff -#define NV50TSC_1_5_UNKNOWN_MASK 0xffffffff +#define NV50TSC_1_5_BORDER_COLOR_GREEN_MASK 0xffffffff -#define NV50TSC_1_6_UNKNOWN_MASK 0xffffffff +#define NV50TSC_1_6_BORDER_COLOR_BLUE_MASK 0xffffffff -#define NV50TSC_1_7_UNKNOWN_MASK 0xffffffff +#define NV50TSC_1_7_BORDER_COLOR_ALPHA_MASK 0xffffffff #endif diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c index 747195b4f63..6ff375951e4 100644 --- a/src/gallium/drivers/nv50/nv50_transfer.c +++ b/src/gallium/drivers/nv50/nv50_transfer.c @@ -6,8 +6,8 @@ struct nv50_transfer { struct pipe_transfer base; - struct pipe_buffer *buffer; - struct nv50_miptree_level *level; + struct nouveau_bo *bo; + unsigned level_offset; int level_pitch; int level_width; int level_height; @@ -16,51 +16,48 @@ struct nv50_transfer { }; static void -nv50_transfer_rect_m2mf(struct pipe_screen *pscreen, struct pipe_buffer *src, - int src_pitch, int sx, int sy, int sw, int sh, - struct pipe_buffer *dst, int dst_pitch, int dx, int dy, +nv50_transfer_rect_m2mf(struct pipe_screen *pscreen, struct nouveau_bo *src_bo, + unsigned src_offset, int src_pitch, int sx, int sy, + int sw, int sh, struct nouveau_bo *dst_bo, + unsigned dst_offset, int dst_pitch, int dx, int dy, int dw, int dh, int cpp, int width, int height, unsigned src_reloc, unsigned dst_reloc) { struct nv50_screen *screen = nv50_screen(pscreen); - struct nouveau_winsys *nvws = screen->nvws; - struct nouveau_channel *chan = nvws->channel; + struct nouveau_channel *chan = screen->m2mf->channel; struct nouveau_grobj *m2mf = screen->m2mf; - struct nouveau_bo *src_bo = nvws->get_bo(src); - struct nouveau_bo *dst_bo = nvws->get_bo(dst); - unsigned src_offset = 0, dst_offset = 0; src_reloc |= NOUVEAU_BO_RD; dst_reloc |= NOUVEAU_BO_WR; WAIT_RING (chan, 14); - if (!src_bo->tiled) { + if (!src_bo->tile_flags) { BEGIN_RING(chan, m2mf, 0x0200, 1); OUT_RING (chan, 1); BEGIN_RING(chan, m2mf, 0x0314, 1); OUT_RING (chan, src_pitch); - src_offset = (sy * src_pitch) + (sx * cpp); + src_offset += (sy * src_pitch) + (sx * cpp); } else { BEGIN_RING(chan, m2mf, 0x0200, 6); OUT_RING (chan, 0); - OUT_RING (chan, 0); + OUT_RING (chan, src_bo->tile_mode << 4); OUT_RING (chan, sw * cpp); OUT_RING (chan, sh); OUT_RING (chan, 1); OUT_RING (chan, 0); } - if (!dst_bo->tiled) { + if (!dst_bo->tile_flags) { BEGIN_RING(chan, m2mf, 0x021c, 1); OUT_RING (chan, 1); BEGIN_RING(chan, m2mf, 0x0318, 1); OUT_RING (chan, dst_pitch); - dst_offset = (dy * dst_pitch) + (dx * cpp); + dst_offset += (dy * dst_pitch) + (dx * cpp); } else { BEGIN_RING(chan, m2mf, 0x021c, 6); OUT_RING (chan, 0); - OUT_RING (chan, 0); + OUT_RING (chan, dst_bo->tile_mode << 4); OUT_RING (chan, dw * cpp); OUT_RING (chan, dh); OUT_RING (chan, 1); @@ -77,15 +74,15 @@ nv50_transfer_rect_m2mf(struct pipe_screen *pscreen, struct pipe_buffer *src, BEGIN_RING(chan, m2mf, 0x030c, 2); OUT_RELOCl(chan, src_bo, src_offset, src_reloc); OUT_RELOCl(chan, dst_bo, dst_offset, dst_reloc); - if (src_bo->tiled) { + if (src_bo->tile_flags) { BEGIN_RING(chan, m2mf, 0x0218, 1); - OUT_RING (chan, (dy << 16) | sx); + OUT_RING (chan, (sy << 16) | sx); } else { src_offset += (line_count * src_pitch); } - if (dst_bo->tiled) { + if (dst_bo->tile_flags) { BEGIN_RING(chan, m2mf, 0x0234, 1); - OUT_RING (chan, (sy << 16) | dx); + OUT_RING (chan, (dy << 16) | dx); } else { dst_offset += (line_count * dst_pitch); } @@ -108,10 +105,12 @@ nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, enum pipe_transfer_usage usage, unsigned x, unsigned y, unsigned w, unsigned h) { + struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct nv50_miptree *mt = nv50_miptree(pt); struct nv50_miptree_level *lvl = &mt->level[level]; struct nv50_transfer *tx; unsigned image = 0; + int ret; if (pt->target == PIPE_TEXTURE_CUBE) image = face; @@ -133,20 +132,24 @@ nv50_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, tx->base.stride = (w * pt->block.size); tx->base.usage = usage; - tx->level = lvl; tx->level_pitch = lvl->pitch; tx->level_width = mt->base.width[level]; tx->level_height = mt->base.height[level]; + tx->level_offset = lvl->image_offset[image]; tx->level_x = x; tx->level_y = y; - tx->buffer = - pipe_buffer_create(pscreen, 0, NOUVEAU_BUFFER_USAGE_TRANSFER, - w * tx->base.block.size * h); + ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, + w * pt->block.size * h, &tx->bo); + if (ret) { + FREE(tx); + return NULL; + } if (usage != PIPE_TRANSFER_WRITE) { - nv50_transfer_rect_m2mf(pscreen, mt->buffer, tx->level_pitch, - x, y, tx->level_width, tx->level_height, - tx->buffer, tx->base.stride, 0, 0, + nv50_transfer_rect_m2mf(pscreen, mt->bo, tx->level_offset, + tx->level_pitch, x, y, tx->level_width, + tx->level_height, tx->bo, 0, + tx->base.stride, 0, 0, tx->base.width, tx->base.height, tx->base.block.size, w, h, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART, @@ -164,17 +167,18 @@ nv50_transfer_del(struct pipe_transfer *ptx) if (ptx->usage != PIPE_TRANSFER_READ) { struct pipe_screen *pscreen = ptx->texture->screen; - nv50_transfer_rect_m2mf(pscreen, tx->buffer, tx->base.stride, + nv50_transfer_rect_m2mf(pscreen, tx->bo, 0, tx->base.stride, 0, 0, tx->base.width, tx->base.height, - mt->buffer, tx->level_pitch, - tx->level_x, tx->level_y, - tx->level_width, tx->level_height, - tx->base.block.size, tx->base.width, - tx->base.height, NOUVEAU_BO_GART, - NOUVEAU_BO_VRAM | NOUVEAU_BO_GART); + mt->bo, tx->level_offset, + tx->level_pitch, tx->level_x, + tx->level_y, tx->level_width, + tx->level_height, tx->base.block.size, + tx->base.width, tx->base.height, + NOUVEAU_BO_GART, NOUVEAU_BO_VRAM | + NOUVEAU_BO_GART); } - pipe_buffer_reference(&tx->buffer, NULL); + nouveau_bo_ref(NULL, &tx->bo); pipe_texture_reference(&ptx->texture, NULL); FREE(ptx); } @@ -184,13 +188,17 @@ nv50_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) { struct nv50_transfer *tx = (struct nv50_transfer *)ptx; unsigned flags = 0; + int ret; if (ptx->usage & PIPE_TRANSFER_WRITE) - flags |= PIPE_BUFFER_USAGE_CPU_WRITE; + flags |= NOUVEAU_BO_WR; if (ptx->usage & PIPE_TRANSFER_READ) - flags |= PIPE_BUFFER_USAGE_CPU_READ; + flags |= NOUVEAU_BO_RD; - return pipe_buffer_map(pscreen, tx->buffer, flags); + ret = nouveau_bo_map(tx->bo, flags); + if (ret) + return NULL; + return tx->bo->map; } static void @@ -198,7 +206,7 @@ nv50_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) { struct nv50_transfer *tx = (struct nv50_transfer *)ptx; - pipe_buffer_unmap(pscreen, tx->buffer); + nouveau_bo_unmap(tx->bo); } void diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c index 0749c906914..422c8c6b5b0 100644 --- a/src/gallium/drivers/nv50/nv50_vbo.c +++ b/src/gallium/drivers/nv50/nv50_vbo.c @@ -22,6 +22,7 @@ #include "pipe/p_context.h" #include "pipe/p_state.h" +#include "pipe/p_inlines.h" #include "nv50_context.h" @@ -48,12 +49,63 @@ nv50_prim(unsigned mode) return NV50TCL_VERTEX_BEGIN_POINTS; } +static INLINE unsigned +nv50_vtxeltfmt(unsigned pf) +{ + static const uint8_t vtxelt_32[4] = { 0x90, 0x20, 0x10, 0x08 }; + static const uint8_t vtxelt_16[4] = { 0xd8, 0x78, 0x28, 0x18 }; + static const uint8_t vtxelt_08[4] = { 0xe8, 0xc0, 0x98, 0x50 }; + + unsigned nf, c = 0; + + switch (pf_type(pf)) { + case PIPE_FORMAT_TYPE_FLOAT: + nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_FLOAT; break; + case PIPE_FORMAT_TYPE_UNORM: + nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_UNORM; break; + case PIPE_FORMAT_TYPE_SNORM: + nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SNORM; break; + case PIPE_FORMAT_TYPE_USCALED: + nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_USCALED; break; + case PIPE_FORMAT_TYPE_SSCALED: + nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_SSCALED; break; + default: + NOUVEAU_ERR("invalid vbo type %d\n",pf_type(pf)); + assert(0); + nf = NV50TCL_VERTEX_ARRAY_ATTRIB_TYPE_FLOAT; + break; + } + + if (pf_size_y(pf)) c++; + if (pf_size_z(pf)) c++; + if (pf_size_w(pf)) c++; + + if (pf_exp2(pf) == 3) { + switch (pf_size_x(pf)) { + case 1: return (nf | (vtxelt_08[c] << 16)); + case 2: return (nf | (vtxelt_16[c] << 16)); + case 4: return (nf | (vtxelt_32[c] << 16)); + default: + break; + } + } else + if (pf_exp2(pf) == 6 && pf_size_x(pf) == 1) { + NOUVEAU_ERR("unsupported vbo component size 64\n"); + assert(0); + return (nf | 0x08000000); + } + + NOUVEAU_ERR("invalid vbo format %s\n",pf_name(pf)); + assert(0); + return (nf | 0x08000000); +} + boolean nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { struct nv50_context *nv50 = nv50_context(pipe); - struct nouveau_channel *chan = nv50->screen->nvws->channel; + struct nouveau_channel *chan = nv50->screen->tesla->channel; struct nouveau_grobj *tesla = nv50->screen->tesla; nv50_state_validate(nv50); @@ -83,7 +135,7 @@ static INLINE void nv50_draw_elements_inline_u08(struct nv50_context *nv50, uint8_t *map, unsigned start, unsigned count) { - struct nouveau_channel *chan = nv50->screen->nvws->channel; + struct nouveau_channel *chan = nv50->screen->tesla->channel; struct nouveau_grobj *tesla = nv50->screen->tesla; map += start; @@ -112,7 +164,7 @@ static INLINE void nv50_draw_elements_inline_u16(struct nv50_context *nv50, uint16_t *map, unsigned start, unsigned count) { - struct nouveau_channel *chan = nv50->screen->nvws->channel; + struct nouveau_channel *chan = nv50->screen->tesla->channel; struct nouveau_grobj *tesla = nv50->screen->tesla; map += start; @@ -138,10 +190,10 @@ nv50_draw_elements_inline_u16(struct nv50_context *nv50, uint16_t *map, } static INLINE void -nv50_draw_elements_inline_u32(struct nv50_context *nv50, uint8_t *map, +nv50_draw_elements_inline_u32(struct nv50_context *nv50, uint32_t *map, unsigned start, unsigned count) { - struct nouveau_channel *chan = nv50->screen->nvws->channel; + struct nouveau_channel *chan = nv50->screen->tesla->channel; struct nouveau_grobj *tesla = nv50->screen->tesla; map += start; @@ -163,10 +215,12 @@ nv50_draw_elements(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { struct nv50_context *nv50 = nv50_context(pipe); - struct nouveau_channel *chan = nv50->screen->nvws->channel; + struct nouveau_channel *chan = nv50->screen->tesla->channel; struct nouveau_grobj *tesla = nv50->screen->tesla; - struct pipe_winsys *ws = pipe->winsys; - void *map = ws->buffer_map(ws, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); + struct pipe_screen *pscreen = pipe->screen; + void *map; + + map = pipe_buffer_map(pscreen, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); nv50_state_validate(nv50); @@ -193,6 +247,7 @@ nv50_draw_elements(struct pipe_context *pipe, BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); OUT_RING (chan, 0); + pipe_buffer_unmap(pscreen, indexBuffer); pipe->flush(pipe, 0, NULL); return TRUE; } @@ -204,6 +259,10 @@ nv50_vbo_validate(struct nv50_context *nv50) struct nouveau_stateobj *vtxbuf, *vtxfmt; int i; + /* don't validate if Gallium took away our buffers */ + if (nv50->vtxbuf_nr == 0) + return; + vtxbuf = so_new(nv50->vtxelt_nr * 4, nv50->vtxelt_nr * 2); vtxfmt = so_new(nv50->vtxelt_nr + 1, 0); so_method(vtxfmt, tesla, 0x1ac0, nv50->vtxelt_nr); @@ -212,38 +271,16 @@ nv50_vbo_validate(struct nv50_context *nv50) struct pipe_vertex_element *ve = &nv50->vtxelt[i]; struct pipe_vertex_buffer *vb = &nv50->vtxbuf[ve->vertex_buffer_index]; + struct nouveau_bo *bo = nouveau_bo(vb->buffer); - switch (ve->src_format) { - case PIPE_FORMAT_R32G32B32A32_FLOAT: - so_data(vtxfmt, 0x7e080000 | i); - break; - case PIPE_FORMAT_R32G32B32_FLOAT: - so_data(vtxfmt, 0x7e100000 | i); - break; - case PIPE_FORMAT_R32G32_FLOAT: - so_data(vtxfmt, 0x7e200000 | i); - break; - case PIPE_FORMAT_R32_FLOAT: - so_data(vtxfmt, 0x7e900000 | i); - break; - case PIPE_FORMAT_R8G8B8A8_UNORM: - so_data(vtxfmt, 0x24500000 | i); - break; - default: - { - NOUVEAU_ERR("invalid vbo format %s\n", - pf_name(ve->src_format)); - assert(0); - return; - } - } + so_data(vtxfmt, nv50_vtxeltfmt(ve->src_format) | i); so_method(vtxbuf, tesla, 0x900 + (i * 16), 3); so_data (vtxbuf, 0x20000000 | vb->stride); - so_reloc (vtxbuf, vb->buffer, vb->buffer_offset + + so_reloc (vtxbuf, bo, vb->buffer_offset + ve->src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); - so_reloc (vtxbuf, vb->buffer, vb->buffer_offset + + so_reloc (vtxbuf, bo, vb->buffer_offset + ve->src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); } diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile index e44f9b9dfc5..faceec9842f 100644 --- a/src/gallium/drivers/r300/Makefile +++ b/src/gallium/drivers/r300/Makefile @@ -4,20 +4,22 @@ include $(TOP)/configs/current LIBNAME = r300 C_SOURCES = \ + r3xx_fs.c \ + r5xx_fs.c \ r300_chipset.c \ r300_clear.c \ r300_context.c \ r300_debug.c \ r300_emit.c \ r300_flush.c \ + r300_fs.c \ r300_query.c \ r300_render.c \ r300_screen.c \ r300_state.c \ r300_state_derived.c \ r300_state_invariant.c \ - r300_state_shader.c \ - r300_state_tcl.c \ + r300_vs.c \ r300_surface.c \ r300_texture.c diff --git a/src/gallium/drivers/r300/SConscript b/src/gallium/drivers/r300/SConscript index 182ed2d459a..493d7b28bc3 100644 --- a/src/gallium/drivers/r300/SConscript +++ b/src/gallium/drivers/r300/SConscript @@ -5,20 +5,22 @@ env = env.Clone() r300 = env.ConvenienceLibrary( target = 'r300', source = [ + 'r3xx_fs.c', + 'r5xx_fs.c', 'r300_chipset.c', 'r300_clear.c', 'r300_context.c', 'r300_debug.c', 'r300_emit.c', 'r300_flush.c', + 'r300_fs.c', 'r300_query.c', 'r300_render.c', 'r300_screen.c', 'r300_state.c', 'r300_state_derived.c', 'r300_state_invariant.c', - 'r300_state_shader.c', - 'r300_state_tcl.c', + 'r300_vs.c', 'r300_surface.c', 'r300_texture.c', ]) diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c index 9d95ad918c2..00fae8d26f3 100644 --- a/src/gallium/drivers/r300/r300_chipset.c +++ b/src/gallium/drivers/r300/r300_chipset.c @@ -34,7 +34,6 @@ void r300_parse_chipset(struct r300_capabilities* caps) caps->is_r500 = FALSE; caps->num_vert_fpus = 4; - /* Note: These are not ordered by PCI ID. I leave that task to GCC, * which will perform the ordering while collating jump tables. Instead, * I've tried to group them according to capabilities and age. */ @@ -150,6 +149,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) caps->num_vert_fpus = 6; break; + case 0x4B48: case 0x4B49: case 0x4B4A: case 0x4B4B: @@ -349,7 +349,4 @@ void r300_parse_chipset(struct r300_capabilities* caps) caps->pci_id); break; } - - /* XXX SW TCL is broken so no forcing it off right now - caps->has_tcl = FALSE; */ } diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h index 21eebeae600..5b2e1f05688 100644 --- a/src/gallium/drivers/r300/r300_chipset.h +++ b/src/gallium/drivers/r300/r300_chipset.h @@ -34,8 +34,6 @@ struct r300_capabilities { int family; /* The number of vertex floating-point units */ int num_vert_fpus; - /* The number of fragment pipes */ - int num_frag_pipes; /* Whether or not TCL is physically present */ boolean has_tcl; /* Whether or not this is an RV515 or newer; R500s have many differences diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 6bdf544a05c..233a32b53c5 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -34,10 +34,6 @@ static boolean r300_draw_range_elements(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); int i; - if (r300->dirty_state) { - r300_emit_dirty_state(r300); - } - for (i = 0; i < r300->vertex_buffer_count; i++) { void* buf = pipe_buffer_map(pipe->screen, r300->vertex_buffers[i].buffer, @@ -133,7 +129,6 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, if (!r300) return NULL; - /* XXX this could be refactored now? */ r300->winsys = r300_winsys; r300->context.winsys = (struct pipe_winsys*)r300_winsys; @@ -150,8 +145,15 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300->context.is_texture_referenced = r300_is_texture_referenced; r300->context.is_buffer_referenced = r300_is_buffer_referenced; + /* Create a Draw. This is used for vert collation and SW TCL. */ r300->draw = draw_create(); + /* Enable our renderer. */ draw_set_rasterize_stage(r300->draw, r300_draw_stage(r300)); + /* Disable Draw's clipping if TCL is present. */ + draw_set_driver_clipping(r300->draw, r300_screen(screen)->caps->has_tcl); + /* Force Draw to never do viewport transform, since (again) we can do + * transform in hardware, always. */ + draw_set_viewport_state(r300->draw, &r300_viewport_identity); r300->blend_color_state = CALLOC_STRUCT(r300_blend_color_state); r300->rs_block = CALLOC_STRUCT(r300_rs_block); diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 6f62998b35d..d891fd6265f 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -63,6 +63,11 @@ struct r300_rs_state { /* Draw-specific rasterizer state */ struct pipe_rasterizer_state rs; + /* Whether or not to enable the VTE. This is referenced at the very + * last moment during emission of VTE state, to decide whether or not + * the VTE should be used for transformation. */ + boolean enable_vte; + uint32_t vap_control_status; /* R300_VAP_CNTL_STATUS: 0x2140 */ uint32_t point_size; /* R300_GA_POINT_SIZE: 0x421c */ uint32_t point_minmax; /* R300_GA_POINT_MINMAX: 0x4230 */ @@ -112,23 +117,24 @@ struct r300_viewport_state { uint32_t vte_control; /* R300_VAP_VTE_CNTL: 0x20b0 */ }; -#define R300_NEW_BLEND 0x0000001 -#define R300_NEW_BLEND_COLOR 0x0000002 -#define R300_NEW_CONSTANTS 0x0000004 -#define R300_NEW_DSA 0x0000008 -#define R300_NEW_FRAMEBUFFERS 0x0000010 -#define R300_NEW_FRAGMENT_SHADER 0x0000020 -#define R300_NEW_RASTERIZER 0x0000040 -#define R300_NEW_RS_BLOCK 0x0000080 -#define R300_NEW_SAMPLER 0x0000100 -#define R300_ANY_NEW_SAMPLERS 0x000ff00 -#define R300_NEW_SCISSOR 0x0010000 -#define R300_NEW_TEXTURE 0x0020000 -#define R300_ANY_NEW_TEXTURES 0x1fe0000 -#define R300_NEW_VERTEX_FORMAT 0x2000000 -#define R300_NEW_VERTEX_SHADER 0x4000000 -#define R300_NEW_VIEWPORT 0x8000000 -#define R300_NEW_KITCHEN_SINK 0xfffffff +#define R300_NEW_BLEND 0x00000001 +#define R300_NEW_BLEND_COLOR 0x00000002 +#define R300_NEW_CLIP 0x00000004 +#define R300_NEW_CONSTANTS 0x00000008 +#define R300_NEW_DSA 0x00000010 +#define R300_NEW_FRAMEBUFFERS 0x00000020 +#define R300_NEW_FRAGMENT_SHADER 0x00000040 +#define R300_NEW_RASTERIZER 0x00000080 +#define R300_NEW_RS_BLOCK 0x00000100 +#define R300_NEW_SAMPLER 0x00000200 +#define R300_ANY_NEW_SAMPLERS 0x0001fe00 +#define R300_NEW_SCISSOR 0x00020000 +#define R300_NEW_TEXTURE 0x00040000 +#define R300_ANY_NEW_TEXTURES 0x03fc0000 +#define R300_NEW_VERTEX_FORMAT 0x04000000 +#define R300_NEW_VERTEX_SHADER 0x08000000 +#define R300_NEW_VIEWPORT 0x10000000 +#define R300_NEW_KITCHEN_SINK 0x1fffffff /* The next several objects are not pure Radeon state; they inherit from * various Gallium classes. */ @@ -136,14 +142,14 @@ struct r300_viewport_state { struct r300_constant_buffer { /* Buffer of constants */ /* XXX first number should be raised */ - float constants[8][4]; + float constants[32][4]; /* Number of user-defined constants */ - int user_count; + unsigned user_count; /* Total number of constants */ - int count; + unsigned count; }; -struct r3xx_fragment_shader { +struct r300_fragment_shader { /* Parent class */ struct pipe_shader_state state; struct tgsi_shader_info info; @@ -153,11 +159,15 @@ struct r3xx_fragment_shader { /* Pixel stack size */ int stack_size; + + /* Are there immediates in this shader? + * If not, we can heavily optimize recompilation. */ + boolean uses_imms; }; -struct r300_fragment_shader { +struct r3xx_fragment_shader { /* Parent class */ - struct r3xx_fragment_shader shader; + struct r300_fragment_shader shader; /* Number of ALU instructions */ int alu_instruction_count; @@ -180,9 +190,9 @@ struct r300_fragment_shader { } instructions[64]; /* XXX magic num */ }; -struct r500_fragment_shader { +struct r5xx_fragment_shader { /* Parent class */ - struct r3xx_fragment_shader shader; + struct r300_fragment_shader shader; /* Number of used instructions */ int instruction_count; @@ -207,7 +217,7 @@ struct r300_texture { /* Stride (pitch?) of this texture in bytes */ unsigned stride; - + /* Total size of this texture, in bytes. */ unsigned size; @@ -243,6 +253,10 @@ struct r300_vertex_shader { /* Has this shader been translated yet? */ boolean translated; + /* Are there immediates in this shader? + * If not, we can heavily optimize recompilation. */ + boolean uses_imms; + /* Number of used instructions */ int instruction_count; @@ -255,6 +269,11 @@ struct r300_vertex_shader { } instructions[128]; /*< XXX magic number */ }; +static struct pipe_viewport_state r300_viewport_identity = { + .scale = {1.0, 1.0, 1.0, 1.0}, + .translate = {0.0, 0.0, 0.0, 0.0}, +}; + struct r300_context { /* Parent class */ struct pipe_context context; @@ -264,17 +283,24 @@ struct r300_context { /* Draw module. Used mostly for SW TCL. */ struct draw_context* draw; + /* Vertex buffer for rendering. */ + struct pipe_buffer* vbo; + /* Offset into the VBO. */ + size_t vbo_offset; + /* Various CSO state objects. */ /* Blend state. */ struct r300_blend_state* blend_state; /* Blend color state. */ struct r300_blend_color_state* blend_color_state; + /* User clip planes. */ + struct pipe_clip_state clip_state; /* Shader constants. */ struct r300_constant_buffer shader_constants[PIPE_SHADER_TYPES]; /* Depth, stencil, and alpha state. */ struct r300_dsa_state* dsa_state; /* Fragment shader. */ - struct r3xx_fragment_shader* fs; + struct r300_fragment_shader* fs; /* Framebuffer state. We currently don't need our own version of this. */ struct pipe_framebuffer_state framebuffer_state; /* Rasterizer state. */ @@ -289,7 +315,7 @@ struct r300_context { /* Texture states. */ struct r300_texture* textures[8]; int texture_count; - /* Vertex buffers. */ + /* Vertex buffers for Gallium. */ struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; int vertex_buffer_count; /* Vertex information. */ @@ -305,7 +331,8 @@ struct r300_context { }; /* Convenience cast wrapper. */ -static struct r300_context* r300_context(struct pipe_context* context) { +static INLINE struct r300_context* r300_context(struct pipe_context* context) +{ return (struct r300_context*)context; } diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h index 82a3942248e..71b142c0dbf 100644 --- a/src/gallium/drivers/r300/r300_cs.h +++ b/src/gallium/drivers/r300/r300_cs.h @@ -34,6 +34,7 @@ #define MAX_CS_SIZE 64 * 1024 / 4 +#define VERY_VERBOSE_CS 0 #define VERY_VERBOSE_REGISTERS 0 /* XXX stolen from radeon_drm.h */ @@ -56,8 +57,10 @@ #define BEGIN_CS(size) do { \ CHECK_CS(size); \ - debug_printf("r300: BEGIN_CS, count %d, in %s (%s:%d)\n", \ - size, __FUNCTION__, __FILE__, __LINE__); \ + if (VERY_VERBOSE_CS) { \ + debug_printf("r300: BEGIN_CS, count %d, in %s (%s:%d)\n", \ + size, __FUNCTION__, __FILE__, __LINE__); \ + } \ cs_winsys->begin_cs(cs_winsys, (size), \ __FILE__, __FUNCTION__, __LINE__); \ cs_count = size; \ @@ -93,8 +96,9 @@ } while (0) #define OUT_CS_RELOC(bo, offset, rd, wd, flags) do { \ - debug_printf("r300: writing relocation for buffer %p, offset %d\n", \ - bo, offset); \ + debug_printf("r300: writing relocation for buffer %p, offset %d, " \ + "domains (%d, %d, %d)\n", \ + bo, offset, rd, wd, flags); \ assert(bo); \ OUT_CS(offset); \ cs_winsys->write_cs_reloc(cs_winsys, bo, rd, wd, flags); \ @@ -102,16 +106,20 @@ } while (0) #define END_CS do { \ - debug_printf("r300: END_CS in %s (%s:%d)\n", __FUNCTION__, __FILE__, \ - __LINE__); \ + if (VERY_VERBOSE_CS) { \ + debug_printf("r300: END_CS in %s (%s:%d)\n", __FUNCTION__, \ + __FILE__, __LINE__); \ + } \ if (cs_count != 0) \ debug_printf("r300: Warning: cs_count off by %d\n", cs_count); \ cs_winsys->end_cs(cs_winsys, __FILE__, __FUNCTION__, __LINE__); \ } while (0) #define FLUSH_CS do { \ - debug_printf("r300: FLUSH_CS in %s (%s:%d)\n\n", __FUNCTION__, __FILE__, \ - __LINE__); \ + if (VERY_VERBOSE_CS) { \ + debug_printf("r300: FLUSH_CS in %s (%s:%d)\n\n", __FUNCTION__, \ + __FILE__, __LINE__); \ + } \ cs_winsys->flush_cs(cs_winsys); \ } while (0) diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c index dd63136c9d6..c83e8526cf7 100644 --- a/src/gallium/drivers/r300/r300_debug.c +++ b/src/gallium/drivers/r300/r300_debug.c @@ -22,7 +22,7 @@ #include "r300_debug.h" -static void r300_dump_fs(struct r300_fragment_shader* fs) +void r3xx_dump_fs(struct r3xx_fragment_shader* fs) { int i; @@ -30,82 +30,7 @@ static void r300_dump_fs(struct r300_fragment_shader* fs) } } -static char* r500_fs_swiz[] = { - " R", - " G", - " B", - " A", - " 0", - ".5", - " 1", - " U", -}; - -static char* r500_fs_op_rgb[] = { - "MAD", - "DP3", - "DP4", - "D2A", - "MIN", - "MAX", - "---", - "CND", - "CMP", - "FRC", - "SOP", - "MDH", - "MDV", -}; - -static char* r500_fs_op_alpha[] = { - "MAD", - " DP", - "MIN", - "MAX", - "---", - "CND", - "CMP", - "FRC", - "EX2", - "LN2", - "RCP", - "RSQ", - "SIN", - "COS", - "MDH", - "MDV", -}; - -static char* r500_fs_mask[] = { - "NONE", - "R ", - " G ", - "RG ", - " B ", - "R B ", - " GB ", - "RGB ", - " A", - "R A", - " G A", - "RG A", - " BA", - "R BA", - " GBA", - "RGBA", -}; - -static char* r500_fs_tex[] = { - " NOP", - " LD", - "TEXKILL", - " PROJ", - "LODBIAS", - " LOD", - " DXDY", -}; - -void r500_fs_dump(struct r500_fragment_shader* fs) +void r5xx_fs_dump(struct r5xx_fragment_shader* fs) { int i; uint32_t inst; @@ -133,8 +58,8 @@ void r500_fs_dump(struct r500_fragment_shader* fs) inst & R500_INST_NOP ? "NOP" : "", inst & R500_INST_ALU_WAIT ? "ALU_WAIT" : ""); debug_printf("wmask: %s omask: %s\n", - r500_fs_mask[(inst >> 11) & 0xf], - r500_fs_mask[(inst >> 15) & 0xf]); + r5xx_fs_mask[(inst >> 11) & 0xf], + r5xx_fs_mask[(inst >> 15) & 0xf]); switch (inst & 0x3) { case R500_INST_TYPE_ALU: case R500_INST_TYPE_OUT: @@ -160,36 +85,36 @@ void r500_fs_dump(struct r500_fragment_shader* fs) debug_printf(" 3: RGB_INST 0x%08x:", inst); debug_printf("rgb_A_src:%d %s/%s/%s %d " "rgb_B_src:%d %s/%s/%s %d\n", - inst & 0x3, r500_fs_swiz[(inst >> 2) & 0x7], - r500_fs_swiz[(inst >> 5) & 0x7], - r500_fs_swiz[(inst >> 8) & 0x7], + inst & 0x3, r5xx_fs_swiz[(inst >> 2) & 0x7], + r5xx_fs_swiz[(inst >> 5) & 0x7], + r5xx_fs_swiz[(inst >> 8) & 0x7], (inst >> 11) & 0x3, (inst >> 13) & 0x3, - r500_fs_swiz[(inst >> 15) & 0x7], - r500_fs_swiz[(inst >> 18) & 0x7], - r500_fs_swiz[(inst >> 21) & 0x7], + r5xx_fs_swiz[(inst >> 15) & 0x7], + r5xx_fs_swiz[(inst >> 18) & 0x7], + r5xx_fs_swiz[(inst >> 21) & 0x7], (inst >> 24) & 0x3); inst = fs->instructions[i].inst4; debug_printf(" 4: ALPHA_INST 0x%08x:", inst); debug_printf("%s dest:%d%s alp_A_src:%d %s %d " "alp_B_src:%d %s %d w:%d\n", - r500_fs_op_alpha[inst & 0xf], (inst >> 4) & 0x7f, + r5xx_fs_op_alpha[inst & 0xf], (inst >> 4) & 0x7f, inst & (1<<11) ? "(rel)":"", (inst >> 12) & 0x3, - r500_fs_swiz[(inst >> 14) & 0x7], (inst >> 17) & 0x3, - (inst >> 19) & 0x3, r500_fs_swiz[(inst >> 21) & 0x7], + r5xx_fs_swiz[(inst >> 14) & 0x7], (inst >> 17) & 0x3, + (inst >> 19) & 0x3, r5xx_fs_swiz[(inst >> 21) & 0x7], (inst >> 24) & 0x3, (inst >> 31) & 0x1); inst = fs->instructions[i].inst5; debug_printf(" 5: RGBA_INST 0x%08x:", inst); debug_printf("%s dest:%d%s rgb_C_src:%d %s/%s/%s %d " "alp_C_src:%d %s %d\n", - r500_fs_op_rgb[inst & 0xf], (inst >> 4) & 0x7f, + r5xx_fs_op_rgb[inst & 0xf], (inst >> 4) & 0x7f, inst & (1 << 11) ? "(rel)":"", (inst >> 12) & 0x3, - r500_fs_swiz[(inst >> 14) & 0x7], - r500_fs_swiz[(inst >> 17) & 0x7], - r500_fs_swiz[(inst >> 20) & 0x7], + r5xx_fs_swiz[(inst >> 14) & 0x7], + r5xx_fs_swiz[(inst >> 17) & 0x7], + r5xx_fs_swiz[(inst >> 20) & 0x7], (inst >> 23) & 0x3, (inst >> 25) & 0x3, - r500_fs_swiz[(inst >> 27) & 0x7], (inst >> 30) & 0x3); + r5xx_fs_swiz[(inst >> 27) & 0x7], (inst >> 30) & 0x3); break; case R500_INST_TYPE_FC: /* XXX don't even bother yet */ @@ -199,7 +124,7 @@ void r500_fs_dump(struct r500_fragment_shader* fs) debug_printf(" 1: TEX_INST 0x%08x: id: %d " "op:%s, %s, %s %s\n", inst, (inst >> 16) & 0xf, - r500_fs_tex[(inst >> 22) & 0x7], + r5xx_fs_tex[(inst >> 22) & 0x7], (inst & (1 << 25)) ? "ACQ" : "", (inst & (1 << 26)) ? "IGNUNC" : "", (inst & (1 << 27)) ? "UNSCALED" : "SCALED"); @@ -208,15 +133,15 @@ void r500_fs_dump(struct r500_fragment_shader* fs) debug_printf(" 2: TEX_ADDR 0x%08x: " "src: %d%s %s/%s/%s/%s dst: %d%s %s/%s/%s/%s\n", inst, inst & 0x7f, inst & (1 << 7) ? "(rel)" : "", - r500_fs_swiz[(inst >> 8) & 0x3], - r500_fs_swiz[(inst >> 10) & 0x3], - r500_fs_swiz[(inst >> 12) & 0x3], - r500_fs_swiz[(inst >> 14) & 0x3], + r5xx_fs_swiz[(inst >> 8) & 0x3], + r5xx_fs_swiz[(inst >> 10) & 0x3], + r5xx_fs_swiz[(inst >> 12) & 0x3], + r5xx_fs_swiz[(inst >> 14) & 0x3], (inst >> 16) & 0x7f, inst & (1 << 23) ? "(rel)" : "", - r500_fs_swiz[(inst >> 24) & 0x3], - r500_fs_swiz[(inst >> 26) & 0x3], - r500_fs_swiz[(inst >> 28) & 0x3], - r500_fs_swiz[(inst >> 30) & 0x3]); + r5xx_fs_swiz[(inst >> 24) & 0x3], + r5xx_fs_swiz[(inst >> 26) & 0x3], + r5xx_fs_swiz[(inst >> 28) & 0x3], + r5xx_fs_swiz[(inst >> 30) & 0x3]); inst = fs->instructions[i].inst3; debug_printf(" 3: TEX_DXDY 0x%08x\n", inst); @@ -225,14 +150,49 @@ void r500_fs_dump(struct r500_fragment_shader* fs) } } +static void r300_vs_op_dump(uint32_t op) +{ + debug_printf(" dst: %d%s op: ", + (op >> 13) & 0x7f, r300_vs_dst_debug[(op >> 8) & 0x7]); + if (op & 0x80) { + if (op & 0x1) { + debug_printf("PVS_MACRO_OP_2CLK_M2X_ADD\n"); + } else { + debug_printf(" PVS_MACRO_OP_2CLK_MADD\n"); + } + } else if (op & 0x40) { + debug_printf("%s\n", r300_vs_me_ops[op & 0x1f]); + } else { + debug_printf("%s\n", r300_vs_ve_ops[op & 0x1f]); + } +} + +void r300_vs_src_dump(uint32_t src) +{ + debug_printf(" reg: %d%s swiz: %s%s/%s%s/%s%s/%s%s\n", + (src >> 5) & 0x7f, r300_vs_src_debug[src & 0x3], + src & (1 << 25) ? "-" : " ", + r300_vs_swiz_debug[(src >> 13) & 0x7], + src & (1 << 26) ? "-" : " ", + r300_vs_swiz_debug[(src >> 16) & 0x7], + src & (1 << 27) ? "-" : " ", + r300_vs_swiz_debug[(src >> 19) & 0x7], + src & (1 << 28) ? "-" : " ", + r300_vs_swiz_debug[(src >> 22) & 0x7]); +} + void r300_vs_dump(struct r300_vertex_shader* vs) { int i; for (i = 0; i < vs->instruction_count; i++) { - debug_printf("inst0: 0x%x\n", vs->instructions[i].inst0); - debug_printf("inst1: 0x%x\n", vs->instructions[i].inst1); - debug_printf("inst2: 0x%x\n", vs->instructions[i].inst2); - debug_printf("inst3: 0x%x\n", vs->instructions[i].inst3); + debug_printf("%d: op: 0x%08x", i, vs->instructions[i].inst0); + r300_vs_op_dump(vs->instructions[i].inst0); + debug_printf(" src0: 0x%08x", vs->instructions[i].inst1); + r300_vs_src_dump(vs->instructions[i].inst1); + debug_printf(" src1: 0x%08x", vs->instructions[i].inst2); + r300_vs_src_dump(vs->instructions[i].inst2); + debug_printf(" src2: 0x%08x", vs->instructions[i].inst3); + r300_vs_src_dump(vs->instructions[i].inst3); } } diff --git a/src/gallium/drivers/r300/r300_debug.h b/src/gallium/drivers/r300/r300_debug.h index a1f873656dc..6b58c1e2501 100644 --- a/src/gallium/drivers/r300/r300_debug.h +++ b/src/gallium/drivers/r300/r300_debug.h @@ -24,10 +24,187 @@ #define R300_DEBUG_H #include "r300_reg.h" -#include "r300_state_shader.h" -#include "r300_state_tcl.h" +#include "r300_fs.h" +#include "r300_vs.h" -void r500_fs_dump(struct r500_fragment_shader* fs); +static char* r5xx_fs_swiz[] = { + " R", + " G", + " B", + " A", + " 0", + ".5", + " 1", + " U", +}; + +static char* r5xx_fs_op_rgb[] = { + "MAD", + "DP3", + "DP4", + "D2A", + "MIN", + "MAX", + "---", + "CND", + "CMP", + "FRC", + "SOP", + "MDH", + "MDV", +}; + +static char* r5xx_fs_op_alpha[] = { + "MAD", + " DP", + "MIN", + "MAX", + "---", + "CND", + "CMP", + "FRC", + "EX2", + "LN2", + "RCP", + "RSQ", + "SIN", + "COS", + "MDH", + "MDV", +}; + +static char* r5xx_fs_mask[] = { + "NONE", + "R ", + " G ", + "RG ", + " B ", + "R B ", + " GB ", + "RGB ", + " A", + "R A", + " G A", + "RG A", + " BA", + "R BA", + " GBA", + "RGBA", +}; + +static char* r5xx_fs_tex[] = { + " NOP", + " LD", + "TEXKILL", + " PROJ", + "LODBIAS", + " LOD", + " DXDY", +}; + +static char* r300_vs_ve_ops[] = { + /* R300 vector ops */ + " VE_NO_OP", + " VE_DOT_PRODUCT", + " VE_MULTIPLY", + " VE_ADD", + " VE_MULTIPLY_ADD", + " VE_DISTANCE_FACTOR", + " VE_FRACTION", + " VE_MAXIMUM", + " VE_MINIMUM", + "VE_SET_GREATER_THAN_EQUAL", + " VE_SET_LESS_THAN", + " VE_MULTIPLYX2_ADD", + " VE_MULTIPLY_CLAMP", + " VE_FLT2FIX_DX", + " VE_FLT2FIX_DX_RND", + /* R500 vector ops */ + " VE_PRED_SET_EQ_PUSH", + " VE_PRED_SET_GT_PUSH", + " VE_PRED_SET_GTE_PUSH", + " VE_PRED_SET_NEQ_PUSH", + " VE_COND_WRITE_EQ", + " VE_COND_WRITE_GT", + " VE_COND_WRITE_GTE", + " VE_COND_WRITE_NEQ", + " VE_SET_GREATER_THAN", + " VE_SET_EQUAL", + " VE_SET_NOT_EQUAL", + " (reserved)", + " (reserved)", + " (reserved)", +}; + +static char* r300_vs_me_ops[] = { + /* R300 math ops */ + " ME_NO_OP", + " ME_EXP_BASE2_DX", + " ME_LOG_BASE2_DX", + " ME_EXP_BASEE_FF", + " ME_LIGHT_COEFF_DX", + " ME_POWER_FUNC_FF", + " ME_RECIP_DX", + " ME_RECIP_FF", + " ME_RECIP_SQRT_DX", + " ME_RECIP_SQRT_FF", + " ME_MULTIPLY", + " ME_EXP_BASE2_FULL_DX", + " ME_LOG_BASE2_FULL_DX", + " ME_POWER_FUNC_FF_CLAMP_B", + "ME_POWER_FUNC_FF_CLAMP_B1", + "ME_POWER_FUNC_FF_CLAMP_01", + " ME_SIN", + " ME_COS", + /* R500 math ops */ + " ME_LOG_BASE2_IEEE", + " ME_RECIP_IEEE", + " ME_RECIP_SQRT_IEEE", + " ME_PRED_SET_EQ", + " ME_PRED_SET_GT", + " ME_PRED_SET_GTE", + " ME_PRED_SET_NEQ", + " ME_PRED_SET_CLR", + " ME_PRED_SET_INV", + " ME_PRED_SET_POP", + " ME_PRED_SET_RESTORE", + " (reserved)", + " (reserved)", + " (reserved)", +}; + +/* XXX refactor to avoid clashing symbols */ +static char* r300_vs_src_debug[] = { + "t", + "i", + "c", + "a", +}; + +static char* r300_vs_dst_debug[] = { + "t", + "a0", + "o", + "ox", + "a", + "i", + "u", + "u", +}; + +static char* r300_vs_swiz_debug[] = { + "X", + "Y", + "Z", + "W", + "0", + "1", + "U", + "U", +}; + +void r5xx_fs_dump(struct r5xx_fragment_shader* fs); +void r3xx_dump_fs(struct r3xx_fragment_shader* fs); void r300_vs_dump(struct r300_vertex_shader* vs); diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 01bac5f759c..ac510ffc2ed 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -56,6 +56,36 @@ void r300_emit_blend_color_state(struct r300_context* r300, } } +void r300_emit_clip_state(struct r300_context* r300, + struct pipe_clip_state* clip) +{ + int i; + struct r300_screen* r300screen = r300_screen(r300->context.screen); + CS_LOCALS(r300); + + if (r300screen->caps->has_tcl) { + BEGIN_CS(5 + (6 * 4)); + OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, + (r300screen->caps->is_r500 ? + R500_PVS_UCP_START : R300_PVS_UCP_START)); + OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, 6 * 4); + for (i = 0; i < 6; i++) { + OUT_CS_32F(clip->ucp[i][0]); + OUT_CS_32F(clip->ucp[i][1]); + OUT_CS_32F(clip->ucp[i][2]); + OUT_CS_32F(clip->ucp[i][3]); + } + OUT_CS_REG(R300_VAP_CLIP_CNTL, ((1 << clip->nr) - 1) | + R300_PS_UCP_MODE_CLIP_AS_TRIFAN); + END_CS; + } else { + BEGIN_CS(2); + OUT_CS_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE); + END_CS; + } + +} + void r300_emit_dsa_state(struct r300_context* r300, struct r300_dsa_state* dsa) { @@ -80,7 +110,7 @@ void r300_emit_dsa_state(struct r300_context* r300, } void r300_emit_fragment_shader(struct r300_context* r300, - struct r300_fragment_shader* fs) + struct r3xx_fragment_shader* fs) { int i; CS_LOCALS(r300); @@ -112,7 +142,7 @@ void r300_emit_fragment_shader(struct r300_context* r300, } void r500_emit_fragment_shader(struct r300_context* r300, - struct r500_fragment_shader* fs) + struct r5xx_fragment_shader* fs) { int i; struct r300_constant_buffer* constants = @@ -163,6 +193,7 @@ void r300_emit_fb_state(struct r300_context* r300, BEGIN_CS((8 * fb->nr_cbufs) + (fb->zsbuf ? 8 : 0) + 4); for (i = 0; i < fb->nr_cbufs; i++) { tex = (struct r300_texture*)fb->cbufs[i]->texture; + assert(tex && tex->buffer && "cbuf is marked, but NULL!"); pixpitch = tex->stride / tex->tex.block.size; OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0 + (4 * i), 1); @@ -177,7 +208,8 @@ void r300_emit_fb_state(struct r300_context* r300, if (fb->zsbuf) { tex = (struct r300_texture*)fb->zsbuf->texture; - pixpitch = (tex->stride / tex->tex.block.size); + assert(tex && tex->buffer && "zsbuf is marked, but NULL!"); + pixpitch = tex->stride / tex->tex.block.size; OUT_CS_REG_SEQ(R300_ZB_DEPTHOFFSET, 1); OUT_CS_RELOC(tex->buffer, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0); @@ -234,7 +266,7 @@ void r300_emit_rs_block_state(struct r300_context* r300, } for (i = 0; i < 8; i++) { OUT_CS(rs->ip[i]); - debug_printf("ip %d: 0x%08x\n", i, rs->ip[i]); + /* debug_printf("ip %d: 0x%08x\n", i, rs->ip[i]); */ } OUT_CS_REG_SEQ(R300_RS_COUNT, 2); @@ -248,27 +280,15 @@ void r300_emit_rs_block_state(struct r300_context* r300, } for (i = 0; i < 8; i++) { OUT_CS(rs->inst[i]); - debug_printf("inst %d: 0x%08x\n", i, rs->inst[i]); + /* debug_printf("inst %d: 0x%08x\n", i, rs->inst[i]); */ } - debug_printf("count: 0x%08x inst_count: 0x%08x\n", rs->count, - rs->inst_count); + /* debug_printf("count: 0x%08x inst_count: 0x%08x\n", rs->count, + * rs->inst_count); */ END_CS; } -void r300_emit_sampler(struct r300_context* r300, - struct r300_sampler_state* sampler, unsigned offset) -{ - CS_LOCALS(r300); - - BEGIN_CS(6); - OUT_CS_REG(R300_TX_FILTER0_0 + (offset * 4), sampler->filter0); - OUT_CS_REG(R300_TX_FILTER1_0 + (offset * 4), sampler->filter1); - OUT_CS_REG(R300_TX_BORDER_COLOR_0 + (offset * 4), sampler->border_color); - END_CS; -} - void r300_emit_scissor_state(struct r300_context* r300, struct r300_scissor_state* scissor) { @@ -282,11 +302,17 @@ void r300_emit_scissor_state(struct r300_context* r300, } void r300_emit_texture(struct r300_context* r300, - struct r300_texture* tex, unsigned offset) + struct r300_sampler_state* sampler, + struct r300_texture* tex, + unsigned offset) { CS_LOCALS(r300); - BEGIN_CS(10); + BEGIN_CS(16); + OUT_CS_REG(R300_TX_FILTER0_0 + (offset * 4), sampler->filter0); + OUT_CS_REG(R300_TX_FILTER1_0 + (offset * 4), sampler->filter1); + OUT_CS_REG(R300_TX_BORDER_COLOR_0 + (offset * 4), sampler->border_color); + OUT_CS_REG(R300_TX_FORMAT0_0 + (offset * 4), tex->state.format0); OUT_CS_REG(R300_TX_FORMAT1_0 + (offset * 4), tex->state.format1); OUT_CS_REG(R300_TX_FORMAT2_0 + (offset * 4), tex->state.format2); @@ -296,6 +322,30 @@ void r300_emit_texture(struct r300_context* r300, END_CS; } +void r300_emit_vertex_buffer(struct r300_context* r300) +{ + CS_LOCALS(r300); + + debug_printf("r300: Preparing vertex buffer %p for render, " + "vertex size %d\n", r300->vbo, + r300->vertex_info.vinfo.size); + /* Set the pointer to our vertex buffer. The emitted values are this: + * PACKET3 [3D_LOAD_VBPNTR] + * COUNT [1] + * FORMAT [size | stride << 8] + * OFFSET [offset into BO] + * VBPNTR [relocated BO] + */ + BEGIN_CS(7); + OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, 3); + OUT_CS(1); + OUT_CS(r300->vertex_info.vinfo.size | + (r300->vertex_info.vinfo.size << 8)); + OUT_CS(r300->vbo_offset); + OUT_CS_RELOC(r300->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0); + END_CS; +} + void r300_emit_vertex_format_state(struct r300_context* r300) { int i; @@ -310,22 +360,22 @@ void r300_emit_vertex_format_state(struct r300_context* r300) OUT_CS_REG_SEQ(R300_VAP_OUTPUT_VTX_FMT_0, 2); OUT_CS(r300->vertex_info.vinfo.hwfmt[2]); OUT_CS(r300->vertex_info.vinfo.hwfmt[3]); - for (i = 0; i < 4; i++) { - debug_printf("hwfmt%d: 0x%08x\n", i, - r300->vertex_info.vinfo.hwfmt[i]); - } + /* for (i = 0; i < 4; i++) { + * debug_printf("hwfmt%d: 0x%08x\n", i, + * r300->vertex_info.vinfo.hwfmt[i]); + * } */ OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_0, 8); for (i = 0; i < 8; i++) { OUT_CS(r300->vertex_info.vap_prog_stream_cntl[i]); - debug_printf("prog_stream_cntl%d: 0x%08x\n", i, - r300->vertex_info.vap_prog_stream_cntl[i]); + /* debug_printf("prog_stream_cntl%d: 0x%08x\n", i, + * r300->vertex_info.vap_prog_stream_cntl[i]); */ } OUT_CS_REG_SEQ(R300_VAP_PROG_STREAM_CNTL_EXT_0, 8); for (i = 0; i < 8; i++) { OUT_CS(r300->vertex_info.vap_prog_stream_cntl_ext[i]); - debug_printf("prog_stream_cntl_ext%d: 0x%08x\n", i, - r300->vertex_info.vap_prog_stream_cntl_ext[i]); + /* debug_printf("prog_stream_cntl_ext%d: 0x%08x\n", i, + * r300->vertex_info.vap_prog_stream_cntl_ext[i]); */ } END_CS; } @@ -346,17 +396,22 @@ void r300_emit_vertex_shader(struct r300_context* r300, } if (constants->count) { - BEGIN_CS(16 + (vs->instruction_count * 4) + (constants->count * 4)); + BEGIN_CS(14 + (vs->instruction_count * 4) + (constants->count * 4)); } else { - BEGIN_CS(13 + (vs->instruction_count * 4) + (constants->count * 4)); + BEGIN_CS(11 + (vs->instruction_count * 4)); } - OUT_CS_REG(R300_VAP_PVS_CODE_CNTL_0, R300_PVS_FIRST_INST(0) | + /* R300_VAP_PVS_CODE_CNTL_0 + * R300_VAP_PVS_CONST_CNTL + * R300_VAP_PVS_CODE_CNTL_1 + * See the r5xx docs for instructions on how to use these. + * XXX these could be optimized to select better values... */ + OUT_CS_REG_SEQ(R300_VAP_PVS_CODE_CNTL_0, 3); + OUT_CS(R300_PVS_FIRST_INST(0) | + R300_PVS_XYZW_VALID_INST(vs->instruction_count - 1) | R300_PVS_LAST_INST(vs->instruction_count - 1)); - OUT_CS_REG(R300_VAP_PVS_CODE_CNTL_1, vs->instruction_count - 1); - - /* XXX */ - OUT_CS_REG(R300_VAP_PVS_CONST_CNTL, 0x0); + OUT_CS(R300_PVS_MAX_CONST_ADDR(constants->count - 1)); + OUT_CS(vs->instruction_count - 1); OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, 0); OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, vs->instruction_count * 4); @@ -386,7 +441,6 @@ void r300_emit_vertex_shader(struct r300_context* r300, R300_PVS_VF_MAX_VTX_NUM(12)); OUT_CS_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0x0); END_CS; - } void r300_emit_viewport_state(struct r300_context* r300, @@ -403,7 +457,11 @@ void r300_emit_viewport_state(struct r300_context* r300, OUT_CS_32F(viewport->zscale); OUT_CS_32F(viewport->zoffset); - OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control); + if (r300->rs_state->enable_vte) { + OUT_CS_REG(R300_VAP_VTE_CNTL, viewport->vte_control); + } else { + OUT_CS_REG(R300_VAP_VTE_CNTL, 0); + } END_CS; } @@ -421,23 +479,67 @@ void r300_flush_textures(struct r300_context* r300) void r300_emit_dirty_state(struct r300_context* r300) { struct r300_screen* r300screen = r300_screen(r300->context.screen); - int i; - int dirty_tex = 0; + struct r300_texture* tex; + int i, dirty_tex = 0; + boolean invalid = FALSE; - if (!(r300->dirty_hw)) { + if (!(r300->dirty_state)) { return; } r300_update_derived_state(r300); /* XXX check size */ - struct r300_texture* fb_tex = - (struct r300_texture*)r300->framebuffer_state.cbufs[0]; - r300->winsys->add_buffer(r300->winsys, fb_tex->buffer, - 0, RADEON_GEM_DOMAIN_VRAM); - if (r300->winsys->validate(r300->winsys)) { - /* XXX */ +validate: + /* Color buffers... */ + for (i = 0; i < r300->framebuffer_state.nr_cbufs; i++) { + tex = (struct r300_texture*)r300->framebuffer_state.cbufs[i]->texture; + assert(tex && tex->buffer && "cbuf is marked, but NULL!"); + if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, + 0, RADEON_GEM_DOMAIN_VRAM)) { + r300->context.flush(&r300->context, 0, NULL); + goto validate; + } + } + /* ...depth buffer... */ + if (r300->framebuffer_state.zsbuf) { + tex = (struct r300_texture*)r300->framebuffer_state.zsbuf->texture; + assert(tex && tex->buffer && "zsbuf is marked, but NULL!"); + if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, + 0, RADEON_GEM_DOMAIN_VRAM)) { + r300->context.flush(&r300->context, 0, NULL); + goto validate; + } + } + /* ...textures... */ + for (i = 0; i < r300->texture_count; i++) { + tex = r300->textures[i]; + assert(tex && tex->buffer && "texture is marked, but NULL!"); + if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, + RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) { + r300->context.flush(&r300->context, 0, NULL); + goto validate; + } + } + /* ...and vertex buffer. */ + if (r300->vbo) { + if (!r300->winsys->add_buffer(r300->winsys, r300->vbo, + RADEON_GEM_DOMAIN_GTT, 0)) { + r300->context.flush(&r300->context, 0, NULL); + goto validate; + } + } else { + debug_printf("No VBO while emitting dirty state!\n"); + } + if (!r300->winsys->validate(r300->winsys)) { r300->context.flush(&r300->context, 0, NULL); + if (invalid) { + /* Well, hell. */ + debug_printf("r300: Stuck in validation loop, gonna quit now."); + exit(1); + } + invalid = TRUE; + goto validate; } if (r300->dirty_state & R300_NEW_BLEND) { @@ -450,6 +552,11 @@ void r300_emit_dirty_state(struct r300_context* r300) r300->dirty_state &= ~R300_NEW_BLEND_COLOR; } + if (r300->dirty_state & R300_NEW_CLIP) { + r300_emit_clip_state(r300, &r300->clip_state); + r300->dirty_state &= ~R300_NEW_CLIP; + } + if (r300->dirty_state & R300_NEW_DSA) { r300_emit_dsa_state(r300, r300->dsa_state); r300->dirty_state &= ~R300_NEW_DSA; @@ -458,10 +565,10 @@ void r300_emit_dirty_state(struct r300_context* r300) if (r300->dirty_state & R300_NEW_FRAGMENT_SHADER) { if (r300screen->caps->is_r500) { r500_emit_fragment_shader(r300, - (struct r500_fragment_shader*)r300->fs); + (struct r5xx_fragment_shader*)r300->fs); } else { r300_emit_fragment_shader(r300, - (struct r300_fragment_shader*)r300->fs); + (struct r3xx_fragment_shader*)r300->fs); } r300->dirty_state &= ~R300_NEW_FRAGMENT_SHADER; } @@ -481,29 +588,27 @@ void r300_emit_dirty_state(struct r300_context* r300) r300->dirty_state &= ~R300_NEW_RS_BLOCK; } - if (r300->dirty_state & R300_ANY_NEW_SAMPLERS) { - for (i = 0; i < r300->sampler_count; i++) { - if (r300->dirty_state & (R300_NEW_SAMPLER << i)) { - r300_emit_sampler(r300, r300->sampler_states[i], i); - r300->dirty_state &= ~(R300_NEW_SAMPLER << i); - dirty_tex++; - } - } - } - if (r300->dirty_state & R300_NEW_SCISSOR) { r300_emit_scissor_state(r300, r300->scissor_state); r300->dirty_state &= ~R300_NEW_SCISSOR; } - if (r300->dirty_state & R300_ANY_NEW_TEXTURES) { - for (i = 0; i < r300->texture_count; i++) { - if (r300->dirty_state & (R300_NEW_TEXTURE << i)) { - r300_emit_texture(r300, r300->textures[i], i); - r300->dirty_state &= ~(R300_NEW_TEXTURE << i); + /* Samplers and textures are tracked separately but emitted together. */ + if (r300->dirty_state & + (R300_ANY_NEW_SAMPLERS | R300_ANY_NEW_TEXTURES)) { + for (i = 0; i < MIN2(r300->sampler_count, r300->texture_count); i++) { + if (r300->dirty_state & + ((R300_NEW_SAMPLER << i) | (R300_NEW_TEXTURE << i))) { + r300_emit_texture(r300, + r300->sampler_states[i], + r300->textures[i], + i); + r300->dirty_state &= + ~((R300_NEW_SAMPLER << i) | (R300_NEW_TEXTURE << i)); dirty_tex++; } } + r300->dirty_state &= ~(R300_ANY_NEW_SAMPLERS | R300_ANY_NEW_TEXTURES); } if (r300->dirty_state & R300_NEW_VIEWPORT) { @@ -519,4 +624,18 @@ void r300_emit_dirty_state(struct r300_context* r300) r300_emit_vertex_format_state(r300); r300->dirty_state &= ~R300_NEW_VERTEX_FORMAT; } + + if (r300->dirty_state & R300_NEW_VERTEX_SHADER) { + r300_emit_vertex_shader(r300, r300->vs); + r300->dirty_state &= ~R300_NEW_VERTEX_SHADER; + } + + /* XXX + assert(r300->dirty_state == 0); + */ + + /* Finally, emit the VBO. */ + r300_emit_vertex_buffer(r300); + + r300->dirty_hw++; } diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h index 31dbc7ab853..fda26f39481 100644 --- a/src/gallium/drivers/r300/r300_emit.h +++ b/src/gallium/drivers/r300/r300_emit.h @@ -36,14 +36,17 @@ void r300_emit_blend_state(struct r300_context* r300, void r300_emit_blend_color_state(struct r300_context* r300, struct r300_blend_color_state* bc); +void r300_emit_clip_state(struct r300_context* r300, + struct pipe_clip_state* clip); + void r300_emit_dsa_state(struct r300_context* r300, struct r300_dsa_state* dsa); void r300_emit_fragment_shader(struct r300_context* r300, - struct r300_fragment_shader* fs); + struct r3xx_fragment_shader* fs); void r500_emit_fragment_shader(struct r300_context* r300, - struct r500_fragment_shader* fs); + struct r5xx_fragment_shader* fs); void r300_emit_fb_state(struct r300_context* r300, struct pipe_framebuffer_state* fb); @@ -53,14 +56,15 @@ void r300_emit_rs_state(struct r300_context* r300, struct r300_rs_state* rs); void r300_emit_rs_block_state(struct r300_context* r300, struct r300_rs_block* rs); -void r300_emit_sampler(struct r300_context* r300, - struct r300_sampler_state* sampler, unsigned offset); - void r300_emit_scissor_state(struct r300_context* r300, struct r300_scissor_state* scissor); void r300_emit_texture(struct r300_context* r300, - struct r300_texture* tex, unsigned offset); + struct r300_sampler_state* sampler, + struct r300_texture* tex, + unsigned offset); + +void r300_emit_vertex_buffer(struct r300_context* r300); void r300_emit_vertex_format_state(struct r300_context* r300); diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c index 89a5f2b20cf..0dff1c6f4fb 100644 --- a/src/gallium/drivers/r300/r300_flush.c +++ b/src/gallium/drivers/r300/r300_flush.c @@ -29,7 +29,11 @@ static void r300_flush(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); CS_LOCALS(r300); - draw_flush(r300->draw); + /* We probably need to flush Draw, but we may have been called from + * within Draw. This feels kludgy, but it might be the best thing. */ + if (!r300->draw->flushing) { + draw_flush(r300->draw); + } if (r300->dirty_hw) { FLUSH_CS; diff --git a/src/gallium/drivers/r300/r300_flush.h b/src/gallium/drivers/r300/r300_flush.h index a1b224b39ce..9a83d89daab 100644 --- a/src/gallium/drivers/r300/r300_flush.h +++ b/src/gallium/drivers/r300/r300_flush.h @@ -23,6 +23,8 @@ #ifndef R300_FLUSH_H #define R300_FLUSH_H +#include "draw/draw_private.h" + #include "pipe/p_context.h" #include "r300_context.h" diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c new file mode 100644 index 00000000000..ca8ef999024 --- /dev/null +++ b/src/gallium/drivers/r300/r300_fs.c @@ -0,0 +1,111 @@ +/* + * Copyright 2008 Corbin Simpson <[email protected]> + * Joakim Sindholt <[email protected]> + * + * 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 + * THE AUTHOR(S) 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 "r300_fs.h" + +void r300_translate_fragment_shader(struct r300_context* r300, + struct r300_fragment_shader* fs) +{ + struct tgsi_parse_context parser; + int i; + boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500; + struct r300_constant_buffer* consts = + &r300->shader_constants[PIPE_SHADER_FRAGMENT]; + + struct r300_fs_asm* assembler = CALLOC_STRUCT(r300_fs_asm); + if (assembler == NULL) { + return; + } + /* Setup starting offset for immediates. */ + assembler->imm_offset = consts->user_count; + /* Enable depth writes, if needed. */ + assembler->writes_depth = fs->info.writes_z; + + /* Make sure we start at the beginning of the shader. */ + if (is_r500) { + ((struct r5xx_fragment_shader*)fs)->instruction_count = 0; + } + + tgsi_parse_init(&parser, fs->state.tokens); + + while (!tgsi_parse_end_of_tokens(&parser)) { + tgsi_parse_token(&parser); + + /* This is seriously the lamest way to create fragment programs ever. + * I blame TGSI. */ + switch (parser.FullToken.Token.Type) { + case TGSI_TOKEN_TYPE_DECLARATION: + /* Allocated registers sitting at the beginning + * of the program. */ + r300_fs_declare(assembler, &parser.FullToken.FullDeclaration); + break; + case TGSI_TOKEN_TYPE_IMMEDIATE: + debug_printf("r300: Emitting immediate to constant buffer, " + "position %d\n", + assembler->imm_offset + assembler->imm_count); + /* I am not amused by the length of these. */ + for (i = 0; i < 4; i++) { + consts->constants[assembler->imm_offset + + assembler->imm_count][i] = + parser.FullToken.FullImmediate.u[i].Float; + } + assembler->imm_count++; + break; + case TGSI_TOKEN_TYPE_INSTRUCTION: + if (is_r500) { + r5xx_fs_instruction((struct r5xx_fragment_shader*)fs, + assembler, &parser.FullToken.FullInstruction); + } else { + r3xx_fs_instruction((struct r3xx_fragment_shader*)fs, + assembler, &parser.FullToken.FullInstruction); + } + break; + } + } + + debug_printf("r300: fs: %d texs and %d colors, first free reg is %d\n", + assembler->tex_count, assembler->color_count, + assembler->tex_count + assembler->color_count); + + consts->count = consts->user_count + assembler->imm_count; + fs->uses_imms = assembler->imm_count; + debug_printf("r300: fs: %d total constants, " + "%d from user and %d from immediates\n", consts->count, + consts->user_count, assembler->imm_count); + r3xx_fs_finalize(fs, assembler); + if (is_r500) { + r5xx_fs_finalize((struct r5xx_fragment_shader*)fs, assembler); + } + + tgsi_dump(fs->state.tokens, 0); + /* XXX finish r300 dumper too */ + if (is_r500) { + r5xx_fs_dump((struct r5xx_fragment_shader*)fs); + } + + tgsi_parse_free(&parser); + FREE(assembler); + + /* And, finally... */ + fs->translated = TRUE; +} diff --git a/src/gallium/drivers/r300/r300_fs.h b/src/gallium/drivers/r300/r300_fs.h new file mode 100644 index 00000000000..18deb7a05e4 --- /dev/null +++ b/src/gallium/drivers/r300/r300_fs.h @@ -0,0 +1,36 @@ +/* + * Copyright 2008 Corbin Simpson <[email protected]> + * Joakim Sindholt <[email protected]> + * + * 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 + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef R300_FS_H +#define R300_FS_H + +#include "tgsi/tgsi_dump.h" + +#include "r300_context.h" +#include "r3xx_fs.h" +#include "r5xx_fs.h" + +void r300_translate_fragment_shader(struct r300_context* r300, + struct r300_fragment_shader* fs); + + #endif /* R300_FS_H */ diff --git a/src/gallium/drivers/r300/r300_fs_inlines.h b/src/gallium/drivers/r300/r300_fs_inlines.h new file mode 100644 index 00000000000..be4be9465e6 --- /dev/null +++ b/src/gallium/drivers/r300/r300_fs_inlines.h @@ -0,0 +1,158 @@ +/* + * Copyright 2008 Corbin Simpson <[email protected]> + * Joakim Sindholt <[email protected]> + * + * 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 + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef R300_FS_INLINES_H +#define R300_FS_INLINES_H + +#include "tgsi/tgsi_parse.h" + +#include "r300_context.h" +#include "r300_debug.h" +#include "r300_reg.h" +#include "r300_screen.h" +#include "r300_shader_inlines.h" + +/* Temporary struct used to hold assembly state while putting together + * fragment programs. */ +struct r300_fs_asm { + /* Pipe context. */ + struct r300_context* r300; + /* Number of colors. */ + unsigned color_count; + /* Number of texcoords. */ + unsigned tex_count; + /* Offset for temporary registers. Inputs and temporaries have no + * distinguishing markings, so inputs start at 0 and the first usable + * temporary register is after all inputs. */ + unsigned temp_offset; + /* Number of requested temporary registers. */ + unsigned temp_count; + /* Offset for immediate constants. Neither R300 nor R500 can do four + * inline constants per source, so instead we copy immediates into the + * constant buffer. */ + unsigned imm_offset; + /* Number of immediate constants. */ + unsigned imm_count; + /* Are depth writes enabled? */ + boolean writes_depth; + /* Depth write offset. This is the TGSI output that corresponds to + * depth writes. */ + unsigned depth_output; +}; + +static INLINE void r300_fs_declare(struct r300_fs_asm* assembler, + struct tgsi_full_declaration* decl) +{ + switch (decl->Declaration.File) { + case TGSI_FILE_INPUT: + switch (decl->Semantic.SemanticName) { + case TGSI_SEMANTIC_COLOR: + assembler->color_count++; + break; + case TGSI_SEMANTIC_FOG: + case TGSI_SEMANTIC_GENERIC: + assembler->tex_count++; + break; + default: + debug_printf("r300: fs: Bad semantic declaration %d\n", + decl->Semantic.SemanticName); + break; + } + break; + case TGSI_FILE_OUTPUT: + /* Depth write. Mark the position of the output so we can + * identify it later. */ + if (decl->Semantic.SemanticName == TGSI_SEMANTIC_POSITION) { + assembler->depth_output = decl->DeclarationRange.First; + } + break; + case TGSI_FILE_CONSTANT: + break; + case TGSI_FILE_TEMPORARY: + assembler->temp_count++; + break; + default: + debug_printf("r300: fs: Bad file %d\n", decl->Declaration.File); + break; + } + + assembler->temp_offset = assembler->color_count + assembler->tex_count; +} + +static INLINE unsigned r300_fs_src(struct r300_fs_asm* assembler, + struct tgsi_src_register* src) +{ + switch (src->File) { + case TGSI_FILE_NULL: + return 0; + case TGSI_FILE_INPUT: + /* XXX may be wrong */ + return src->Index; + break; + case TGSI_FILE_TEMPORARY: + return src->Index + assembler->temp_offset; + break; + case TGSI_FILE_IMMEDIATE: + return (src->Index + assembler->imm_offset) | (1 << 8); + break; + case TGSI_FILE_CONSTANT: + /* XXX magic */ + return src->Index | (1 << 8); + break; + default: + debug_printf("r300: fs: Unimplemented src %d\n", src->File); + break; + } + return 0; +} + +static INLINE unsigned r300_fs_dst(struct r300_fs_asm* assembler, + struct tgsi_dst_register* dst) +{ + switch (dst->File) { + case TGSI_FILE_NULL: + /* This happens during KIL instructions. */ + return 0; + break; + case TGSI_FILE_OUTPUT: + return 0; + break; + case TGSI_FILE_TEMPORARY: + return dst->Index + assembler->temp_offset; + break; + default: + debug_printf("r300: fs: Unimplemented dst %d\n", dst->File); + break; + } + return 0; +} + +static INLINE boolean r300_fs_is_depr(struct r300_fs_asm* assembler, + struct tgsi_dst_register* dst) +{ + return (assembler->writes_depth && + (dst->File == TGSI_FILE_OUTPUT) && + (dst->Index == assembler->depth_output)); +} + +#endif /* R300_FS_INLINES_H */ diff --git a/src/gallium/drivers/r300/r300_query.h b/src/gallium/drivers/r300/r300_query.h index 4f447ea45b8..6a7646087a7 100644 --- a/src/gallium/drivers/r300/r300_query.h +++ b/src/gallium/drivers/r300/r300_query.h @@ -27,6 +27,8 @@ #include "r300_cs.h" #include "r300_reg.h" +struct r300_context; + struct r300_query { /* The kind of query. Currently only OQ is supported. */ unsigned type; diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h index 660816e1da1..6825d998700 100644 --- a/src/gallium/drivers/r300/r300_reg.h +++ b/src/gallium/drivers/r300/r300_reg.h @@ -511,11 +511,13 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_PVS_XYZW_VALID_INST_SHIFT 10 # define R300_PVS_LAST_INST_SHIFT 20 # define R300_PVS_FIRST_INST(x) ((x) << 0) +# define R300_PVS_XYZW_VALID_INST(x) ((x) << 10) # define R300_PVS_LAST_INST(x) ((x) << 20) /* Addresses are relative the the vertex program parameters area. */ #define R300_VAP_PVS_CONST_CNTL 0x22D4 # define R300_PVS_CONST_BASE_OFFSET_SHIFT 0 # define R300_PVS_MAX_CONST_ADDR_SHIFT 16 +# define R300_PVS_MAX_CONST_ADDR(x) ((x) << 16) #define R300_VAP_PVS_CODE_CNTL_1 0x22D8 # define R300_PVS_LAST_VTX_SRC_INST_SHIFT 0 #define R300_VAP_PVS_FLOW_CNTL_OPC 0x22DC @@ -1062,8 +1064,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. R300_GA_COLOR_CONTROL_RGB2_SHADING_FLAT | \ R300_GA_COLOR_CONTROL_ALPHA2_SHADING_FLAT | \ R300_GA_COLOR_CONTROL_RGB3_SHADING_FLAT | \ - R300_GA_COLOR_CONTROL_ALPHA3_SHADING_FLAT | \ - R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST ) + R300_GA_COLOR_CONTROL_ALPHA3_SHADING_FLAT ) # define R300_SHADE_MODEL_SMOOTH ( \ R300_GA_COLOR_CONTROL_RGB0_SHADING_GOURAUD | \ @@ -1073,8 +1074,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. R300_GA_COLOR_CONTROL_RGB2_SHADING_GOURAUD | \ R300_GA_COLOR_CONTROL_ALPHA2_SHADING_GOURAUD | \ R300_GA_COLOR_CONTROL_RGB3_SHADING_GOURAUD | \ - R300_GA_COLOR_CONTROL_ALPHA3_SHADING_GOURAUD | \ - R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST ) + R300_GA_COLOR_CONTROL_ALPHA3_SHADING_GOURAUD ) /* Specifies red & green components of fill color -- S312 format -- Backwards comp. */ #define R300_GA_SOLID_RG 0x427c @@ -1478,6 +1478,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_TX_PITCH_EN (1 << 31) # define R300_TX_WIDTH(x) ((x) << 0) # define R300_TX_HEIGHT(x) ((x) << 11) +# define R300_TX_NUM_LEVELS(x) ((x) << 26) #define R300_TX_FORMAT1_0 0x44C0 /* The interpretation of the format word by Wladimir van der Laan */ @@ -1485,9 +1486,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. They are given meanings as R, G, B and Alpha by the swizzle specification */ # define R300_TX_FORMAT_X8 0x0 -# define R500_TX_FORMAT_X1 0x0 // bit set in format 2 # define R300_TX_FORMAT_X16 0x1 -# define R500_TX_FORMAT_X1_REV 0x0 // bit set in format 2 # define R300_TX_FORMAT_Y4X4 0x2 # define R300_TX_FORMAT_Y8X8 0x3 # define R300_TX_FORMAT_Y16X16 0x4 @@ -1504,31 +1503,29 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_TX_FORMAT_DXT1 0xF # define R300_TX_FORMAT_DXT3 0x10 # define R300_TX_FORMAT_DXT5 0x11 -# define R300_TX_FORMAT_D3DMFT_CxV8U8 0x12 /* no swizzle */ -# define R300_TX_FORMAT_A8R8G8B8 0x13 /* no swizzle */ -# define R300_TX_FORMAT_B8G8_B8G8 0x14 /* no swizzle */ -# define R300_TX_FORMAT_G8R8_G8B8 0x15 /* no swizzle */ - - /* These two values are wrong, but they're the only values that - * produce any even vaguely correct results. Can r300 only do 16-bit - * depth textures? - */ -# define R300_TX_FORMAT_X24_Y8 0x1e -# define R300_TX_FORMAT_X32 0x1e - - /* 0x16 - some 16 bit green format.. ?? */ +# define R300_TX_FORMAT_Y8 0x12 +# define R300_TX_FORMAT_AVYU444 0x13 +# define R300_TX_FORMAT_VYUY422 0x14 +# define R300_TX_FORMAT_YVYU422 0x15 +# define R300_TX_FORMAT_16_MPEG 0x16 +# define R300_TX_FORMAT_16_16_MPEG 0x17 +# define R300_TX_FORMAT_16F 0x18 +# define R300_TX_FORMAT_16F_16F 0x19 +# define R300_TX_FORMAT_16F_16F_16F_16F 0x1A +# define R300_TX_FORMAT_32F 0x1B +# define R300_TX_FORMAT_32F_32F 0x1C +# define R300_TX_FORMAT_32F_32F_32F_32F 0x1D +# define R300_TX_FORMAT_W24_FP 0x1E + +# define R300_TX_FORMAT_SIGNED_W (1 << 5) +# define R300_TX_FORMAT_SIGNED_Z (1 << 6) +# define R300_TX_FORMAT_SIGNED_Y (1 << 7) +# define R300_TX_FORMAT_SIGNED_X (1 << 8) +# define R300_TX_FORMAT_SIGNED (0xf << 5) + # define R300_TX_FORMAT_3D (1 << 25) # define R300_TX_FORMAT_CUBIC_MAP (2 << 25) - /* gap */ - /* Floating point formats */ - /* Note - hardware supports both 16 and 32 bit floating point */ -# define R300_TX_FORMAT_FL_I16 0x18 -# define R300_TX_FORMAT_FL_I16A16 0x19 -# define R300_TX_FORMAT_FL_R16G16B16A16 0x1A -# define R300_TX_FORMAT_FL_I32 0x1B -# define R300_TX_FORMAT_FL_I32A32 0x1C -# define R300_TX_FORMAT_FL_R32G32B32A32 0x1D /* alpha modes, convenience mostly */ /* if you have alpha, pick constant appropriate to the number of channels (1 for I8, 2 for I8A8, 4 for R8G8B8A8, etc */ @@ -1569,7 +1566,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_TX_FORMAT_CONST_Z (4<<5) # define R300_TX_FORMAT_CONST_W (8<<5) -# define R300_TX_FORMAT_YUV_MODE 0x00800000 +# define R300_TX_FORMAT_GAMMA (1 << 21) +# define R300_TX_FORMAT_YUV_TO_RGB (1 << 22) #define R300_TX_FORMAT2_0 0x4500 /* obvious missing in gap */ # define R300_TX_PITCHMASK_SHIFT 0 @@ -3040,6 +3038,7 @@ enum { # define R500_INST_RGB_WMASK_R (1 << 11) # define R500_INST_RGB_WMASK_G (1 << 12) # define R500_INST_RGB_WMASK_B (1 << 13) +# define R500_INST_RGB_WMASK_RGB (7 << 11) # define R500_INST_ALPHA_WMASK (1 << 14) # define R500_INST_RGB_OMASK_R (1 << 15) # define R500_INST_RGB_OMASK_G (1 << 16) diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index cbd84d7c569..cd458d019ae 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -45,11 +45,7 @@ struct r300_render { /* VBO */ struct pipe_buffer* vbo; - size_t vbo_size; - size_t vbo_offset; - void* vbo_map; size_t vbo_alloc_size; - size_t vbo_max_used; }; static INLINE struct r300_render* @@ -78,24 +74,21 @@ static boolean r300_render_allocate_vertices(struct vbuf_render* render, struct pipe_screen* screen = r300->context.screen; size_t size = (size_t)vertex_size * (size_t)count; - if (r300render->vbo) { + if (r300render->vbo && (size > r300render->vbo_alloc_size)) { pipe_buffer_reference(&r300render->vbo, NULL); } + + if (!r300render->vbo) { + r300render->vbo = pipe_buffer_create(screen, + 64, + PIPE_BUFFER_USAGE_VERTEX, + size); + } - r300render->vbo_size = MAX2(size, r300render->vbo_alloc_size); - r300render->vbo_offset = 0; - r300render->vbo = pipe_buffer_create(screen, - 64, - PIPE_BUFFER_USAGE_VERTEX, - r300render->vbo_size); - + r300render->vbo_alloc_size = MAX2(size, r300render->vbo_alloc_size); r300render->vertex_size = vertex_size; - if (r300render->vbo) { - return TRUE; - } else { - return FALSE; - } + return (r300render->vbo) ? TRUE : FALSE; } static void* r300_render_map_vertices(struct vbuf_render* render) @@ -103,10 +96,8 @@ static void* r300_render_map_vertices(struct vbuf_render* render) struct r300_render* r300render = r300_render(render); struct pipe_screen* screen = r300render->r300->context.screen; - r300render->vbo_map = pipe_buffer_map(screen, r300render->vbo, - PIPE_BUFFER_USAGE_CPU_WRITE); - - return (unsigned char*)r300render->vbo_map + r300render->vbo_offset; + return (unsigned char*)pipe_buffer_map(screen, r300render->vbo, + PIPE_BUFFER_USAGE_CPU_WRITE); } static void r300_render_unmap_vertices(struct vbuf_render* render, @@ -116,9 +107,6 @@ static void r300_render_unmap_vertices(struct vbuf_render* render, struct r300_render* r300render = r300_render(render); struct pipe_screen* screen = r300render->r300->context.screen; - r300render->vbo_max_used = MAX2(r300render->vbo_max_used, - r300render->vertex_size * (max + 1)); - pipe_buffer_unmap(screen, r300render->vbo); } @@ -180,27 +168,9 @@ static void prepare_render(struct r300_render* render, unsigned count) CS_LOCALS(r300); - /* Make sure that all possible state is emitted. */ - r300_emit_dirty_state(r300); + r300->vbo = render->vbo; - debug_printf("r300: Preparing vertex buffer %p for render, " - "vertex size %d, vertex count %d\n", render->vbo, - r300->vertex_info.vinfo.size, count); - /* Set the pointer to our vertex buffer. The emitted values are this: - * PACKET3 [3D_LOAD_VBPNTR] - * COUNT [1] - * FORMAT [size | stride << 8] - * OFFSET [0] - * VBPNTR [relocated BO] - */ - BEGIN_CS(7); - OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, 3); - OUT_CS(1); - OUT_CS(r300->vertex_info.vinfo.size | - (r300->vertex_info.vinfo.size << 8)); - OUT_CS(render->vbo_offset); - OUT_CS_RELOC(render->vbo, 0, RADEON_GEM_DOMAIN_GTT, 0, 0); - END_CS; + r300_emit_dirty_state(r300); } static void r300_render_draw_arrays(struct vbuf_render* render, @@ -212,8 +182,6 @@ static void r300_render_draw_arrays(struct vbuf_render* render, CS_LOCALS(r300); - r300render->vbo_offset = start; - prepare_render(r300render, count); debug_printf("r300: Doing vbuf render, count %d\n", count); @@ -248,13 +216,14 @@ static void r300_render_draw(struct vbuf_render* render, return; } +/* index_map = pipe_buffer_map(screen, index_buffer, PIPE_BUFFER_USAGE_CPU_WRITE); memcpy(index_map, indices, count); pipe_buffer_unmap(screen, index_buffer); debug_printf("r300: Doing indexbuf render, count %d\n", count); -/* + BEGIN_CS(8); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | @@ -264,13 +233,15 @@ static void r300_render_draw(struct vbuf_render* render, OUT_CS_INDEX_RELOC(index_buffer, 0, count, RADEON_GEM_DOMAIN_GTT, 0, 0); END_CS; */ - BEGIN_CS(2 + count); - OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, count); + BEGIN_CS(2 + (count+1)/2); + OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, (count+1)/2); OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | - r300render->hwprim | R300_VAP_VF_CNTL__INDEX_SIZE_32bit); - for (i = 0; i < count; i++) { - index = indices[i]; - OUT_CS(index); + r300render->hwprim); + for (i = 0; i < count-1; i += 2) { + OUT_CS(indices[i+1] << 16 | indices[i]); + } + if (count % 2) { + OUT_CS(indices[count-1]); } END_CS; } diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index d2c5998c261..258e4ac7b2a 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -87,23 +87,24 @@ static int r300_get_param(struct pipe_screen* pscreen, int param) } else { return 0; } - return 0; case PIPE_CAP_GLSL: - /* IN THEORY */ - return 0; + if (r300screen->caps->is_r500) { + return 1; + } else { + return 0; + } case PIPE_CAP_S3TC: - /* IN THEORY */ - return 0; + return 1; case PIPE_CAP_ANISOTROPIC_FILTER: - /* IN THEORY */ - return 0; + return 1; case PIPE_CAP_POINT_SPRITE: /* IN THEORY */ return 0; case PIPE_CAP_MAX_RENDER_TARGETS: return 4; case PIPE_CAP_OCCLUSION_QUERY: - return 1; + /* IN THEORY */ + return 0; case PIPE_CAP_TEXTURE_SHADOW_MAP: /* IN THEORY */ return 0; @@ -143,6 +144,11 @@ static int r300_get_param(struct pipe_screen* pscreen, int param) case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: /* XXX guessing (what a terrible guess) */ return 2; + case PIPE_CAP_TGSI_CONT_SUPPORTED: + /* XXX */ + return 0; + case PIPE_CAP_BLEND_EQUATION_SEPARATE: + return 1; default: debug_printf("r300: Implementation error: Bad param %d\n", param); @@ -152,17 +158,20 @@ static int r300_get_param(struct pipe_screen* pscreen, int param) static float r300_get_paramf(struct pipe_screen* pscreen, int param) { + struct r300_screen* r300screen = r300_screen(pscreen); + switch (param) { case PIPE_CAP_MAX_LINE_WIDTH: case PIPE_CAP_MAX_LINE_WIDTH_AA: - /* XXX this is the biggest thing that will fit in that register. - * Perhaps the actual rendering limits are less? */ - return 10922.0f; case PIPE_CAP_MAX_POINT_WIDTH: case PIPE_CAP_MAX_POINT_WIDTH_AA: - /* XXX this is the biggest thing that will fit in that register. - * Perhaps the actual rendering limits are less? */ - return 10922.0f; + /* The maximum dimensions of the colorbuffer are our practical + * rendering limits. 2048 pixels should be enough for anybody. */ + if (r300screen->caps->is_r500) { + return 4096.0f; + } else { + return 2048.0f; + } case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: return 16.0f; case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: @@ -174,21 +183,58 @@ static float r300_get_paramf(struct pipe_screen* pscreen, int param) } } -static boolean check_tex_2d_format(enum pipe_format format, boolean is_r500) +static boolean check_tex_2d_format(enum pipe_format format, uint32_t usage, + boolean is_r500) { switch (format) { + /* Supported formats. */ /* Colorbuffer */ case PIPE_FORMAT_A4R4G4B4_UNORM: case PIPE_FORMAT_R5G6B5_UNORM: case PIPE_FORMAT_A1R5G5B5_UNORM: - case PIPE_FORMAT_A8R8G8B8_UNORM: + return usage & + (PIPE_TEXTURE_USAGE_RENDER_TARGET | + PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_PRIMARY); + + /* Texture */ + case PIPE_FORMAT_A8R8G8B8_SRGB: + case PIPE_FORMAT_R8G8B8A8_SRGB: + case PIPE_FORMAT_DXT1_RGB: + case PIPE_FORMAT_DXT1_RGBA: + case PIPE_FORMAT_DXT3_RGBA: + case PIPE_FORMAT_DXT5_RGBA: + case PIPE_FORMAT_YCBCR: + return usage & PIPE_TEXTURE_USAGE_SAMPLER; + /* Colorbuffer or texture */ + case PIPE_FORMAT_A8R8G8B8_UNORM: + case PIPE_FORMAT_R8G8B8A8_UNORM: case PIPE_FORMAT_I8_UNORM: + return usage & + (PIPE_TEXTURE_USAGE_RENDER_TARGET | + PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_PRIMARY | + PIPE_TEXTURE_USAGE_SAMPLER); + /* Z buffer */ case PIPE_FORMAT_Z16_UNORM: - /* Z buffer with stencil */ + return usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL; + + /* Z buffer with stencil or texture */ case PIPE_FORMAT_Z24S8_UNORM: - return TRUE; + return usage & + (PIPE_TEXTURE_USAGE_DEPTH_STENCIL | + PIPE_TEXTURE_USAGE_SAMPLER); + + /* Definitely unsupported formats. */ + /* Non-usable Z buffer/stencil formats. */ + case PIPE_FORMAT_Z24X8_UNORM: + case PIPE_FORMAT_S8Z24_UNORM: + case PIPE_FORMAT_X8Z24_UNORM: + debug_printf("r300: Note: Got unsupported format: %s in %s\n", + pf_name(format), __FUNCTION__); + return FALSE; /* XXX These don't even exist case PIPE_FORMAT_A32R32G32B32: @@ -211,7 +257,8 @@ static boolean check_tex_2d_format(enum pipe_format format, boolean is_r500) return FALSE; */ default: - debug_printf("r300: Warning: Got unsupported format: %s in %s\n", + /* Unknown format... */ + debug_printf("r300: Warning: Got unknown format: %s in %s\n", pf_name(format), __FUNCTION__); break; } @@ -228,11 +275,18 @@ static boolean r300_is_format_supported(struct pipe_screen* pscreen, { switch (target) { case PIPE_TEXTURE_2D: - return check_tex_2d_format(format, + return check_tex_2d_format(format, tex_usage, r300_screen(pscreen)->caps->is_r500); + case PIPE_TEXTURE_1D: + case PIPE_TEXTURE_3D: + case PIPE_TEXTURE_CUBE: + debug_printf("r300: Implementation error: Unsupported format " + "target: %d\n", target); + break; default: - debug_printf("r300: Warning: Got unknown format target: %d\n", - format); + debug_printf("r300: Fatal: This is not a format target: %d\n", + target); + assert(0); break; } @@ -337,7 +391,6 @@ struct pipe_screen* r300_create_screen(struct r300_winsys* r300_winsys) return NULL; caps->pci_id = r300_winsys->pci_id; - caps->num_frag_pipes = r300_winsys->gb_pipes; r300_parse_chipset(caps); diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h index 3f52dbc3bea..2a0e41fbc3b 100644 --- a/src/gallium/drivers/r300/r300_screen.h +++ b/src/gallium/drivers/r300/r300_screen.h @@ -49,7 +49,7 @@ struct r300_transfer { }; /* Convenience cast wrapper. */ -static struct r300_screen* r300_screen(struct pipe_screen* screen) { +static INLINE struct r300_screen* r300_screen(struct pipe_screen* screen) { return (struct r300_screen*)screen; } diff --git a/src/gallium/drivers/r300/r300_shader_inlines.h b/src/gallium/drivers/r300/r300_shader_inlines.h new file mode 100644 index 00000000000..a04f45b03e2 --- /dev/null +++ b/src/gallium/drivers/r300/r300_shader_inlines.h @@ -0,0 +1,47 @@ +/* + * Copyright 2009 Corbin Simpson <[email protected]> + * Joakim Sindholt <[email protected]> + * + * 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 + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef R300_SHADER_INLINES_H +#define R300_SHADER_INLINES_H + +/* TGSI constants. TGSI is like XML: If it can't solve your problems, you're + * not using enough of it. */ +static const struct tgsi_full_src_register r300_constant_zero = { + .SrcRegister.Extended = TRUE, + .SrcRegister.File = TGSI_FILE_NULL, + .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ZERO, + .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ZERO, + .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ZERO, + .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ZERO, +}; + +static const struct tgsi_full_src_register r300_constant_one = { + .SrcRegister.Extended = TRUE, + .SrcRegister.File = TGSI_FILE_NULL, + .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ONE, + .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ONE, + .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ONE, + .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ONE, +}; + +#endif /* R300_SHADER_INLINES_H */ diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 184a23c9e68..162740f594d 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -24,12 +24,14 @@ #include "util/u_pack_color.h" #include "util/u_debug.h" + +#include "pipe/p_config.h" #include "pipe/internal/p_winsys_screen.h" #include "r300_context.h" #include "r300_reg.h" #include "r300_state_inlines.h" -#include "r300_state_shader.h" +#include "r300_fs.h" /* r300_state: Functions used to intialize state context by translating * Gallium state objects into semi-native r300 state objects. */ @@ -62,8 +64,6 @@ static void* r300_create_blend_state(struct pipe_context* pipe, } /* PIPE_LOGICOP_* don't need to be translated, fortunately. */ - /* XXX are logicops still allowed if blending's disabled? - * Does Gallium take care of it for us? */ if (state->logicop_enable) { blend->rop = R300_RB3D_ROPCNTL_ROP_ENABLE | (state->logicop_func) << R300_RB3D_ROPCNTL_ROP_SHIFT; @@ -121,9 +121,14 @@ static void r300_set_clip_state(struct pipe_context* pipe, const struct pipe_clip_state* state) { struct r300_context* r300 = r300_context(pipe); - /* XXX Draw */ - draw_flush(r300->draw); - draw_set_clip_state(r300->draw, state); + + if (r300_screen(pipe->screen)->caps->has_tcl) { + r300->clip_state = *state; + r300->dirty_state |= R300_NEW_CLIP; + } else { + draw_flush(r300->draw); + draw_set_clip_state(r300->draw, state); + } } static void @@ -150,17 +155,20 @@ static void } r300->dirty_state |= R300_NEW_CONSTANTS; - +#if 0 /* If the number of constants have changed, invalidate the shader. */ if (r300->shader_constants[shader].user_count != i) { - if (shader == PIPE_SHADER_FRAGMENT && r300->fs) { + if (shader == PIPE_SHADER_FRAGMENT && r300->fs && + r300->fs->uses_imms) { r300->fs->translated = FALSE; r300_translate_fragment_shader(r300, r300->fs); - } else if (shader == PIPE_SHADER_VERTEX && r300->vs) { + } else if (shader == PIPE_SHADER_VERTEX && r300->vs && + r300->vs->uses_imms) { r300->vs->translated = FALSE; r300_translate_vertex_shader(r300, r300->vs); } } +#endif } /* Create a new depth, stencil, and alpha state based on the CSO dsa state. @@ -257,6 +265,7 @@ static void r300_set_edgeflags(struct pipe_context* pipe, const unsigned* bitfield) { /* XXX you know it's bad when i915 has this blank too */ + /* XXX and even worse, I have no idea WTF the bitfield is */ } static void @@ -277,18 +286,17 @@ static void* r300_create_fs_state(struct pipe_context* pipe, const struct pipe_shader_state* shader) { struct r300_context* r300 = r300_context(pipe); - struct r3xx_fragment_shader* fs = NULL; + struct r300_fragment_shader* fs = NULL; if (r300_screen(r300->context.screen)->caps->is_r500) { - fs = - (struct r3xx_fragment_shader*)CALLOC_STRUCT(r500_fragment_shader); + fs = (struct r300_fragment_shader*)CALLOC_STRUCT(r5xx_fragment_shader); } else { - fs = - (struct r3xx_fragment_shader*)CALLOC_STRUCT(r300_fragment_shader); + fs = (struct r300_fragment_shader*)CALLOC_STRUCT(r3xx_fragment_shader); } /* Copy state directly into shader. */ fs->state = *shader; + fs->state.tokens = tgsi_dup_tokens(shader->tokens); tgsi_scan_shader(shader->tokens, &fs->info); @@ -299,7 +307,7 @@ static void* r300_create_fs_state(struct pipe_context* pipe, static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) { struct r300_context* r300 = r300_context(pipe); - struct r3xx_fragment_shader* fs = (struct r3xx_fragment_shader*)shader; + struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader; if (fs == NULL) { r300->fs = NULL; @@ -308,7 +316,6 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) r300_translate_fragment_shader(r300, fs); } - fs->translated = TRUE; r300->fs = fs; r300->dirty_state |= R300_NEW_FRAGMENT_SHADER; @@ -317,13 +324,15 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) /* Delete fragment shader state. */ static void r300_delete_fs_state(struct pipe_context* pipe, void* shader) { + struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader; + FREE(fs->state.tokens); FREE(shader); } static void r300_set_polygon_stipple(struct pipe_context* pipe, const struct pipe_poly_stipple* state) { - /* XXX */ + /* XXX no idea how to set this up, but not terribly important */ } /* Create a new rasterizer state based on the CSO rasterizer state. @@ -341,14 +350,21 @@ static void* r300_create_rs_state(struct pipe_context* pipe, /* Copy rasterizer state for Draw. */ rs->rs = *state; + rs->enable_vte = !state->bypass_vs_clip_and_viewport; + +#ifdef PIPE_ARCH_LITTLE_ENDIAN + rs->vap_control_status = R300_VC_NO_SWAP; +#else + rs->vap_control_status = R300_VC_32BIT_SWAP; +#endif + /* If bypassing TCL, or if no TCL engine is present, turn off the HW TCL. * Else, enable HW TCL and force Draw's TCL off. */ if (state->bypass_vs_clip_and_viewport || !r300_screen(pipe->screen)->caps->has_tcl) { - rs->vap_control_status = R300_VAP_TCL_BYPASS; + rs->vap_control_status |= R300_VAP_TCL_BYPASS; } else { rs->rs.bypass_vs_clip_and_viewport = TRUE; - rs->vap_control_status = 0; } rs->point_size = pack_float_16_6x(state->point_size) | @@ -412,6 +428,10 @@ static void* r300_create_rs_state(struct pipe_context* pipe, rs->color_control = R300_SHADE_MODEL_SMOOTH; } + if (!state->flatshade_first) { + rs->color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST; + } + return (void*)rs; } @@ -555,40 +575,35 @@ static void r300_set_viewport_state(struct pipe_context* pipe, { struct r300_context* r300 = r300_context(pipe); - draw_flush(r300->draw); - - if (r300_screen(r300->context.screen)->caps->has_tcl) { - /* Do the transform in HW. */ - r300->viewport_state->vte_control = R300_VTX_W0_FMT; + /* Do the transform in HW. */ + r300->viewport_state->vte_control = R300_VTX_W0_FMT; - if (state->scale[0] != 1.0f) { - r300->viewport_state->xscale = state->scale[0]; - r300->viewport_state->vte_control |= R300_VPORT_X_SCALE_ENA; - } - if (state->scale[1] != 1.0f) { - r300->viewport_state->yscale = state->scale[1]; - r300->viewport_state->vte_control |= R300_VPORT_Y_SCALE_ENA; - } - if (state->scale[2] != 1.0f) { - r300->viewport_state->zscale = state->scale[2]; - r300->viewport_state->vte_control |= R300_VPORT_Z_SCALE_ENA; - } - if (state->translate[0] != 0.0f) { - r300->viewport_state->xoffset = state->translate[0]; - r300->viewport_state->vte_control |= R300_VPORT_X_OFFSET_ENA; - } - if (state->translate[1] != 0.0f) { - r300->viewport_state->yoffset = state->translate[1]; - r300->viewport_state->vte_control |= R300_VPORT_Y_OFFSET_ENA; - } - if (state->translate[2] != 0.0f) { - r300->viewport_state->zoffset = state->translate[2]; - r300->viewport_state->vte_control |= R300_VPORT_Z_OFFSET_ENA; - } - } else { - r300->viewport_state->vte_control = 0; - /* Have Draw do the actual transform. */ - draw_set_viewport_state(r300->draw, state); + if (state->scale[0] != 1.0f) { + assert(state->scale[0] != 0.0f); + r300->viewport_state->xscale = state->scale[0]; + r300->viewport_state->vte_control |= R300_VPORT_X_SCALE_ENA; + } + if (state->scale[1] != 1.0f) { + assert(state->scale[1] != 0.0f); + r300->viewport_state->yscale = state->scale[1]; + r300->viewport_state->vte_control |= R300_VPORT_Y_SCALE_ENA; + } + if (state->scale[2] != 1.0f) { + assert(state->scale[2] != 0.0f); + r300->viewport_state->zscale = state->scale[2]; + r300->viewport_state->vte_control |= R300_VPORT_Z_SCALE_ENA; + } + if (state->translate[0] != 0.0f) { + r300->viewport_state->xoffset = state->translate[0]; + r300->viewport_state->vte_control |= R300_VPORT_X_OFFSET_ENA; + } + if (state->translate[1] != 0.0f) { + r300->viewport_state->yoffset = state->translate[1]; + r300->viewport_state->vte_control |= R300_VPORT_Y_OFFSET_ENA; + } + if (state->translate[2] != 0.0f) { + r300->viewport_state->zoffset = state->translate[2]; + r300->viewport_state->vte_control |= R300_VPORT_Z_OFFSET_ENA; } r300->dirty_state |= R300_NEW_VIEWPORT; @@ -628,6 +643,7 @@ static void* r300_create_vs_state(struct pipe_context* pipe, struct r300_vertex_shader* vs = CALLOC_STRUCT(r300_vertex_shader); /* Copy state directly into shader. */ vs->state = *shader; + vs->state.tokens = tgsi_dup_tokens(shader->tokens); tgsi_scan_shader(shader->tokens, &vs->info); @@ -673,6 +689,7 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader) struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader; draw_delete_vertex_shader(r300->draw, vs->draw); + FREE(vs->state.tokens); FREE(shader); } else { draw_delete_vertex_shader(r300->draw, diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index c4c9784a00c..2477b30822b 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -64,6 +64,7 @@ static void r300_vs_tab_routes(struct r300_context* r300, break; case TGSI_SEMANTIC_FOG: fog = TRUE; + /* Fall through */ case TGSI_SEMANTIC_GENERIC: texs++; break; @@ -103,6 +104,9 @@ static void r300_vs_tab_routes(struct r300_context* r300, } } + /* XXX magic */ + assert(texs <= 8); + /* Do the actual vertex_info setup. * * vertex_info has four uints of hardware-specific data in it. @@ -140,21 +144,32 @@ static void r300_vs_tab_routes(struct r300_context* r300, vinfo->hwfmt[2] |= (R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i); } - for (i = 0; i < texs; i++) { + /* Init i right here, increment it if fog is enabled. + * This gets around a double-increment problem. */ + i = 0; + + if (fog) { + i++; draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, - draw_find_vs_output(r300->draw, TGSI_SEMANTIC_GENERIC, i)); + draw_find_vs_output(r300->draw, TGSI_SEMANTIC_FOG, 0)); vinfo->hwfmt[1] |= (R300_INPUT_CNTL_TC0 << i); vinfo->hwfmt[3] |= (4 << (3 * i)); } - if (fog) { - i++; + for (i; i < texs; i++) { draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, - draw_find_vs_output(r300->draw, TGSI_SEMANTIC_FOG, 0)); + draw_find_vs_output(r300->draw, TGSI_SEMANTIC_GENERIC, i)); vinfo->hwfmt[1] |= (R300_INPUT_CNTL_TC0 << i); vinfo->hwfmt[3] |= (4 << (3 * i)); } + /* Handle the case where the vertex shader will be generating some of + * the attribs based on its inputs. */ + if (r300screen->caps->has_tcl && + info->num_inputs < info->num_outputs) { + vinfo->num_attribs = info->num_inputs; + } + draw_compute_vertex_size(vinfo); } @@ -162,26 +177,40 @@ static void r300_vs_tab_routes(struct r300_context* r300, static void r300_vertex_psc(struct r300_context* r300, struct r300_vertex_format* vformat) { + struct r300_screen* r300screen = r300_screen(r300->context.screen); struct vertex_info* vinfo = &vformat->vinfo; int* tab = vformat->vs_tab; uint32_t temp; - int i; + int i, attrib_count; - debug_printf("r300: attrib count: %d\n", vinfo->num_attribs); - for (i = 0; i < vinfo->num_attribs; i++) { - debug_printf("r300: attrib: offset %d, interp %d, size %d," - " tab %d\n", vinfo->attrib[i].src_index, - vinfo->attrib[i].interp_mode, vinfo->attrib[i].emit, - tab[i]); + /* Vertex shaders have no semantics on their inputs, + * so PSC should just route stuff based on their info, + * and not on attrib information. */ + if (r300screen->caps->has_tcl) { + attrib_count = r300->vs->info.num_inputs; + debug_printf("r300: routing %d attribs in psc for vs\n", + attrib_count); + } else { + attrib_count = vinfo->num_attribs; + debug_printf("r300: attrib count: %d\n", attrib_count); + for (i = 0; i < attrib_count; i++) { + debug_printf("r300: attrib: offset %d, interp %d, size %d," + " tab %d\n", vinfo->attrib[i].src_index, + vinfo->attrib[i].interp_mode, vinfo->attrib[i].emit, + tab[i]); + } } - for (i = 0; i < vinfo->num_attribs; i++) { + for (i = 0; i < attrib_count; i++) { /* Make sure we have a proper destination for our attribute */ assert(tab[i] != -1); /* Add the attribute to the PSC table. */ - temp = translate_vertex_data_type(vinfo->attrib[i].emit) | - (tab[i] << R300_DST_VEC_LOC_SHIFT); + temp = r300screen->caps->has_tcl ? + R300_DATA_TYPE_FLOAT_4 : + translate_vertex_data_type(vinfo->attrib[i].emit); + temp |= tab[i] << R300_DST_VEC_LOC_SHIFT; + if (i & 1) { vformat->vap_prog_stream_cntl[i >> 1] &= 0x0000ffff; vformat->vap_prog_stream_cntl[i >> 1] |= temp << 16; @@ -206,7 +235,6 @@ static void r300_vertex_psc(struct r300_context* r300, /* Update the vertex format. */ static void r300_update_vertex_format(struct r300_context* r300) { - struct r300_screen* r300screen = r300_screen(r300->context.screen); struct r300_vertex_format vformat; int i; diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h index 91b93fc367e..22c8e199ae3 100644 --- a/src/gallium/drivers/r300/r300_state_inlines.h +++ b/src/gallium/drivers/r300/r300_state_inlines.h @@ -353,25 +353,6 @@ static INLINE uint32_t r300_translate_out_fmt(enum pipe_format format) /* Non-CSO state. (For now.) */ -static INLINE uint32_t r300_translate_gb_pipes(int pipe_count) -{ - switch (pipe_count) { - case 1: - return R300_GB_TILE_PIPE_COUNT_RV300; - break; - case 2: - return R300_GB_TILE_PIPE_COUNT_R300; - break; - case 3: - return R300_GB_TILE_PIPE_COUNT_R420_3P; - break; - case 4: - return R300_GB_TILE_PIPE_COUNT_R420; - break; - } - return 0; -} - static INLINE uint32_t translate_vertex_data_type(int type) { switch (type) { case EMIT_1F: diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c index 8bd9b41bd74..430129d5bd2 100644 --- a/src/gallium/drivers/r300/r300_state_invariant.c +++ b/src/gallium/drivers/r300/r300_state_invariant.c @@ -34,36 +34,22 @@ void r300_emit_invariant_state(struct r300_context* r300) struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps; CS_LOCALS(r300); - BEGIN_CS(30 + (caps->has_tcl ? 2: 0)); + BEGIN_CS(22 + (caps->has_tcl ? 2: 0)); /*** Graphics Backend (GB) ***/ /* Various GB enables */ OUT_CS_REG(R300_GB_ENABLE, 0x0); - /* Subpixel multisampling for AA */ - OUT_CS_REG(R300_GB_MSPOS0, 0x66666666); - OUT_CS_REG(R300_GB_MSPOS1, 0x66666666); - /* GB tile config and pipe setup */ - OUT_CS_REG(R300_GB_TILE_CONFIG, R300_GB_TILE_DISABLE | - r300_translate_gb_pipes(caps->num_frag_pipes)); + /* Subpixel multisampling for AA + * These are commented out because glisse's CS checker doesn't like them. + * I presume these will be re-enabled later. + * OUT_CS_REG(R300_GB_MSPOS0, 0x66666666); + * OUT_CS_REG(R300_GB_MSPOS1, 0x6666666); + */ /* Source of fog depth */ OUT_CS_REG(R300_GB_SELECT, R300_GB_FOG_SELECT_1_1_W); /* AA enable */ OUT_CS_REG(R300_GB_AA_CONFIG, 0x0); - /*** Geometry Assembly (GA) ***/ - /* GA errata fixes. */ - if (caps->is_r500) { - OUT_CS_REG(R300_GA_ENHANCE, - R300_GA_ENHANCE_DEADLOCK_CNTL_PREVENT_TCL | - R300_GA_ENHANCE_FASTSYNC_CNTL_ENABLE | - R500_GA_ENHANCE_REG_READWRITE_ENABLE | - R500_GA_ENHANCE_REG_NOSTALL_ENABLE); - } else { - OUT_CS_REG(R300_GA_ENHANCE, - R300_GA_ENHANCE_DEADLOCK_CNTL_PREVENT_TCL | - R300_GA_ENHANCE_FASTSYNC_CNTL_ENABLE); - } - /*** Fog (FG) ***/ OUT_CS_REG(R300_FG_FOG_BLEND, 0x0); OUT_CS_REG(R300_FG_FOG_COLOR_R, 0x0); @@ -86,7 +72,7 @@ void r300_emit_invariant_state(struct r300_context* r300) END_CS; /* XXX unsorted stuff from surface_fill */ - BEGIN_CS(79 + (caps->has_tcl ? 7 : 0)); + BEGIN_CS(71 + (caps->has_tcl ? 5 : 0) + (caps->is_r500 ? 4 : 0)); /* Flush PVS. */ OUT_CS_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0x0); @@ -94,30 +80,26 @@ void r300_emit_invariant_state(struct r300_context* r300) R300_VPORT_X_OFFSET_ENA | R300_VPORT_Y_SCALE_ENA | R300_VPORT_Y_OFFSET_ENA | R300_VPORT_Z_SCALE_ENA | R300_VPORT_Z_OFFSET_ENA | R300_VTX_W0_FMT); - /* XXX endian */ if (caps->has_tcl) { - OUT_CS_REG(R300_VAP_CNTL_STATUS, R300_VC_NO_SWAP); - OUT_CS_REG(R300_VAP_CLIP_CNTL, R300_CLIP_DISABLE | - R300_PS_UCP_MODE_CLIP_AS_TRIFAN); OUT_CS_REG_SEQ(R300_VAP_GB_VERT_CLIP_ADJ, 4); OUT_CS_32F(1.0); OUT_CS_32F(1.0); OUT_CS_32F(1.0); OUT_CS_32F(1.0); - } else { - OUT_CS_REG(R300_VAP_CNTL_STATUS, R300_VC_NO_SWAP | - R300_VAP_TCL_BYPASS); } /* XXX point tex stuffing */ OUT_CS_REG_SEQ(R300_GA_POINT_S0, 1); OUT_CS_32F(0.0); OUT_CS_REG_SEQ(R300_GA_POINT_S1, 1); OUT_CS_32F(1.0); + /* XXX line tex stuffing */ + OUT_CS_REG_SEQ(R300_GA_LINE_S0, 1); + OUT_CS_32F(0.0); + OUT_CS_REG_SEQ(R300_GA_LINE_S1, 1); + OUT_CS_32F(1.0); OUT_CS_REG(R300_GA_TRIANGLE_STIPPLE, 0x5 | (0x5 << R300_GA_TRIANGLE_STIPPLE_Y_SHIFT_SHIFT)); /* XXX this big chunk should be refactored into rs_state */ - OUT_CS_REG(R300_GA_LINE_S0, 0x00000000); - OUT_CS_REG(R300_GA_LINE_S1, 0x3F800000); OUT_CS_REG(R300_GA_SOLID_RG, 0x00000000); OUT_CS_REG(R300_GA_SOLID_BA, 0x00000000); OUT_CS_REG(R300_GA_POLY_MODE, 0x00000000); @@ -133,8 +115,10 @@ void r300_emit_invariant_state(struct r300_context* r300) OUT_CS_REG(R300_RB3D_CCTL, 0x00000000); OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0x0000000F); OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, 0x00000000); - OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x00000000); - OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFFFFFFFF); + if (caps->is_r500) { + OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x00000000); + OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFFFFFFFF); + } OUT_CS_REG(R300_ZB_FORMAT, 0x00000002); OUT_CS_REG(R300_ZB_ZCACHE_CTLSTAT, 0x00000003); OUT_CS_REG(R300_ZB_BW_CNTL, 0x00000000); @@ -144,8 +128,6 @@ void r300_emit_invariant_state(struct r300_context* r300) OUT_CS_REG(R300_VAP_VTX_STATE_CNTL, 0x1); OUT_CS_REG(R300_VAP_VSM_VTX_ASSM, 0x405); OUT_CS_REG(R300_SE_VTE_CNTL, 0x0000043F); - /* Vertex size. */ - OUT_CS_REG(R300_VAP_VTX_SIZE, 0x8); /* XXX */ OUT_CS_REG(R300_SC_CLIP_RULE, 0xaaaa); diff --git a/src/gallium/drivers/r300/r300_surface.c b/src/gallium/drivers/r300/r300_surface.c index 4dd5b8af99a..25168ce5e95 100644 --- a/src/gallium/drivers/r300/r300_surface.c +++ b/src/gallium/drivers/r300/r300_surface.c @@ -23,30 +23,36 @@ #include "r300_surface.h" -static void r300_surface_setup(struct pipe_context* pipe, - struct pipe_surface* dest, +static void r300_surface_setup(struct r300_context* r300, + struct r300_texture* dest, unsigned x, unsigned y, unsigned w, unsigned h) { - struct r300_context* r300 = r300_context(pipe); - struct r300_capabilities* caps = r300_screen(pipe->screen)->caps; - struct r300_texture* tex = (struct r300_texture*)dest->texture; - unsigned pixpitch = tex->stride / tex->tex.block.size; + struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps; + unsigned pixpitch = dest->stride / dest->tex.block.size; CS_LOCALS(r300); - /* Make sure our target BO is okay. */ - r300->winsys->add_buffer(r300->winsys, tex->buffer, - 0, RADEON_GEM_DOMAIN_VRAM); - if (r300->winsys->validate(r300->winsys)) { - r300->context.flush(&r300->context, 0, NULL); - } - r300_emit_blend_state(r300, &blend_clear_state); r300_emit_blend_color_state(r300, &blend_color_clear_state); r300_emit_dsa_state(r300, &dsa_clear_state); r300_emit_rs_state(r300, &rs_clear_state); - BEGIN_CS(15); + BEGIN_CS(24); + + /* Viewport setup */ + OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6); + OUT_CS_32F((float)w); + OUT_CS_32F((float)x); + OUT_CS_32F((float)h); + OUT_CS_32F((float)y); + OUT_CS_32F(1.0); + OUT_CS_32F(0.0); + + OUT_CS_REG(R300_VAP_VTE_CNTL, R300_VPORT_X_SCALE_ENA | + R300_VPORT_X_OFFSET_ENA | + R300_VPORT_Y_SCALE_ENA | + R300_VPORT_Y_OFFSET_ENA | + R300_VTX_XY_FMT | R300_VTX_Z_FMT); /* Pixel scissors. */ OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2); @@ -71,9 +77,9 @@ static void r300_surface_setup(struct pipe_context* pipe, /* Setup colorbuffer. */ OUT_CS_REG_SEQ(R300_RB3D_COLOROFFSET0, 1); - OUT_CS_RELOC(tex->buffer, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0); + OUT_CS_RELOC(dest->buffer, 0, 0, RADEON_GEM_DOMAIN_VRAM, 0); OUT_CS_REG(R300_RB3D_COLORPITCH0, pixpitch | - r300_translate_colorformat(tex->tex.format)); + r300_translate_colorformat(dest->tex.format)); OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0xf); END_CS; @@ -93,6 +99,7 @@ static void r300_surface_fill(struct pipe_context* pipe, struct r300_capabilities* caps = r300_screen(pipe->screen)->caps; struct r300_texture* tex = (struct r300_texture*)dest->texture; unsigned pixpitch = tex->stride / tex->tex.block.size; + boolean invalid = FALSE; CS_LOCALS(r300); a = (float)((color >> 24) & 0xff) / 255.0f; @@ -105,12 +112,30 @@ static void r300_surface_fill(struct pipe_context* pipe, /* Fallback? */ if (FALSE) { +fallback: debug_printf("r300: Falling back on surface clear..."); util_surface_fill(pipe, dest, x, y, w, h, color); return; } - r300_surface_setup(r300, dest, x, y, w, h); + /* Make sure our target BO is okay. */ +validate: + if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, + 0, RADEON_GEM_DOMAIN_VRAM)) { + r300->context.flush(&r300->context, 0, NULL); + goto validate; + } + if (!r300->winsys->validate(r300->winsys)) { + r300->context.flush(&r300->context, 0, NULL); + if (invalid) { + debug_printf("r300: Stuck in validation loop, gonna fallback."); + goto fallback; + } + invalid = TRUE; + goto validate; + } + + r300_surface_setup(r300, tex, x, y, w, h); /* Vertex shader setup */ if (caps->has_tcl) { @@ -127,14 +152,14 @@ static void r300_surface_fill(struct pipe_context* pipe, /* Fragment shader setup */ if (caps->is_r500) { - r500_emit_fragment_shader(r300, &r500_passthrough_fragment_shader); - r300_emit_rs_block_state(r300, &r500_rs_block_clear_state); + r500_emit_fragment_shader(r300, &r5xx_passthrough_fragment_shader); + r300_emit_rs_block_state(r300, &r5xx_rs_block_clear_state); } else { - r300_emit_fragment_shader(r300, &r300_passthrough_fragment_shader); - r300_emit_rs_block_state(r300, &r300_rs_block_clear_state); + r300_emit_fragment_shader(r300, &r3xx_passthrough_fragment_shader); + r300_emit_rs_block_state(r300, &r3xx_rs_block_clear_state); } - BEGIN_CS(31); + BEGIN_CS(26); /* VAP stream control, mapping from input memory to PVS/RS memory */ if (caps->has_tcl) { @@ -161,27 +186,21 @@ static void r300_surface_fill(struct pipe_context* pipe, /* Disable textures */ OUT_CS_REG(R300_TX_ENABLE, 0x0); - /* Viewport setup */ - OUT_CS_REG_SEQ(R300_SE_VPORT_XSCALE, 6); - OUT_CS_32F(1.0); - OUT_CS_32F((float)x); - OUT_CS_32F(1.0); - OUT_CS_32F((float)y); - OUT_CS_32F(1.0); - OUT_CS_32F(0.0); - /* The size of the point we're about to draw, in sixths of pixels */ OUT_CS_REG(R300_GA_POINT_SIZE, - ((h * 6) & R300_POINTSIZE_Y_MASK) | + ((h * 6) & R300_POINTSIZE_Y_MASK) | ((w * 6) << R300_POINTSIZE_X_SHIFT)); + /* Vertex size. */ + OUT_CS_REG(R300_VAP_VTX_SIZE, 0x8); + /* Packet3 with our point vertex */ OUT_CS_PKT3(R200_3D_DRAW_IMMD_2, 8); OUT_CS(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING | (1 << R300_PRIM_NUM_VERTICES_SHIFT)); /* Position */ - OUT_CS_32F(w / 2.0); - OUT_CS_32F(h / 2.0); + OUT_CS_32F(0.5); + OUT_CS_32F(0.5); OUT_CS_32F(1.0); OUT_CS_32F(1.0); /* Color */ @@ -190,11 +209,7 @@ static void r300_surface_fill(struct pipe_context* pipe, OUT_CS_32F(b); OUT_CS_32F(a); - /* XXX figure out why this is 0xA and not 0x2 */ OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA); - /* XXX OUT_CS_REG(R300_ZB_ZCACHE_CTLSTAT, - R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE | - R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE); */ END_CS; @@ -213,27 +228,56 @@ static void r300_surface_copy(struct pipe_context* pipe, struct r300_texture* srctex = (struct r300_texture*)src->texture; struct r300_texture* desttex = (struct r300_texture*)dest->texture; unsigned pixpitch = srctex->stride / srctex->tex.block.size; + boolean invalid = FALSE; + float fsrcx = srcx, fsrcy = srcy, fdestx = destx, fdesty = desty; CS_LOCALS(r300); debug_printf("r300: Copying surface %p at (%d,%d) to %p at (%d, %d)," " dimensions %dx%d (pixel pitch %d)\n", src, srcx, srcy, dest, destx, desty, w, h, pixpitch); - if ((srctex == desttex) && + if ((srctex->buffer == desttex->buffer) && ((destx < srcx + w) || (srcx < destx + w)) && ((desty < srcy + h) || (srcy < desty + h))) { +fallback: debug_printf("r300: Falling back on surface_copy\n"); util_surface_copy(pipe, FALSE, dest, destx, desty, src, srcx, srcy, w, h); } - r300_emit_sampler(r300, &r300_sampler_copy_state, 0); - r300_emit_texture(r300, srctex, 0); + /* Add our target BOs to the list. */ +validate: + if (!r300->winsys->add_buffer(r300->winsys, srctex->buffer, + RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) { + r300->context.flush(&r300->context, 0, NULL); + goto validate; + } + if (!r300->winsys->add_buffer(r300->winsys, desttex->buffer, + 0, RADEON_GEM_DOMAIN_VRAM)) { + r300->context.flush(&r300->context, 0, NULL); + goto validate; + } + if (!r300->winsys->validate(r300->winsys)) { + r300->context.flush(&r300->context, 0, NULL); + if (invalid) { + debug_printf("r300: Stuck in validation loop, gonna fallback."); + goto fallback; + } + invalid = TRUE; + goto validate; + } + + r300_surface_setup(r300, desttex, destx, desty, w, h); + + /* Setup the texture. */ + r300_emit_texture(r300, &r300_sampler_copy_state, srctex, 0); + + /* Flush and enable. */ r300_flush_textures(r300); /* Vertex shader setup */ if (caps->has_tcl) { - r300_emit_vertex_shader(r300, &r300_texture_vertex_shader); + r300_emit_vertex_shader(r300, &r300_passthrough_vertex_shader); } else { BEGIN_CS(4); OUT_CS_REG(R300_VAP_CNTL_STATUS, R300_VAP_TCL_BYPASS); @@ -246,13 +290,14 @@ static void r300_surface_copy(struct pipe_context* pipe, /* Fragment shader setup */ if (caps->is_r500) { - r500_emit_fragment_shader(r300, &r500_texture_fragment_shader); - r300_emit_rs_block_state(r300, &r500_rs_block_copy_state); + r500_emit_fragment_shader(r300, &r5xx_texture_fragment_shader); + r300_emit_rs_block_state(r300, &r5xx_rs_block_copy_state); } else { - r300_emit_fragment_shader(r300, &r300_texture_fragment_shader); - r300_emit_rs_block_state(r300, &r300_rs_block_copy_state); + r300_emit_fragment_shader(r300, &r3xx_texture_fragment_shader); + r300_emit_rs_block_state(r300, &r3xx_rs_block_copy_state); } + BEGIN_CS(30); /* VAP stream control, mapping from input memory to PVS/RS memory */ if (caps->has_tcl) { OUT_CS_REG(R300_VAP_PROG_STREAM_CNTL_0, @@ -275,33 +320,38 @@ static void r300_surface_copy(struct pipe_context* pipe, /* Two components of texture 0 */ OUT_CS_REG(R300_VAP_OUTPUT_VTX_FMT_1, 0x2); + /* Vertex size. */ + OUT_CS_REG(R300_VAP_VTX_SIZE, 0x4); + /* Packet3 with our texcoords */ - OUT_CS_PKT3(R200_3D_DRAW_IMMD_2, 8); + OUT_CS_PKT3(R200_3D_DRAW_IMMD_2, 16); OUT_CS(R300_PRIM_TYPE_QUADS | R300_PRIM_WALK_RING | (4 << R300_PRIM_NUM_VERTICES_SHIFT)); /* (x , y ) */ - OUT_CS_32F((float)destx); - OUT_CS_32F((float)desty); - OUT_CS_32F((float)srcx); - OUT_CS_32F((float)srcy); + OUT_CS_32F(fdestx / dest->width); + OUT_CS_32F(fdesty / dest->height); + OUT_CS_32F(fsrcx / src->width); + OUT_CS_32F(fsrcy / src->height); /* (x , y + h) */ - OUT_CS_32F((float)destx); - OUT_CS_32F((float)(desty + h)); - OUT_CS_32F((float)srcx); - OUT_CS_32F((float)(srcy + h)); + OUT_CS_32F(fdestx / dest->width); + OUT_CS_32F((fdesty + h) / dest->height); + OUT_CS_32F(fsrcx / src->width); + OUT_CS_32F((fsrcy + h) / src->height); /* (x + w, y + h) */ - OUT_CS_32F((float)(destx + w)); - OUT_CS_32F((float)(desty + h)); - OUT_CS_32F((float)(srcx + w)); - OUT_CS_32F((float)(srcy + h)); + OUT_CS_32F((fdestx + w) / dest->width); + OUT_CS_32F((fdesty + h) / dest->height); + OUT_CS_32F((fsrcx + w) / src->width); + OUT_CS_32F((fsrcy + h) / src->height); /* (x + w, y ) */ - OUT_CS_32F((float)(destx + w)); - OUT_CS_32F((float)desty); - OUT_CS_32F((float)(srcx + w)); - OUT_CS_32F((float)srcy); + OUT_CS_32F((fdestx + w) / dest->width); + OUT_CS_32F(fdesty / dest->height); + OUT_CS_32F((fsrcx + w) / src->width); + OUT_CS_32F(fsrcy / src->height); OUT_CS_REG(R300_RB3D_DSTCACHE_CTLSTAT, 0xA); + END_CS; + r300->dirty_hw++; } diff --git a/src/gallium/drivers/r300/r300_surface.h b/src/gallium/drivers/r300/r300_surface.h index 894def07aa8..d01f0b143f5 100644 --- a/src/gallium/drivers/r300/r300_surface.h +++ b/src/gallium/drivers/r300/r300_surface.h @@ -31,8 +31,8 @@ #include "r300_context.h" #include "r300_cs.h" #include "r300_emit.h" -#include "r300_state_shader.h" -#include "r300_state_tcl.h" +#include "r300_fs.h" +#include "r300_vs.h" #include "r300_state_inlines.h" static struct r300_blend_state blend_clear_state = { @@ -72,7 +72,7 @@ static struct r300_rs_state rs_clear_state = { .color_control = R300_SHADE_MODEL_FLAT, }; -static struct r300_rs_block r300_rs_block_clear_state = { +static struct r300_rs_block r3xx_rs_block_clear_state = { .ip[0] = R500_RS_SEL_S(R300_RS_SEL_K0) | R500_RS_SEL_T(R300_RS_SEL_K0) | R500_RS_SEL_R(R300_RS_SEL_K0) | @@ -82,7 +82,7 @@ static struct r300_rs_block r300_rs_block_clear_state = { .inst_count = 0, }; -static struct r300_rs_block r500_rs_block_clear_state = { +static struct r300_rs_block r5xx_rs_block_clear_state = { .ip[0] = R500_RS_SEL_S(R500_RS_IP_PTR_K0) | R500_RS_SEL_T(R500_RS_IP_PTR_K0) | R500_RS_SEL_R(R500_RS_IP_PTR_K0) | @@ -94,24 +94,24 @@ static struct r300_rs_block r500_rs_block_clear_state = { /* The following state is used for surface_copy only. */ -static struct r300_rs_block r300_rs_block_copy_state = { +static struct r300_rs_block r3xx_rs_block_copy_state = { .ip[0] = R500_RS_SEL_S(R300_RS_SEL_K0) | R500_RS_SEL_T(R300_RS_SEL_K0) | R500_RS_SEL_R(R300_RS_SEL_K0) | R500_RS_SEL_Q(R300_RS_SEL_K1), .inst[0] = R300_RS_INST_COL_CN_WRITE, .count = R300_IT_COUNT(2) | R300_IC_COUNT(0) | R300_HIRES_EN, - .inst_count = R300_RS_TX_OFFSET(6), + .inst_count = R300_RS_TX_OFFSET(0), }; -static struct r300_rs_block r500_rs_block_copy_state = { +static struct r300_rs_block r5xx_rs_block_copy_state = { .ip[0] = R500_RS_SEL_S(0) | R500_RS_SEL_T(1) | R500_RS_SEL_R(R500_RS_IP_PTR_K0) | R500_RS_SEL_Q(R500_RS_IP_PTR_K1), .inst[0] = R500_RS_INST_TEX_CN_WRITE, .count = R300_IT_COUNT(2) | R300_IC_COUNT(0) | R300_HIRES_EN, - .inst_count = R300_RS_TX_OFFSET(6), + .inst_count = R300_RS_TX_OFFSET(0), }; static struct r300_sampler_state r300_sampler_copy_state = { diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index fe91f4e1844..daf1647bee8 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -22,6 +22,8 @@ #include "r300_texture.h" +/* XXX maths need to go to util */ + static int minify(int i) { return MAX2(1, i >> 1); @@ -30,25 +32,32 @@ static int minify(int i) static void r300_setup_texture_state(struct r300_texture* tex, unsigned width, unsigned height, - unsigned pitch) + unsigned pitch, + unsigned levels) { struct r300_texture_state* state = &tex->state; state->format0 = R300_TX_WIDTH((width - 1) & 0x7ff) | - R300_TX_HEIGHT((height - 1) & 0x7ff) | R300_TX_PITCH_EN; + R300_TX_HEIGHT((height - 1) & 0x7ff) | + R300_TX_NUM_LEVELS(levels) | + R300_TX_PITCH_EN; /* XXX */ - state->format1 = R300_TX_FORMAT_A8R8G8B8; + state->format1 = r300_translate_texformat(tex->tex.format); state->format2 = pitch - 1; - /* XXX + /* Assume (somewhat foolishly) that oversized textures will + * not be permitted by the state tracker. */ if (width > 2048) { - state->pitch |= R300_TXWIDTH_11; + state->format2 |= R500_TXWIDTH_BIT11; } if (height > 2048) { - state->pitch |= R300_TXHEIGHT_11; - } */ + state->format2 |= R500_TXHEIGHT_BIT11; + } + + debug_printf("r300: Set texture state (%dx%d, pitch %d, %d levels)\n", + width, height, pitch, levels); } static void r300_setup_miptree(struct r300_texture* tex) @@ -65,16 +74,26 @@ static void r300_setup_miptree(struct r300_texture* tex) } base->nblocksx[i] = pf_get_nblocksx(&base->block, base->width[i]); - base->nblocksy[i] = pf_get_nblocksy(&base->block, base->width[i]); - - /* Radeons enjoy things in multiples of 32. */ - /* XXX this can be 32 when POT */ - stride = (base->nblocksx[i] * base->block.size + 63) & ~63; + base->nblocksy[i] = pf_get_nblocksy(&base->block, base->height[i]); + + /* Radeons enjoy things in multiples of 64. + * + * XXX + * POT, uncompressed, unmippmapped textures can be aligned to 32, + * instead of 64. */ + stride = align( + (base->nblocksx[i] * base->block.size) / base->block.width, + 32); size = stride * base->nblocksy[i] * base->depth[i]; - tex->offset[i] = (tex->size + 63) & ~63; - tex->size = tex->offset[i] + size; + tex->offset[i] = align(tex->size, 32); + tex->size += tex->offset[i] + size; + debug_printf("r300: Texture miptree: Level %d " + "(%dx%dx%d px, pitch %d bytes)\n", + i, base->width[i], base->height[i], base->depth[i], + stride); + /* Save stride of first level to the texture. */ if (i == 0) { tex->stride = stride; } @@ -86,8 +105,6 @@ static struct pipe_texture* r300_texture_create(struct pipe_screen* screen, const struct pipe_texture* template) { - /* XXX struct r300_screen* r300screen = r300_screen(screen); */ - struct r300_texture* tex = CALLOC_STRUCT(r300_texture); if (!tex) { @@ -100,11 +117,10 @@ static struct pipe_texture* r300_setup_miptree(tex); - /* XXX */ - r300_setup_texture_state(tex, tex->tex.width[0], tex->tex.height[0], - tex->tex.width[0]); + r300_setup_texture_state(tex, template->width[0], template->height[0], + template->width[0], template->last_level); - tex->buffer = screen->buffer_create(screen, 64, + tex->buffer = screen->buffer_create(screen, 1024, PIPE_BUFFER_USAGE_PIXEL, tex->size); @@ -166,6 +182,7 @@ static struct pipe_texture* { struct r300_texture* tex; + /* XXX we should start doing mips now... */ if (base->target != PIPE_TEXTURE_2D || base->last_level != 0 || base->depth[0] != 1) { @@ -183,8 +200,9 @@ static struct pipe_texture* tex->stride = *stride; + /* XXX */ r300_setup_texture_state(tex, tex->tex.width[0], tex->tex.height[0], - tex->stride); + tex->stride, 0); pipe_buffer_reference(&tex->buffer, buffer); diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index 98fb5c9a08f..3b56f0307c0 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -32,6 +32,52 @@ void r300_init_screen_texture_functions(struct pipe_screen* screen); +/* Note the signature of R300_EASY_TX_FORMAT(A, R, G, B, FORMAT)... */ +static INLINE uint32_t r300_translate_texformat(enum pipe_format format) +{ + switch (format) { + /* X8 */ + case PIPE_FORMAT_I8_UNORM: + return R300_EASY_TX_FORMAT(X, X, X, X, X8); + /* W8Z8Y8X8 */ + case PIPE_FORMAT_A8R8G8B8_UNORM: + return R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8); + case PIPE_FORMAT_R8G8B8A8_UNORM: + return R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8); + case PIPE_FORMAT_A8R8G8B8_SRGB: + return R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8) | + R300_TX_FORMAT_GAMMA; + case PIPE_FORMAT_R8G8B8A8_SRGB: + return R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8) | + R300_TX_FORMAT_GAMMA; + /* DXT1 */ + case PIPE_FORMAT_DXT1_RGB: + return R300_EASY_TX_FORMAT(X, Y, Z, ONE, DXT1); + case PIPE_FORMAT_DXT1_RGBA: + return R300_EASY_TX_FORMAT(X, Y, Z, W, DXT1); + /* DXT3 */ + case PIPE_FORMAT_DXT3_RGBA: + return R300_EASY_TX_FORMAT(X, Y, Z, W, DXT3); + /* DXT5 */ + case PIPE_FORMAT_DXT5_RGBA: + return R300_EASY_TX_FORMAT(Y, Z, W, X, DXT5); + /* YVYU422 */ + case PIPE_FORMAT_YCBCR: + return R300_EASY_TX_FORMAT(X, Y, Z, ONE, YVYU422) | + R300_TX_FORMAT_YUV_TO_RGB; + /* W24_FP */ + case PIPE_FORMAT_Z24S8_UNORM: + return R300_EASY_TX_FORMAT(X, X, X, X, W24_FP); + default: + debug_printf("r300: Implementation error: " + "Got unsupported texture format %s in %s\n", + pf_name(format), __FUNCTION__); + assert(0); + break; + } + return 0; +} + #ifndef R300_WINSYS_H boolean r300_get_texture_buffer(struct pipe_texture* texture, diff --git a/src/gallium/drivers/r300/r300_state_tcl.c b/src/gallium/drivers/r300/r300_vs.c index d84912de48f..741a1b69895 100644 --- a/src/gallium/drivers/r300/r300_state_tcl.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -20,7 +20,7 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "r300_state_tcl.h" +#include "r300_vs.h" static void r300_vs_declare(struct r300_vs_asm* assembler, struct tgsi_full_declaration* decl) @@ -71,16 +71,13 @@ static INLINE unsigned r300_vs_src_type(struct r300_vs_asm* assembler, { switch (src->File) { case TGSI_FILE_NULL: - /* Probably a zero or one swizzle */ - return R300_PVS_SRC_REG_INPUT; - break; case TGSI_FILE_INPUT: + /* Probably a zero or one swizzle */ return R300_PVS_SRC_REG_INPUT; - break; case TGSI_FILE_TEMPORARY: return R300_PVS_SRC_REG_TEMPORARY; - break; case TGSI_FILE_CONSTANT: + case TGSI_FILE_IMMEDIATE: return R300_PVS_SRC_REG_CONSTANT; default: debug_printf("r300: vs: Unimplemented src type %d\n", src->File); @@ -89,16 +86,32 @@ static INLINE unsigned r300_vs_src_type(struct r300_vs_asm* assembler, return 0; } +static INLINE unsigned r300_vs_src(struct r300_vs_asm* assembler, + struct tgsi_src_register* src) +{ + switch (src->File) { + case TGSI_FILE_NULL: + case TGSI_FILE_INPUT: + case TGSI_FILE_TEMPORARY: + case TGSI_FILE_CONSTANT: + return src->Index; + case TGSI_FILE_IMMEDIATE: + return src->Index + assembler->imm_offset; + default: + debug_printf("r300: vs: Unimplemented src type %d\n", src->File); + break; + } + return 0; +} + static INLINE unsigned r300_vs_dst_type(struct r300_vs_asm* assembler, struct tgsi_dst_register* dst) { switch (dst->File) { case TGSI_FILE_TEMPORARY: return R300_PVS_DST_REG_TEMPORARY; - break; case TGSI_FILE_OUTPUT: return R300_PVS_DST_REG_OUT; - break; default: debug_printf("r300: vs: Unimplemented dst type %d\n", dst->File); break; @@ -112,10 +125,8 @@ static INLINE unsigned r300_vs_dst(struct r300_vs_asm* assembler, switch (dst->File) { case TGSI_FILE_TEMPORARY: return dst->Index; - break; case TGSI_FILE_OUTPUT: return assembler->tab[dst->Index]; - break; default: debug_printf("r300: vs: Unimplemented dst %d\n", dst->File); break; @@ -133,8 +144,15 @@ static uint32_t r300_vs_op(unsigned op) return R300_VE_MULTIPLY; case TGSI_OPCODE_ADD: case TGSI_OPCODE_MOV: + case TGSI_OPCODE_SUB: case TGSI_OPCODE_SWZ: return R300_VE_ADD; + case TGSI_OPCODE_MAX: + return R300_VE_MAXIMUM; + case TGSI_OPCODE_SLT: + return R300_VE_SET_LESS_THAN; + case TGSI_OPCODE_RSQ: + return R300_PVS_DST_MATH_INST | R300_ME_RECIP_DX; case TGSI_OPCODE_MAD: return R300_PVS_DST_MACRO_INST | R300_PVS_MACRO_OP_2CLK_MADD; default: @@ -146,51 +164,78 @@ static uint32_t r300_vs_op(unsigned op) static uint32_t r300_vs_swiz(struct tgsi_full_src_register* reg) { if (reg->SrcRegister.Extended) { - return reg->SrcRegisterExtSwz.ExtSwizzleX | + return (reg->SrcRegister.Negate ? (0xf << 12) : 0) | + reg->SrcRegisterExtSwz.ExtSwizzleX | (reg->SrcRegisterExtSwz.ExtSwizzleY << 3) | (reg->SrcRegisterExtSwz.ExtSwizzleZ << 6) | (reg->SrcRegisterExtSwz.ExtSwizzleW << 9); } else { - return reg->SrcRegister.SwizzleX | + return (reg->SrcRegister.Negate ? (0xf << 12) : 0) | + reg->SrcRegister.SwizzleX | (reg->SrcRegister.SwizzleY << 3) | (reg->SrcRegister.SwizzleZ << 6) | (reg->SrcRegister.SwizzleW << 9); } } +/* XXX icky icky icky icky */ +static uint32_t r300_vs_scalar_swiz(struct tgsi_full_src_register* reg) +{ + if (reg->SrcRegister.Extended) { + return (reg->SrcRegister.Negate ? (0xf << 12) : 0) | + reg->SrcRegisterExtSwz.ExtSwizzleX | + (reg->SrcRegisterExtSwz.ExtSwizzleX << 3) | + (reg->SrcRegisterExtSwz.ExtSwizzleX << 6) | + (reg->SrcRegisterExtSwz.ExtSwizzleX << 9); + } else { + return (reg->SrcRegister.Negate ? (0xf << 12) : 0) | + reg->SrcRegister.SwizzleX | + (reg->SrcRegister.SwizzleX << 3) | + (reg->SrcRegister.SwizzleX << 6) | + (reg->SrcRegister.SwizzleX << 9); + } +} + +/* XXX scalar stupidity */ static void r300_vs_emit_inst(struct r300_vertex_shader* vs, struct r300_vs_asm* assembler, struct tgsi_full_src_register* src, struct tgsi_full_dst_register* dst, unsigned op, - unsigned count) + unsigned count, + boolean is_scalar) { int i = vs->instruction_count; vs->instructions[i].inst0 = R300_PVS_DST_OPCODE(r300_vs_op(op)) | R300_PVS_DST_REG_TYPE(r300_vs_dst_type(assembler, &dst->DstRegister)) | R300_PVS_DST_OFFSET(r300_vs_dst(assembler, &dst->DstRegister)) | - R300_PVS_DST_WE_XYZW; + R300_PVS_DST_WE(dst->DstRegister.WriteMask); switch (count) { case 3: vs->instructions[i].inst3 = R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler, &src[2].SrcRegister)) | - R300_PVS_SRC_OFFSET(src[2].SrcRegister.Index) | + R300_PVS_SRC_OFFSET(r300_vs_src(assembler, + &src[2].SrcRegister)) | R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[2])); /* Fall through */ case 2: vs->instructions[i].inst2 = R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler, &src[1].SrcRegister)) | - R300_PVS_SRC_OFFSET(src[1].SrcRegister.Index) | + R300_PVS_SRC_OFFSET(r300_vs_src(assembler, + &src[1].SrcRegister)) | R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[1])); /* Fall through */ case 1: vs->instructions[i].inst1 = R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler, &src[0].SrcRegister)) | - R300_PVS_SRC_OFFSET(src[0].SrcRegister.Index) | - R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[0])); + R300_PVS_SRC_OFFSET(r300_vs_src(assembler, + &src[0].SrcRegister)) | + /* XXX the icky, it burns */ + R300_PVS_SRC_SWIZZLE(is_scalar ? r300_vs_scalar_swiz(&src[0]) + : r300_vs_swiz(&src[0])); break; } vs->instruction_count++; @@ -201,11 +246,22 @@ static void r300_vs_instruction(struct r300_vertex_shader* vs, struct tgsi_full_instruction* inst) { switch (inst->Instruction.Opcode) { + case TGSI_OPCODE_RSQ: + r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, + &inst->FullDstRegisters[0], inst->Instruction.Opcode, + 1, TRUE); + break; + case TGSI_OPCODE_SUB: + inst->FullSrcRegisters[1].SrcRegister.Negate = + !inst->FullSrcRegisters[1].SrcRegister.Negate; + /* Fall through */ case TGSI_OPCODE_ADD: case TGSI_OPCODE_MUL: + case TGSI_OPCODE_MAX: + case TGSI_OPCODE_SLT: r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, &inst->FullDstRegisters[0], inst->Instruction.Opcode, - 2); + 2, FALSE); break; case TGSI_OPCODE_DP3: /* Set alpha swizzle to zero for src0 and src1 */ @@ -235,19 +291,19 @@ static void r300_vs_instruction(struct r300_vertex_shader* vs, case TGSI_OPCODE_DP4: r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, &inst->FullDstRegisters[0], inst->Instruction.Opcode, - 2); + 2, FALSE); break; case TGSI_OPCODE_MOV: case TGSI_OPCODE_SWZ: inst->FullSrcRegisters[1] = r300_constant_zero; r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, &inst->FullDstRegisters[0], inst->Instruction.Opcode, - 2); + 2, FALSE); break; case TGSI_OPCODE_MAD: r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, &inst->FullDstRegisters[0], inst->Instruction.Opcode, - 3); + 3, FALSE); break; case TGSI_OPCODE_END: break; @@ -278,6 +334,8 @@ static void r300_vs_init(struct r300_vertex_shader* vs, break; } } + + vs->instruction_count = 0; } void r300_translate_vertex_shader(struct r300_context* r300, @@ -320,8 +378,7 @@ void r300_translate_vertex_shader(struct r300_context* r300, for (i = 0; i < 4; i++) { consts->constants[assembler->imm_offset + assembler->imm_count][i] = - parser.FullToken.FullImmediate.u.ImmediateFloat32[i] - .Float; + parser.FullToken.FullImmediate.u[i].Float; } assembler->imm_count++; break; @@ -337,6 +394,7 @@ void r300_translate_vertex_shader(struct r300_context* r300, assembler->tex_count + assembler->color_count); consts->count = consts->user_count + assembler->imm_count; + vs->uses_imms = assembler->imm_count; debug_printf("r300: vs: %d total constants, " "%d from user and %d from immediates\n", consts->count, consts->user_count, assembler->imm_count); @@ -344,10 +402,13 @@ void r300_translate_vertex_shader(struct r300_context* r300, debug_printf("r300: vs: tab: %d %d %d %d\n", assembler->tab[0], assembler->tab[1], assembler->tab[2], assembler->tab[3]); - tgsi_dump(vs->state.tokens); + tgsi_dump(vs->state.tokens, 0); /* XXX finish r300 vertex shader dumper */ r300_vs_dump(vs); tgsi_parse_free(&parser); FREE(assembler); + + /* And, finally... */ + vs->translated = TRUE; } diff --git a/src/gallium/drivers/r300/r300_state_tcl.h b/src/gallium/drivers/r300/r300_vs.h index e2e1357d436..165d7178122 100644 --- a/src/gallium/drivers/r300/r300_state_tcl.h +++ b/src/gallium/drivers/r300/r300_vs.h @@ -20,21 +20,27 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef R300_STATE_TCL_H -#define R300_STATE_TCL_H +#ifndef R300_VS_H +#define R300_VS_H #include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_dump.h" #include "r300_context.h" #include "r300_debug.h" #include "r300_reg.h" #include "r300_screen.h" +#include "r300_shader_inlines.h" /* XXX get these to r300_reg */ #define R300_PVS_DST_OPCODE(x) ((x) << 0) # define R300_VE_DOT_PRODUCT 1 # define R300_VE_MULTIPLY 2 # define R300_VE_ADD 3 +# define R300_VE_MAXIMUM 7 +# define R300_VE_SET_LESS_THAN 10 +#define R300_PVS_DST_MATH_INST (1 << 6) +# define R300_ME_RECIP_DX 6 #define R300_PVS_DST_MACRO_INST (1 << 7) # define R300_PVS_MACRO_OP_2CLK_MADD 0 #define R300_PVS_DST_REG_TYPE(x) ((x) << 8) @@ -72,15 +78,13 @@ ((R300_PVS_SRC_SELECT_FORCE_1 | (R300_PVS_SRC_SELECT_FORCE_1 << 3) | \ (R300_PVS_SRC_SELECT_FORCE_1 << 6) | \ (R300_PVS_SRC_SELECT_FORCE_1 << 9)) << 13) - -static const struct tgsi_full_src_register r300_constant_zero = { - .SrcRegister.Extended = TRUE, - .SrcRegister.File = TGSI_FILE_NULL, - .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ZERO, - .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ZERO, - .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ZERO, - .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ZERO, -}; +#define R300_PVS_MODIFIER_X (1 << 25) +#define R300_PVS_MODIFIER_Y (1 << 26) +#define R300_PVS_MODIFIER_Z (1 << 27) +#define R300_PVS_MODIFIER_W (1 << 28) +#define R300_PVS_NEGATE_XYZW \ + (R300_PVS_MODIFIER_X | R300_PVS_MODIFIER_Y | \ + R300_PVS_MODIFIER_Z | R300_PVS_MODIFIER_W) /* Temporary struct used to hold assembly state while putting together * fragment programs. */ @@ -150,4 +154,4 @@ static struct r300_vertex_shader r300_texture_vertex_shader = { void r300_translate_vertex_shader(struct r300_context* r300, struct r300_vertex_shader* vs); -#endif /* R300_STATE_TCL_H */ +#endif /* R300_VS_H */ diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index a833bb0399a..d2893c3b9d7 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -45,9 +45,6 @@ struct r300_winsys { /* PCI ID */ uint32_t pci_id; - /* GB pipe count */ - uint32_t gb_pipes; - /* GART size. */ uint32_t gart_size; @@ -55,10 +52,10 @@ struct r300_winsys { uint32_t vram_size; /* Add a pipe_buffer to the list of buffer objects to validate. */ - void (*add_buffer)(struct r300_winsys* winsys, - struct pipe_buffer* pbuffer, - uint32_t rd, - uint32_t wd); + boolean (*add_buffer)(struct r300_winsys* winsys, + struct pipe_buffer* pbuffer, + uint32_t rd, + uint32_t wd); /* Revalidate all currently setup pipe_buffers. * Returns TRUE if a flush is required. */ diff --git a/src/gallium/drivers/r300/r3xx_fs.c b/src/gallium/drivers/r300/r3xx_fs.c new file mode 100644 index 00000000000..6e05d769773 --- /dev/null +++ b/src/gallium/drivers/r300/r3xx_fs.c @@ -0,0 +1,96 @@ +/* + * Copyright 2008 Corbin Simpson <[email protected]> + * Joakim Sindholt <[email protected]> + * + * 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 + * THE AUTHOR(S) 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 "r3xx_fs.h" + +static INLINE uint32_t r3xx_rgb_op(unsigned op) +{ + switch (op) { + case TGSI_OPCODE_MOV: + return R300_ALU_OUTC_CMP; + default: + return 0; + } +} + +static INLINE uint32_t r3xx_alpha_op(unsigned op) +{ + switch (op) { + case TGSI_OPCODE_MOV: + return R300_ALU_OUTA_CMP; + default: + return 0; + } +} + +static INLINE void r3xx_emit_maths(struct r3xx_fragment_shader* fs, + struct r300_fs_asm* assembler, + struct tgsi_full_src_register* src, + struct tgsi_full_dst_register* dst, + unsigned op, + unsigned count) +{ + int i = fs->alu_instruction_count; + + fs->instructions[i].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | + R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) | + R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) | + r3xx_rgb_op(op); + fs->instructions[i].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | + R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ; + fs->instructions[i].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | + R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) | + R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) | + r3xx_alpha_op(op); + fs->instructions[i].alu_alpha_addr = R300_ALPHA_ADDR0(0) | + R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT; + + fs->alu_instruction_count++; +} + +void r3xx_fs_finalize(struct r300_fragment_shader* fs, + struct r300_fs_asm* assembler) +{ + fs->stack_size = assembler->temp_count + assembler->temp_offset + 1; +} + +void r3xx_fs_instruction(struct r3xx_fragment_shader* fs, + struct r300_fs_asm* assembler, + struct tgsi_full_instruction* inst) +{ + switch (inst->Instruction.Opcode) { + case TGSI_OPCODE_MOV: + /* src0 -> src1 and src2 forced to zero */ + inst->FullSrcRegisters[1] = inst->FullSrcRegisters[0]; + inst->FullSrcRegisters[2] = r300_constant_zero; + r3xx_emit_maths(fs, assembler, inst->FullSrcRegisters, + &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); + break; + case TGSI_OPCODE_END: + break; + default: + debug_printf("r300: fs: Bad opcode %d\n", + inst->Instruction.Opcode); + break; + } +} diff --git a/src/gallium/drivers/r300/r3xx_fs.h b/src/gallium/drivers/r300/r3xx_fs.h new file mode 100644 index 00000000000..3da39ec2526 --- /dev/null +++ b/src/gallium/drivers/r300/r3xx_fs.h @@ -0,0 +1,76 @@ +/* + * Copyright 2008 Corbin Simpson <[email protected]> + * Joakim Sindholt <[email protected]> + * + * 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 + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#ifndef R3XX_FS_H +#define R3XX_FS_H + +#include "r300_fs_inlines.h" + +static struct r3xx_fragment_shader r3xx_passthrough_fragment_shader = { + .alu_instruction_count = 1, + .tex_instruction_count = 0, + .indirections = 0, + .shader.stack_size = 1, + + .instructions[0].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | + R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) | + R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) | + R300_ALU_OUTC_CMP, + .instructions[0].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | + R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ, + .instructions[0].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | + R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) | + R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) | + R300_ALU_OUTA_CMP, + .instructions[0].alu_alpha_addr = R300_ALPHA_ADDR0(0) | + R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT, +}; + +static struct r3xx_fragment_shader r3xx_texture_fragment_shader = { + .alu_instruction_count = 1, + .tex_instruction_count = 0, + .indirections = 0, + .shader.stack_size = 1, + + .instructions[0].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | + R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) | + R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) | + R300_ALU_OUTC_CMP, + .instructions[0].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | + R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ, + .instructions[0].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | + R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) | + R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) | + R300_ALU_OUTA_CMP, + .instructions[0].alu_alpha_addr = R300_ALPHA_ADDR0(0) | + R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT, +}; + +void r3xx_fs_finalize(struct r300_fragment_shader* fs, + struct r300_fs_asm* assembler); + +void r3xx_fs_instruction(struct r3xx_fragment_shader* fs, + struct r300_fs_asm* assembler, + struct tgsi_full_instruction* inst); + +#endif /* R3XX_FS_H */ diff --git a/src/gallium/drivers/r300/r300_state_shader.c b/src/gallium/drivers/r300/r5xx_fs.c index 1b02239ee76..99d826278ce 100644 --- a/src/gallium/drivers/r300/r300_state_shader.c +++ b/src/gallium/drivers/r300/r5xx_fs.c @@ -1,5 +1,6 @@ /* * Copyright 2008 Corbin Simpson <[email protected]> + * Joakim Sindholt <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,107 +21,9 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "r300_state_shader.h" +#include "r5xx_fs.h" -static void r300_copy_passthrough_shader(struct r300_fragment_shader* fs) -{ - struct r300_fragment_shader* pt = &r300_passthrough_fragment_shader; - fs->shader.stack_size = pt->shader.stack_size; - fs->alu_instruction_count = pt->alu_instruction_count; - fs->tex_instruction_count = pt->tex_instruction_count; - fs->indirections = pt->indirections; - fs->instructions[0] = pt->instructions[0]; -} - -static void r500_copy_passthrough_shader(struct r500_fragment_shader* fs) -{ - struct r500_fragment_shader* pt = &r500_passthrough_fragment_shader; - fs->shader.stack_size = pt->shader.stack_size; - fs->instruction_count = pt->instruction_count; - fs->instructions[0] = pt->instructions[0]; -} - -static void r300_fs_declare(struct r300_fs_asm* assembler, - struct tgsi_full_declaration* decl) -{ - switch (decl->Declaration.File) { - case TGSI_FILE_INPUT: - switch (decl->Semantic.SemanticName) { - case TGSI_SEMANTIC_COLOR: - assembler->color_count++; - break; - case TGSI_SEMANTIC_GENERIC: - assembler->tex_count++; - break; - default: - debug_printf("r300: fs: Bad semantic declaration %d\n", - decl->Semantic.SemanticName); - break; - } - break; - case TGSI_FILE_OUTPUT: - case TGSI_FILE_CONSTANT: - break; - case TGSI_FILE_TEMPORARY: - assembler->temp_count++; - break; - default: - debug_printf("r300: fs: Bad file %d\n", decl->Declaration.File); - break; - } - - assembler->temp_offset = assembler->color_count + assembler->tex_count; -} - -static INLINE unsigned r300_fs_src(struct r300_fs_asm* assembler, - struct tgsi_src_register* src) -{ - switch (src->File) { - case TGSI_FILE_NULL: - return 0; - case TGSI_FILE_INPUT: - /* XXX may be wrong */ - return src->Index; - break; - case TGSI_FILE_TEMPORARY: - return src->Index + assembler->temp_offset; - break; - case TGSI_FILE_IMMEDIATE: - return (src->Index + assembler->imm_offset) | (1 << 8); - break; - case TGSI_FILE_CONSTANT: - /* XXX magic */ - return src->Index | (1 << 8); - break; - default: - debug_printf("r300: fs: Unimplemented src %d\n", src->File); - break; - } - return 0; -} - -static INLINE unsigned r300_fs_dst(struct r300_fs_asm* assembler, - struct tgsi_dst_register* dst) -{ - switch (dst->File) { - case TGSI_FILE_NULL: - /* This happens during KIL instructions. */ - return 0; - break; - case TGSI_FILE_OUTPUT: - return 0; - break; - case TGSI_FILE_TEMPORARY: - return dst->Index + assembler->temp_offset; - break; - default: - debug_printf("r300: fs: Unimplemented dst %d\n", dst->File); - break; - } - return 0; -} - -static INLINE unsigned r500_fix_swiz(unsigned s) +static INLINE unsigned r5xx_fix_swiz(unsigned s) { /* For historical reasons, the swizzle values x, y, z, w, and 0 are * equivalent to the actual machine code, but 1 is not. Thus, we just @@ -132,13 +35,13 @@ static INLINE unsigned r500_fix_swiz(unsigned s) } } -static uint32_t r500_rgba_swiz(struct tgsi_full_src_register* reg) +static uint32_t r5xx_rgba_swiz(struct tgsi_full_src_register* reg) { if (reg->SrcRegister.Extended) { - return r500_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleX) | - (r500_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleY) << 3) | - (r500_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleZ) << 6) | - (r500_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleW) << 9); + return r5xx_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleX) | + (r5xx_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleY) << 3) | + (r5xx_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleZ) << 6) | + (r5xx_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleW) << 9); } else { return reg->SrcRegister.SwizzleX | (reg->SrcRegister.SwizzleY << 3) | @@ -147,7 +50,7 @@ static uint32_t r500_rgba_swiz(struct tgsi_full_src_register* reg) } } -static uint32_t r500_strq_swiz(struct tgsi_full_src_register* reg) +static uint32_t r5xx_strq_swiz(struct tgsi_full_src_register* reg) { return reg->SrcRegister.SwizzleX | (reg->SrcRegister.SwizzleY << 2) | @@ -155,50 +58,36 @@ static uint32_t r500_strq_swiz(struct tgsi_full_src_register* reg) (reg->SrcRegister.SwizzleW << 6); } -static INLINE uint32_t r500_rgb_swiz(struct tgsi_full_src_register* reg) +static INLINE uint32_t r5xx_rgb_swiz(struct tgsi_full_src_register* reg) { /* Only the first 9 bits... */ - return (r500_rgba_swiz(reg) & 0x1ff) | + return (r5xx_rgba_swiz(reg) & 0x1ff) | (reg->SrcRegister.Negate ? (1 << 9) : 0) | (reg->SrcRegisterExtMod.Absolute ? (1 << 10) : 0); } -static INLINE uint32_t r500_alpha_swiz(struct tgsi_full_src_register* reg) +static INLINE uint32_t r5xx_alpha_swiz(struct tgsi_full_src_register* reg) { /* Only the last 3 bits... */ - return (r500_rgba_swiz(reg) >> 9) | + return (r5xx_rgba_swiz(reg) >> 9) | (reg->SrcRegister.Negate ? (1 << 9) : 0) | (reg->SrcRegisterExtMod.Absolute ? (1 << 10) : 0); } -static INLINE uint32_t r300_rgb_op(unsigned op) -{ - switch (op) { - case TGSI_OPCODE_MOV: - return R300_ALU_OUTC_CMP; - default: - return 0; - } -} - -static INLINE uint32_t r300_alpha_op(unsigned op) -{ - switch (op) { - case TGSI_OPCODE_MOV: - return R300_ALU_OUTA_CMP; - default: - return 0; - } -} - -static INLINE uint32_t r500_rgba_op(unsigned op) +static INLINE uint32_t r5xx_rgba_op(unsigned op) { switch (op) { + case TGSI_OPCODE_COS: case TGSI_OPCODE_EX2: case TGSI_OPCODE_LG2: case TGSI_OPCODE_RCP: case TGSI_OPCODE_RSQ: + case TGSI_OPCODE_SIN: return R500_ALU_RGBA_OP_SOP; + case TGSI_OPCODE_DDX: + return R500_ALU_RGBA_OP_MDH; + case TGSI_OPCODE_DDY: + return R500_ALU_RGBA_OP_MDV; case TGSI_OPCODE_FRC: return R500_ALU_RGBA_OP_FRC; case TGSI_OPCODE_DP3: @@ -221,9 +110,11 @@ static INLINE uint32_t r500_rgba_op(unsigned op) } } -static INLINE uint32_t r500_alpha_op(unsigned op) +static INLINE uint32_t r5xx_alpha_op(unsigned op) { switch (op) { + case TGSI_OPCODE_COS: + return R500_ALPHA_OP_COS; case TGSI_OPCODE_EX2: return R500_ALPHA_OP_EX2; case TGSI_OPCODE_LG2: @@ -234,6 +125,12 @@ static INLINE uint32_t r500_alpha_op(unsigned op) return R500_ALPHA_OP_RSQ; case TGSI_OPCODE_FRC: return R500_ALPHA_OP_FRC; + case TGSI_OPCODE_SIN: + return R500_ALPHA_OP_SIN; + case TGSI_OPCODE_DDX: + return R500_ALPHA_OP_MDH; + case TGSI_OPCODE_DDY: + return R500_ALPHA_OP_MDV; case TGSI_OPCODE_DP3: case TGSI_OPCODE_DP4: case TGSI_OPCODE_DPH: @@ -253,7 +150,7 @@ static INLINE uint32_t r500_alpha_op(unsigned op) } } -static INLINE uint32_t r500_tex_op(unsigned op) +static INLINE uint32_t r5xx_tex_op(unsigned op) { switch (op) { case TGSI_OPCODE_KIL: @@ -269,64 +166,35 @@ static INLINE uint32_t r500_tex_op(unsigned op) } } -static INLINE void r300_emit_maths(struct r300_fragment_shader* fs, +/* Setup an ALU operation. */ +static INLINE void r5xx_emit_maths(struct r5xx_fragment_shader* fs, struct r300_fs_asm* assembler, struct tgsi_full_src_register* src, struct tgsi_full_dst_register* dst, unsigned op, unsigned count) { - int i = fs->alu_instruction_count; - - fs->instructions[i].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) | - r300_rgb_op(op); - fs->instructions[i].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | - R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ; - fs->instructions[i].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) | - r300_alpha_op(op); - fs->instructions[i].alu_alpha_addr = R300_ALPHA_ADDR0(0) | - R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT; - - fs->alu_instruction_count++; -} - -/* Setup an ALU operation. */ -static INLINE void r500_emit_alu(struct r500_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_dst_register* dst) -{ int i = fs->instruction_count; if (dst->DstRegister.File == TGSI_FILE_OUTPUT) { - fs->instructions[i].inst0 = R500_INST_TYPE_OUT | - R500_ALU_OMASK(dst->DstRegister.WriteMask); + fs->instructions[i].inst0 = R500_INST_TYPE_OUT; + if (r300_fs_is_depr(assembler, dst)) { + fs->instructions[i].inst4 = R500_W_OMASK; + } else { + fs->instructions[i].inst0 |= + R500_ALU_OMASK(dst->DstRegister.WriteMask); + } } else { fs->instructions[i].inst0 = R500_INST_TYPE_ALU | - R500_ALU_WMASK(dst->DstRegister.WriteMask); + R500_ALU_WMASK(dst->DstRegister.WriteMask); } fs->instructions[i].inst0 |= R500_INST_TEX_SEM_WAIT; - fs->instructions[i].inst4 = + fs->instructions[i].inst4 |= R500_ALPHA_ADDRD(r300_fs_dst(assembler, &dst->DstRegister)); fs->instructions[i].inst5 = R500_ALU_RGBA_ADDRD(r300_fs_dst(assembler, &dst->DstRegister)); -} - -static INLINE void r500_emit_maths(struct r500_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_src_register* src, - struct tgsi_full_dst_register* dst, - unsigned op, - unsigned count) -{ - int i = fs->instruction_count; - - r500_emit_alu(fs, assembler, dst); switch (count) { case 3: @@ -336,9 +204,9 @@ static INLINE void r500_emit_maths(struct r500_fragment_shader* fs, R500_ALPHA_ADDR2(r300_fs_src(assembler, &src[2].SrcRegister)); fs->instructions[i].inst5 |= R500_ALU_RGBA_SEL_C_SRC2 | - R500_SWIZ_RGBA_C(r500_rgb_swiz(&src[2])) | + R500_SWIZ_RGBA_C(r5xx_rgb_swiz(&src[2])) | R500_ALU_RGBA_ALPHA_SEL_C_SRC2 | - R500_SWIZ_ALPHA_C(r500_alpha_swiz(&src[2])); + R500_SWIZ_ALPHA_C(r5xx_alpha_swiz(&src[2])); case 2: fs->instructions[i].inst1 |= R500_RGB_ADDR1(r300_fs_src(assembler, &src[1].SrcRegister)); @@ -346,10 +214,10 @@ static INLINE void r500_emit_maths(struct r500_fragment_shader* fs, R500_ALPHA_ADDR1(r300_fs_src(assembler, &src[1].SrcRegister)); fs->instructions[i].inst3 = R500_ALU_RGB_SEL_B_SRC1 | - R500_SWIZ_RGB_B(r500_rgb_swiz(&src[1])); + R500_SWIZ_RGB_B(r5xx_rgb_swiz(&src[1])); fs->instructions[i].inst4 |= - R500_SWIZ_ALPHA_B(r500_alpha_swiz(&src[1])) | - R500_ALPHA_SEL_B_SRC1; + R500_ALPHA_SEL_B_SRC1 | + R500_SWIZ_ALPHA_B(r5xx_alpha_swiz(&src[1])); case 1: case 0: default: @@ -359,20 +227,20 @@ static INLINE void r500_emit_maths(struct r500_fragment_shader* fs, R500_ALPHA_ADDR0(r300_fs_src(assembler, &src[0].SrcRegister)); fs->instructions[i].inst3 |= R500_ALU_RGB_SEL_A_SRC0 | - R500_SWIZ_RGB_A(r500_rgb_swiz(&src[0])); + R500_SWIZ_RGB_A(r5xx_rgb_swiz(&src[0])); fs->instructions[i].inst4 |= - R500_SWIZ_ALPHA_A(r500_alpha_swiz(&src[0])) | - R500_ALPHA_SEL_A_SRC0; + R500_ALPHA_SEL_A_SRC0 | + R500_SWIZ_ALPHA_A(r5xx_alpha_swiz(&src[0])); break; } - fs->instructions[i].inst4 |= r500_alpha_op(op); - fs->instructions[i].inst5 |= r500_rgba_op(op); + fs->instructions[i].inst4 |= r5xx_alpha_op(op); + fs->instructions[i].inst5 |= r5xx_rgba_op(op); fs->instruction_count++; } -static INLINE void r500_emit_tex(struct r500_fragment_shader* fs, +static INLINE void r5xx_emit_tex(struct r5xx_fragment_shader* fs, struct r300_fs_asm* assembler, struct tgsi_full_src_register* src, struct tgsi_full_dst_register* dst, @@ -385,10 +253,10 @@ static INLINE void r500_emit_tex(struct r500_fragment_shader* fs, R500_INST_TEX_SEM_WAIT; fs->instructions[i].inst1 = R500_TEX_ID(0) | R500_TEX_SEM_ACQUIRE | //R500_TEX_IGNORE_UNCOVERED | - r500_tex_op(op); + r5xx_tex_op(op); fs->instructions[i].inst2 = R500_TEX_SRC_ADDR(r300_fs_src(assembler, &src->SrcRegister)) | - R500_SWIZ_TEX_STRQ(r500_strq_swiz(src)) | + R500_SWIZ_TEX_STRQ(r5xx_strq_swiz(src)) | R500_TEX_DST_ADDR(r300_fs_dst(assembler, &dst->DstRegister)) | R500_TEX_DST_R_SWIZ_R | R500_TEX_DST_G_SWIZ_G | R500_TEX_DST_B_SWIZ_B | R500_TEX_DST_A_SWIZ_A; @@ -405,42 +273,32 @@ static INLINE void r500_emit_tex(struct r500_fragment_shader* fs, src[0].SrcRegister.File = TGSI_FILE_TEMPORARY; src[1] = src[0]; - src[2] = r500_constant_zero; - r500_emit_maths(fs, assembler, src, dst, TGSI_OPCODE_MOV, 3); + src[2] = r300_constant_zero; + r5xx_emit_maths(fs, assembler, src, dst, TGSI_OPCODE_MOV, 3); } else { fs->instruction_count++; } } -static void r300_fs_instruction(struct r300_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_instruction* inst) +void r5xx_fs_finalize(struct r5xx_fragment_shader* fs, + struct r300_fs_asm* assembler) { - switch (inst->Instruction.Opcode) { - case TGSI_OPCODE_MOV: - /* src0 -> src1 and src2 forced to zero */ - inst->FullSrcRegisters[1] = inst->FullSrcRegisters[0]; - inst->FullSrcRegisters[2] = r500_constant_zero; - r300_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); - break; - case TGSI_OPCODE_END: - break; - default: - debug_printf("r300: fs: Bad opcode %d\n", - inst->Instruction.Opcode); - break; - } + /* XXX should this just go with OPCODE_END? */ + fs->instructions[fs->instruction_count - 1].inst0 |= + R500_INST_LAST; } -static void r500_fs_instruction(struct r500_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_instruction* inst) +void r5xx_fs_instruction(struct r5xx_fragment_shader* fs, + struct r300_fs_asm* assembler, + struct tgsi_full_instruction* inst) { /* Switch between opcodes. When possible, prefer using the official * AMD/ATI names for opcodes, please, as it facilitates using the * documentation. */ switch (inst->Instruction.Opcode) { + /* XXX trig needs extra prep */ + case TGSI_OPCODE_COS: + case TGSI_OPCODE_SIN: /* The simple scalar ops. */ case TGSI_OPCODE_EX2: case TGSI_OPCODE_LG2: @@ -452,8 +310,10 @@ static void r500_fs_instruction(struct r500_fragment_shader* fs, inst->FullSrcRegisters[0].SrcRegister.SwizzleW = inst->FullSrcRegisters[0].SrcRegister.SwizzleX; /* Fall through */ + case TGSI_OPCODE_DDX: + case TGSI_OPCODE_DDY: case TGSI_OPCODE_FRC: - r500_emit_maths(fs, assembler, inst->FullSrcRegisters, + r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, &inst->FullDstRegisters[0], inst->Instruction.Opcode, 1); break; @@ -474,7 +334,7 @@ static void r500_fs_instruction(struct r500_fragment_shader* fs, /* Fall through */ case TGSI_OPCODE_DP3: case TGSI_OPCODE_DP4: - r500_emit_maths(fs, assembler, inst->FullSrcRegisters, + r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, &inst->FullDstRegisters[0], inst->Instruction.Opcode, 2); break; @@ -484,7 +344,7 @@ static void r500_fs_instruction(struct r500_fragment_shader* fs, inst->FullSrcRegisters[3] = inst->FullSrcRegisters[2]; inst->FullSrcRegisters[2] = inst->FullSrcRegisters[0]; inst->FullSrcRegisters[0] = inst->FullSrcRegisters[3]; - r500_emit_maths(fs, assembler, inst->FullSrcRegisters, + r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); break; @@ -498,18 +358,18 @@ static void r500_fs_instruction(struct r500_fragment_shader* fs, /* Force src0 to one, move all registers over */ inst->FullSrcRegisters[2] = inst->FullSrcRegisters[1]; inst->FullSrcRegisters[1] = inst->FullSrcRegisters[0]; - inst->FullSrcRegisters[0] = r500_constant_one; - r500_emit_maths(fs, assembler, inst->FullSrcRegisters, + inst->FullSrcRegisters[0] = r300_constant_one; + r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); break; case TGSI_OPCODE_MUL: /* Force our src2 to zero */ - inst->FullSrcRegisters[2] = r500_constant_zero; - r500_emit_maths(fs, assembler, inst->FullSrcRegisters, + inst->FullSrcRegisters[2] = r300_constant_zero; + r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); break; case TGSI_OPCODE_MAD: - r500_emit_maths(fs, assembler, inst->FullSrcRegisters, + r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); break; @@ -522,17 +382,71 @@ static void r500_fs_instruction(struct r500_fragment_shader* fs, case TGSI_OPCODE_SWZ: /* src0 -> src1 and src2 forced to zero */ inst->FullSrcRegisters[1] = inst->FullSrcRegisters[0]; - inst->FullSrcRegisters[2] = r500_constant_zero; - r500_emit_maths(fs, assembler, inst->FullSrcRegisters, + inst->FullSrcRegisters[2] = r300_constant_zero; + r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); break; + /* The compound and hybrid insts. */ + case TGSI_OPCODE_LRP: + /* LRP DST A, B, C -> MAD TMP -A, C, C; MAD DST A, B, TMP */ + inst->FullSrcRegisters[3] = inst->FullSrcRegisters[1]; + inst->FullSrcRegisters[1] = inst->FullSrcRegisters[2]; + inst->FullSrcRegisters[0].SrcRegister.Negate = + !(inst->FullSrcRegisters[0].SrcRegister.Negate); + inst->FullDstRegisters[1] = inst->FullDstRegisters[0]; + inst->FullDstRegisters[0].DstRegister.Index = + assembler->temp_count; + inst->FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; + r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, + &inst->FullDstRegisters[0], TGSI_OPCODE_MAD, 3); + inst->FullSrcRegisters[2].SrcRegister.Index = + assembler->temp_count; + inst->FullSrcRegisters[2].SrcRegister.File = TGSI_FILE_TEMPORARY; + inst->FullSrcRegisters[2].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; + inst->FullSrcRegisters[2].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; + inst->FullSrcRegisters[2].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Z; + inst->FullSrcRegisters[2].SrcRegister.SwizzleW = TGSI_SWIZZLE_W; + inst->FullSrcRegisters[1] = inst->FullSrcRegisters[3]; + inst->FullSrcRegisters[0].SrcRegister.Negate = + !(inst->FullSrcRegisters[0].SrcRegister.Negate); + inst->FullDstRegisters[0] = inst->FullDstRegisters[1]; + r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, + &inst->FullDstRegisters[0], TGSI_OPCODE_MAD, 3); + break; + case TGSI_OPCODE_POW: + /* POW DST A, B -> LG2 TMP A; MUL TMP TMP, B; EX2 DST TMP */ + inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleW = + inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleX; + inst->FullSrcRegisters[0].SrcRegister.SwizzleW = + inst->FullSrcRegisters[0].SrcRegister.SwizzleX; + inst->FullDstRegisters[1] = inst->FullDstRegisters[0]; + inst->FullDstRegisters[0].DstRegister.Index = + assembler->temp_count; + inst->FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; + r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, + &inst->FullDstRegisters[0], TGSI_OPCODE_LG2, 1); + inst->FullSrcRegisters[0].SrcRegister.Index = + assembler->temp_count; + inst->FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; + inst->FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; + inst->FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; + inst->FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Z; + inst->FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_W; + inst->FullSrcRegisters[2] = r300_constant_zero; + r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, + &inst->FullDstRegisters[0], TGSI_OPCODE_MUL, 3); + inst->FullDstRegisters[0] = inst->FullDstRegisters[1]; + r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, + &inst->FullDstRegisters[0], TGSI_OPCODE_EX2, 1); + break; + /* The texture instruction set. */ case TGSI_OPCODE_KIL: case TGSI_OPCODE_TEX: case TGSI_OPCODE_TXB: case TGSI_OPCODE_TXP: - r500_emit_tex(fs, assembler, &inst->FullSrcRegisters[0], + r5xx_emit_tex(fs, assembler, &inst->FullSrcRegisters[0], &inst->FullDstRegisters[0], inst->Instruction.Opcode); break; @@ -551,99 +465,3 @@ static void r500_fs_instruction(struct r500_fragment_shader* fs, R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP; } } - -static void r300_fs_finalize(struct r3xx_fragment_shader* fs, - struct r300_fs_asm* assembler) -{ - fs->stack_size = assembler->temp_count + assembler->temp_offset; -} - -static void r500_fs_finalize(struct r500_fragment_shader* fs, - struct r300_fs_asm* assembler) -{ - /* XXX should this just go with OPCODE_END? */ - fs->instructions[fs->instruction_count - 1].inst0 |= - R500_INST_LAST; -} - -void r300_translate_fragment_shader(struct r300_context* r300, - struct r3xx_fragment_shader* fs) -{ - struct tgsi_parse_context parser; - int i; - boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500; - struct r300_constant_buffer* consts = - &r300->shader_constants[PIPE_SHADER_FRAGMENT]; - - struct r300_fs_asm* assembler = CALLOC_STRUCT(r300_fs_asm); - if (assembler == NULL) { - return; - } - /* Setup starting offset for immediates. */ - assembler->imm_offset = consts->user_count; - - /* Make sure we start at the beginning of the shader. */ - if (is_r500) { - ((struct r500_fragment_shader*)fs)->instruction_count = 0; - } - - tgsi_parse_init(&parser, fs->state.tokens); - - while (!tgsi_parse_end_of_tokens(&parser)) { - tgsi_parse_token(&parser); - - /* This is seriously the lamest way to create fragment programs ever. - * I blame TGSI. */ - switch (parser.FullToken.Token.Type) { - case TGSI_TOKEN_TYPE_DECLARATION: - /* Allocated registers sitting at the beginning - * of the program. */ - r300_fs_declare(assembler, &parser.FullToken.FullDeclaration); - break; - case TGSI_TOKEN_TYPE_IMMEDIATE: - debug_printf("r300: Emitting immediate to constant buffer, " - "position %d\n", - assembler->imm_offset + assembler->imm_count); - /* I am not amused by the length of these. */ - for (i = 0; i < 4; i++) { - consts->constants[assembler->imm_offset + - assembler->imm_count][i] = - parser.FullToken.FullImmediate.u.ImmediateFloat32[i] - .Float; - } - assembler->imm_count++; - break; - case TGSI_TOKEN_TYPE_INSTRUCTION: - if (is_r500) { - r500_fs_instruction((struct r500_fragment_shader*)fs, - assembler, &parser.FullToken.FullInstruction); - } else { - r300_fs_instruction((struct r300_fragment_shader*)fs, - assembler, &parser.FullToken.FullInstruction); - } - break; - } - } - - debug_printf("r300: fs: %d texs and %d colors, first free reg is %d\n", - assembler->tex_count, assembler->color_count, - assembler->tex_count + assembler->color_count); - - consts->count = consts->user_count + assembler->imm_count; - debug_printf("r300: fs: %d total constants, " - "%d from user and %d from immediates\n", consts->count, - consts->user_count, assembler->imm_count); - r300_fs_finalize(fs, assembler); - if (is_r500) { - r500_fs_finalize((struct r500_fragment_shader*)fs, assembler); - } - - tgsi_dump(fs->state.tokens); - /* XXX finish r300 dumper too */ - if (is_r500) { - r500_fs_dump((struct r500_fragment_shader*)fs); - } - - tgsi_parse_free(&parser); - FREE(assembler); -} diff --git a/src/gallium/drivers/r300/r300_state_shader.h b/src/gallium/drivers/r300/r5xx_fs.h index 185fdd90f0c..629e587be4d 100644 --- a/src/gallium/drivers/r300/r300_state_shader.h +++ b/src/gallium/drivers/r300/r5xx_fs.h @@ -1,5 +1,6 @@ /* * Copyright 2008 Corbin Simpson <[email protected]> + * Joakim Sindholt <[email protected]> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,15 +21,10 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef R300_STATE_SHADER_H -#define R300_STATE_SHADER_H +#ifndef R5XX_FS_H +#define R5XX_FS_H -#include "tgsi/tgsi_parse.h" - -#include "r300_context.h" -#include "r300_debug.h" -#include "r300_reg.h" -#include "r300_screen.h" +#include "r300_fs_inlines.h" /* XXX this all should find its way back to r300_reg */ /* Swizzle tools */ @@ -57,82 +53,9 @@ #define R500_TEX_WMASK(x) ((x) << 11) #define R500_ALU_WMASK(x) ((x) << 11) #define R500_ALU_OMASK(x) ((x) << 15) +#define R500_W_OMASK (1 << 31) -/* TGSI constants. TGSI is like XML: If it can't solve your problems, you're - * not using enough of it. */ -static const struct tgsi_full_src_register r500_constant_zero = { - .SrcRegister.Extended = TRUE, - .SrcRegister.File = TGSI_FILE_NULL, - .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ZERO, - .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ZERO, - .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ZERO, - .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ZERO, -}; - -static const struct tgsi_full_src_register r500_constant_one = { - .SrcRegister.Extended = TRUE, - .SrcRegister.File = TGSI_FILE_NULL, - .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ONE, - .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ONE, - .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ONE, - .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ONE, -}; - -/* Temporary struct used to hold assembly state while putting together - * fragment programs. */ -struct r300_fs_asm { - /* Pipe context. */ - struct r300_context* r300; - /* Number of colors. */ - unsigned color_count; - /* Number of texcoords. */ - unsigned tex_count; - /* Offset for temporary registers. Inputs and temporaries have no - * distinguishing markings, so inputs start at 0 and the first usable - * temporary register is after all inputs. */ - unsigned temp_offset; - /* Number of requested temporary registers. */ - unsigned temp_count; - /* Offset for immediate constants. Neither R300 nor R500 can do four - * inline constants per source, so instead we copy immediates into the - * constant buffer. */ - unsigned imm_offset; - /* Number of immediate constants. */ - unsigned imm_count; -}; - -void r300_translate_fragment_shader(struct r300_context* r300, - struct r3xx_fragment_shader* fs); - -static struct r300_fragment_shader r300_passthrough_fragment_shader = { - /* XXX This is the emission code. TODO: decode - OUT_CS_REG(R300_US_CONFIG, 0); - OUT_CS_REG(R300_US_CODE_OFFSET, 0x0); - OUT_CS_REG(R300_US_CODE_ADDR_0, 0x0); - OUT_CS_REG(R300_US_CODE_ADDR_1, 0x0); - OUT_CS_REG(R300_US_CODE_ADDR_2, 0x0); - OUT_CS_REG(R300_US_CODE_ADDR_3, 0x400000); -*/ - .alu_instruction_count = 1, - .tex_instruction_count = 0, - .indirections = 0, - .shader.stack_size = 1, - - .instructions[0].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) | - R300_ALU_OUTC_CMP, - .instructions[0].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | - R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ, - .instructions[0].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) | - R300_ALU_OUTA_CMP, - .instructions[0].alu_alpha_addr = R300_ALPHA_ADDR0(0) | - R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT, -}; - -static struct r500_fragment_shader r500_passthrough_fragment_shader = { +static struct r5xx_fragment_shader r5xx_passthrough_fragment_shader = { .shader.stack_size = 0, .instruction_count = 1, .instructions[0].inst0 = R500_INST_TYPE_OUT | @@ -158,40 +81,12 @@ static struct r500_fragment_shader r500_passthrough_fragment_shader = { R500_ALU_RGBA_A_SWIZ_0, }; -static struct r300_fragment_shader r300_texture_fragment_shader = { - /* XXX This is the emission code. TODO: decode - OUT_CS_REG(R300_US_CONFIG, 0); - OUT_CS_REG(R300_US_CODE_OFFSET, 0x0); - OUT_CS_REG(R300_US_CODE_ADDR_0, 0x0); - OUT_CS_REG(R300_US_CODE_ADDR_1, 0x0); - OUT_CS_REG(R300_US_CODE_ADDR_2, 0x0); - OUT_CS_REG(R300_US_CODE_ADDR_3, 0x400000); -*/ - .alu_instruction_count = 1, - .tex_instruction_count = 0, - .indirections = 0, - .shader.stack_size = 1, - - .instructions[0].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) | - R300_ALU_OUTC_CMP, - .instructions[0].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | - R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ, - .instructions[0].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) | - R300_ALU_OUTA_CMP, - .instructions[0].alu_alpha_addr = R300_ALPHA_ADDR0(0) | - R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT, -}; - -static struct r500_fragment_shader r500_texture_fragment_shader = { +static struct r5xx_fragment_shader r5xx_texture_fragment_shader = { .shader.stack_size = 1, .instruction_count = 2, .instructions[0].inst0 = R500_INST_TYPE_TEX | R500_INST_TEX_SEM_WAIT | - R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK | + R500_INST_RGB_WMASK_RGB | R500_INST_ALPHA_WMASK | R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP, .instructions[0].inst1 = R500_TEX_ID(0) | R500_TEX_INST_LD | R500_TEX_SEM_ACQUIRE | R500_TEX_IGNORE_UNCOVERED, @@ -227,4 +122,11 @@ static struct r500_fragment_shader r500_texture_fragment_shader = { R500_ALU_RGBA_A_SWIZ_0, }; -#endif /* R300_STATE_SHADER_H */ +void r5xx_fs_finalize(struct r5xx_fragment_shader* fs, + struct r300_fs_asm* assembler); + +void r5xx_fs_instruction(struct r5xx_fragment_shader* fs, + struct r300_fs_asm* assembler, + struct tgsi_full_instruction* inst); + +#endif /* R5XX_FS_H */ diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index dffc15a4f19..7888c2f644b 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -92,6 +92,7 @@ struct softpipe_context { * queries. */ uint64_t occlusion_count; + unsigned active_query_count; /** Mapped vertex buffers */ ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS]; diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c index ba2766ff139..d4045816d03 100644 --- a/src/gallium/drivers/softpipe/sp_draw_arrays.c +++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c @@ -35,6 +35,7 @@ #include "pipe/p_context.h" #include "pipe/internal/p_winsys_screen.h" #include "pipe/p_inlines.h" +#include "util/u_prim.h" #include "sp_context.h" #include "sp_state.h" @@ -65,6 +66,7 @@ softpipe_map_constant_buffers(struct softpipe_context *sp) size); } + static void softpipe_unmap_constant_buffers(struct softpipe_context *sp) { @@ -86,20 +88,6 @@ softpipe_unmap_constant_buffers(struct softpipe_context *sp) } -static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = { - PIPE_PRIM_POINTS, - PIPE_PRIM_LINES, - PIPE_PRIM_LINES, - PIPE_PRIM_LINES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES, - PIPE_PRIM_TRIANGLES -}; - - boolean softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) @@ -108,15 +96,11 @@ softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode, } - /** * Draw vertex arrays, with optional indexing. * Basically, map the vertex buffers (and drawing surfaces), then hand off * the drawing to the 'draw' module. - * - * XXX should the element buffer be specified/bound with a separate function? */ - boolean softpipe_draw_range_elements(struct pipe_context *pipe, struct pipe_buffer *indexBuffer, @@ -129,7 +113,7 @@ softpipe_draw_range_elements(struct pipe_context *pipe, struct draw_context *draw = sp->draw; unsigned i; - sp->reduced_api_prim = reduced_prim[mode]; + sp->reduced_api_prim = u_reduced_prim(mode); if (sp->dirty) softpipe_update_derived( sp ); @@ -147,6 +131,7 @@ softpipe_draw_range_elements(struct pipe_context *pipe, PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_vertex_buffer(draw, i, buf); } + /* Map index buffer, if present */ if (indexBuffer) { void *mapped_indexes @@ -159,10 +144,10 @@ softpipe_draw_range_elements(struct pipe_context *pipe, } else { /* no index/element buffer */ - draw_set_mapped_element_buffer_range(draw, 0, start, start + count - 1, NULL); + draw_set_mapped_element_buffer_range(draw, 0, start, + start + count - 1, NULL); } - /* draw! */ draw_arrays(draw, mode, start, count); @@ -187,6 +172,7 @@ softpipe_draw_range_elements(struct pipe_context *pipe, return TRUE; } + boolean softpipe_draw_elements(struct pipe_context *pipe, struct pipe_buffer *indexBuffer, @@ -200,11 +186,9 @@ softpipe_draw_elements(struct pipe_context *pipe, } - void softpipe_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags) { struct softpipe_context *sp = softpipe_context(pipe); draw_set_edgeflags(sp->draw, edgeflags); } - diff --git a/src/gallium/drivers/softpipe/sp_fs_sse.c b/src/gallium/drivers/softpipe/sp_fs_sse.c index 31c3ca21c51..f4fa0905d74 100644 --- a/src/gallium/drivers/softpipe/sp_fs_sse.c +++ b/src/gallium/drivers/softpipe/sp_fs_sse.c @@ -45,17 +45,6 @@ #include "rtasm/rtasm_x86sse.h" -/* Surely this should be defined somewhere in a tgsi header: - */ -typedef void (PIPE_CDECL *codegen_function)( - const struct tgsi_exec_vector *input, - struct tgsi_exec_vector *output, - const float (*constant)[4], - struct tgsi_exec_vector *temporary, - const struct tgsi_interp_coef *coef, - float (*immediates)[4] - //, const struct tgsi_exec_vector *quadPos - ); /** @@ -65,7 +54,7 @@ struct sp_sse_fragment_shader { struct sp_fragment_shader base; struct x86_function sse2_program; - codegen_function func; + tgsi_sse2_fs_function func; float immediates[TGSI_EXEC_NUM_IMMEDIATES][4]; }; @@ -83,6 +72,7 @@ fs_sse_prepare( const struct sp_fragment_shader *base, struct tgsi_exec_machine *machine, struct tgsi_sampler **samplers ) { + machine->Samplers = samplers; } @@ -107,12 +97,10 @@ fs_sse_run( const struct sp_fragment_shader *base, tgsi_set_kill_mask(machine, 0x0); tgsi_set_exec_mask(machine, 1, 1, 1, 1); - shader->func( machine->Inputs, - machine->Outputs, + shader->func( machine, machine->Consts, - machine->Temps, - machine->InterpCoefs, - shader->immediates + (const float (*)[4])shader->immediates, + machine->InterpCoefs // , &machine->QuadPos ); @@ -151,7 +139,7 @@ softpipe_create_fs_sse(struct softpipe_context *softpipe, return NULL; } - shader->func = (codegen_function) x86_get_func( &shader->sse2_program ); + shader->func = (tgsi_sse2_fs_function) x86_get_func( &shader->sse2_program ); if (!shader->func) { x86_release_func( &shader->sse2_program ); FREE(shader); diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.c b/src/gallium/drivers/softpipe/sp_prim_vbuf.c index 06725fd09b4..42021789ea8 100644 --- a/src/gallium/drivers/softpipe/sp_prim_vbuf.c +++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.c @@ -238,65 +238,117 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) case PIPE_PRIM_TRIANGLES: for (i = 2; i < nr; i += 3) { - setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride)); + if (softpipe->rasterizer->flatshade_first) { + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[i-2], stride) ); + } + else { + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } } break; case PIPE_PRIM_TRIANGLE_STRIP: for (i = 2; i < nr; i += 1) { - setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i+(i&1)-2], stride), - get_vert(vertex_buffer, indices[i-(i&1)-1], stride), - get_vert(vertex_buffer, indices[i-0], stride)); + if (softpipe->rasterizer->flatshade_first) { + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i+(i&1)-1], stride), + get_vert(vertex_buffer, indices[i-(i&1)], stride), + get_vert(vertex_buffer, indices[i-2], stride) ); + } + else { + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i+(i&1)-2], stride), + get_vert(vertex_buffer, indices[i-(i&1)-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } } break; case PIPE_PRIM_TRIANGLE_FAN: for (i = 2; i < nr; i += 1) { - setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[0], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride)); + if (softpipe->rasterizer->flatshade_first) { + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[0], stride), + get_vert(vertex_buffer, indices[i-1], stride) ); + } + else { + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[0], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } } break; case PIPE_PRIM_QUADS: for (i = 3; i < nr; i += 4) { - setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-3], stride), - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-0], stride)); - - setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride)); + if (softpipe->rasterizer->flatshade_first) { + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-3], stride) ); + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[i-3], stride) ); + } + else { + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } } break; case PIPE_PRIM_QUAD_STRIP: for (i = 3; i < nr; i += 2) { - setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-3], stride), - get_vert(vertex_buffer, indices[i-2], stride), - get_vert(vertex_buffer, indices[i-0], stride)); - - setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-3], stride), - get_vert(vertex_buffer, indices[i-0], stride)); + if (softpipe->rasterizer->flatshade_first) { + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-3], stride)); + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[i-3], stride) ); + } + else { + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-2], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + setup_tri( setup_ctx, + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-3], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } } break; case PIPE_PRIM_POLYGON: + /* Almost same as tri fan but the _first_ vertex specifies the flat + * shading color. Note that the first polygon vertex is passed as + * the last triangle vertex here. + * flatshade_first state makes no difference. + */ for (i = 2; i < nr; i += 1) { setup_tri( setup_ctx, - get_vert(vertex_buffer, indices[0-1], stride), get_vert(vertex_buffer, indices[i-0], stride), - get_vert(vertex_buffer, indices[0], stride)); + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[0], stride) ); } break; @@ -368,58 +420,104 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) } break; - case PIPE_PRIM_TRIANGLES: for (i = 2; i < nr; i += 3) { - setup_tri( setup_ctx, - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride)); + if (softpipe->rasterizer->flatshade_first) { + setup_tri( setup_ctx, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-2, stride) ); + } + else { + setup_tri( setup_ctx, + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); + } } break; case PIPE_PRIM_TRIANGLE_STRIP: - for (i = 2; i < nr; i += 1) { - setup_tri( setup_ctx, - get_vert(vertex_buffer, i+(i&1)-2, stride), - get_vert(vertex_buffer, i-(i&1)-1, stride), - get_vert(vertex_buffer, i-0, stride)); + for (i = 2; i < nr; i++) { + if (softpipe->rasterizer->flatshade_first) { + setup_tri( setup_ctx, + get_vert(vertex_buffer, i+(i&1)-1, stride), + get_vert(vertex_buffer, i-(i&1), stride), + get_vert(vertex_buffer, i-2, stride) ); + } + else { + setup_tri( setup_ctx, + get_vert(vertex_buffer, i+(i&1)-2, stride), + get_vert(vertex_buffer, i-(i&1)-1, stride), + get_vert(vertex_buffer, i-0, stride) ); + } } break; case PIPE_PRIM_TRIANGLE_FAN: for (i = 2; i < nr; i += 1) { - setup_tri( setup_ctx, - get_vert(vertex_buffer, 0, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride)); + if (softpipe->rasterizer->flatshade_first) { + setup_tri( setup_ctx, + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, 0, stride), + get_vert(vertex_buffer, i-1, stride) ); + } + else { + setup_tri( setup_ctx, + get_vert(vertex_buffer, 0, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); + } } break; case PIPE_PRIM_QUADS: for (i = 3; i < nr; i += 4) { - setup_tri( setup_ctx, - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-0, stride)); - - setup_tri( setup_ctx, - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride)); + if (softpipe->rasterizer->flatshade_first) { + setup_tri( setup_ctx, + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-3, stride) ); + setup_tri( setup_ctx, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-3, stride) ); + } + else { + setup_tri( setup_ctx, + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride) ); + setup_tri( setup_ctx, + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); + } } break; + case PIPE_PRIM_QUAD_STRIP: for (i = 3; i < nr; i += 2) { - setup_tri( setup_ctx, - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-2, stride), - get_vert(vertex_buffer, i-0, stride)); - - setup_tri( setup_ctx, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-3, stride), - get_vert(vertex_buffer, i-0, stride)); + if (softpipe->rasterizer->flatshade_first) { + setup_tri( setup_ctx, + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-3, stride) ); + setup_tri( setup_ctx, + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-3, stride) ); + } + else { + setup_tri( setup_ctx, + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride) ); + setup_tri( setup_ctx, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-0, stride) ); + } } break; @@ -427,12 +525,13 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) /* Almost same as tri fan but the _first_ vertex specifies the flat * shading color. Note that the first polygon vertex is passed as * the last triangle vertex here. + * flatshade_first state makes no difference. */ for (i = 2; i < nr; i += 1) { setup_tri( setup_ctx, get_vert(vertex_buffer, i-1, stride), get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, 0, stride)); + get_vert(vertex_buffer, 0, stride) ); } break; diff --git a/src/gallium/drivers/softpipe/sp_quad_fs.c b/src/gallium/drivers/softpipe/sp_quad_fs.c index ca637a1d6a4..28f8d1a60ea 100644 --- a/src/gallium/drivers/softpipe/sp_quad_fs.c +++ b/src/gallium/drivers/softpipe/sp_quad_fs.c @@ -52,7 +52,7 @@ struct quad_shade_stage { struct quad_stage stage; /**< base class */ - struct tgsi_exec_machine machine; + struct tgsi_exec_machine *machine; struct tgsi_exec_vector *inputs, *outputs; }; @@ -73,7 +73,7 @@ shade_quad(struct quad_stage *qs, struct quad_header *quad) { struct quad_shade_stage *qss = quad_shade_stage( qs ); struct softpipe_context *softpipe = qs->softpipe; - struct tgsi_exec_machine *machine = &qss->machine; + struct tgsi_exec_machine *machine = qss->machine; boolean z_written; /* Consts do not require 16 byte alignment. */ @@ -146,7 +146,7 @@ shade_begin(struct quad_stage *qs) struct softpipe_context *softpipe = qs->softpipe; softpipe->fs->prepare( softpipe->fs, - &qss->machine, + qss->machine, (struct tgsi_sampler **) softpipe->tgsi.frag_samplers_list ); @@ -159,9 +159,8 @@ shade_destroy(struct quad_stage *qs) { struct quad_shade_stage *qss = (struct quad_shade_stage *) qs; - tgsi_exec_machine_free_data(&qss->machine); - FREE( qss->inputs ); - FREE( qss->outputs ); + tgsi_exec_machine_destroy(qss->machine); + FREE( qs ); } @@ -170,19 +169,24 @@ struct quad_stage * sp_quad_shade_stage( struct softpipe_context *softpipe ) { struct quad_shade_stage *qss = CALLOC_STRUCT(quad_shade_stage); - - /* allocate storage for program inputs/outputs, aligned to 16 bytes */ - qss->inputs = MALLOC(PIPE_MAX_ATTRIBS * sizeof(*qss->inputs) + 16); - qss->outputs = MALLOC(PIPE_MAX_ATTRIBS * sizeof(*qss->outputs) + 16); - qss->machine.Inputs = align16(qss->inputs); - qss->machine.Outputs = align16(qss->outputs); + if (!qss) + goto fail; qss->stage.softpipe = softpipe; qss->stage.begin = shade_begin; qss->stage.run = shade_quad; qss->stage.destroy = shade_destroy; - tgsi_exec_machine_init( &qss->machine ); + qss->machine = tgsi_exec_machine_create(); + if (!qss->machine) + goto fail; return &qss->stage; + +fail: + if (qss && qss->machine) + tgsi_exec_machine_destroy(qss->machine); + + FREE(qss); + return NULL; } diff --git a/src/gallium/drivers/softpipe/sp_quad_pipe.c b/src/gallium/drivers/softpipe/sp_quad_pipe.c index 892ef87ee9f..b5f69b74264 100644 --- a/src/gallium/drivers/softpipe/sp_quad_pipe.c +++ b/src/gallium/drivers/softpipe/sp_quad_pipe.c @@ -80,7 +80,7 @@ sp_build_quad_pipeline(struct softpipe_context *sp) sp_push_quad_first( sp, sp->quad[i].blend, i ); } - if (sp->depth_stencil->depth.occlusion_count) { + if (sp->active_query_count) { sp_push_quad_first( sp, sp->quad[i].occlusion, i ); } diff --git a/src/gallium/drivers/softpipe/sp_query.c b/src/gallium/drivers/softpipe/sp_query.c index 93dab236d66..379cf4ad064 100644 --- a/src/gallium/drivers/softpipe/sp_query.c +++ b/src/gallium/drivers/softpipe/sp_query.c @@ -34,6 +34,7 @@ #include "util/u_memory.h" #include "sp_context.h" #include "sp_query.h" +#include "sp_state.h" struct softpipe_query { uint64_t start; @@ -69,6 +70,8 @@ softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q) struct softpipe_query *sq = softpipe_query(q); sq->start = softpipe->occlusion_count; + softpipe->active_query_count++; + softpipe->dirty |= SP_NEW_QUERY; } @@ -78,7 +81,9 @@ softpipe_end_query(struct pipe_context *pipe, struct pipe_query *q) struct softpipe_context *softpipe = softpipe_context( pipe ); struct softpipe_query *sq = softpipe_query(q); + softpipe->active_query_count--; sq->end = softpipe->occlusion_count; + softpipe->dirty |= SP_NEW_QUERY; } diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index cc39d33ede6..6178c4ac7e3 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -82,13 +82,15 @@ softpipe_get_param(struct pipe_screen *screen, int param) case PIPE_CAP_TEXTURE_SHADOW_MAP: return 1; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: - return 12; /* max 2Kx2K */ + return 13; /* max 4Kx4K */ case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: return 8; /* max 128x128x128 */ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - return 12; /* max 2Kx2K */ + return 13; /* max 4Kx4K */ case PIPE_CAP_TGSI_CONT_SUPPORTED: return 1; + case PIPE_CAP_BLEND_EQUATION_SEPARATE: + return 1; default: return 0; } @@ -108,7 +110,7 @@ softpipe_get_paramf(struct pipe_screen *screen, int param) case PIPE_CAP_MAX_POINT_WIDTH_AA: return 255.0; /* arbitrary */ case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: - return 0.0; + return 16.0; /* not actually signficant at this time */ case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: return 16.0; /* arbitrary */ default: diff --git a/src/gallium/drivers/softpipe/sp_setup.c b/src/gallium/drivers/softpipe/sp_setup.c index 1eb23cd6b6f..de3ae3c3696 100644 --- a/src/gallium/drivers/softpipe/sp_setup.c +++ b/src/gallium/drivers/softpipe/sp_setup.c @@ -507,6 +507,8 @@ static void print_vertex(const struct setup_context *setup, #endif /** + * Sort the vertices from top to bottom order, setting up the triangle + * edge fields (ebot, emaj, etop). * \return FALSE if coords are inf/nan (cull the tri), TRUE otherwise */ static boolean setup_sort_vertices( struct setup_context *setup, @@ -1051,7 +1053,10 @@ setup_line_coefficients(struct setup_context *setup, float area; /* use setup->vmin, vmax to point to vertices */ - setup->vprovoke = v1; + if (softpipe->rasterizer->flatshade_first) + setup->vprovoke = v0; + else + setup->vprovoke = v1; setup->vmin = v0; setup->vmax = v1; diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c index 5de358dae93..a1d3bade27a 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.c +++ b/src/gallium/drivers/softpipe/sp_tex_sample.c @@ -705,15 +705,18 @@ get_texel(const struct tgsi_sampler *tgsi_sampler, * Compare texcoord 'p' (aka R) against texture value 'rgba[0]' * When we sampled the depth texture, the depth value was put into all * RGBA channels. We look at the red channel here. + * \param rgba quad of (depth) texel values + * \param p texture 'P' components for four pixels in quad + * \param j which pixel in the quad to test [0..3] */ static INLINE void -shadow_compare(uint compare_func, +shadow_compare(const struct pipe_sampler_state *sampler, float rgba[NUM_CHANNELS][QUAD_SIZE], const float p[QUAD_SIZE], uint j) { int k; - switch (compare_func) { + switch (sampler->compare_func) { case PIPE_FUNC_LESS: k = p[j] < rgba[0][j]; break; @@ -751,6 +754,78 @@ shadow_compare(uint compare_func, /** + * As above, but do four z/texture comparisons. + */ +static INLINE void +shadow_compare4(const struct pipe_sampler_state *sampler, + float rgba[NUM_CHANNELS][QUAD_SIZE], + const float p[QUAD_SIZE]) +{ + int j, k0, k1, k2, k3; + float val; + + /* compare four texcoords vs. four texture samples */ + switch (sampler->compare_func) { + case PIPE_FUNC_LESS: + k0 = p[0] < rgba[0][0]; + k1 = p[1] < rgba[0][1]; + k2 = p[2] < rgba[0][2]; + k3 = p[3] < rgba[0][3]; + break; + case PIPE_FUNC_LEQUAL: + k0 = p[0] <= rgba[0][0]; + k1 = p[1] <= rgba[0][1]; + k2 = p[2] <= rgba[0][2]; + k3 = p[3] <= rgba[0][3]; + break; + case PIPE_FUNC_GREATER: + k0 = p[0] > rgba[0][0]; + k1 = p[1] > rgba[0][1]; + k2 = p[2] > rgba[0][2]; + k3 = p[3] > rgba[0][3]; + break; + case PIPE_FUNC_GEQUAL: + k0 = p[0] >= rgba[0][0]; + k1 = p[1] >= rgba[0][1]; + k2 = p[2] >= rgba[0][2]; + k3 = p[3] >= rgba[0][3]; + break; + case PIPE_FUNC_EQUAL: + k0 = p[0] == rgba[0][0]; + k1 = p[1] == rgba[0][1]; + k2 = p[2] == rgba[0][2]; + k3 = p[3] == rgba[0][3]; + break; + case PIPE_FUNC_NOTEQUAL: + k0 = p[0] != rgba[0][0]; + k1 = p[1] != rgba[0][1]; + k2 = p[2] != rgba[0][2]; + k3 = p[3] != rgba[0][3]; + break; + case PIPE_FUNC_ALWAYS: + k0 = k1 = k2 = k3 = 1; + break; + case PIPE_FUNC_NEVER: + k0 = k1 = k2 = k3 = 0; + break; + default: + k0 = k1 = k2 = k3 = 0; + assert(0); + break; + } + + /* convert four pass/fail values to an intensity in [0,1] */ + val = 0.25F * (k0 + k1 + k2 + k3); + + /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */ + for (j = 0; j < 4; j++) { + rgba[0][j] = rgba[1][j] = rgba[2][j] = val; + rgba[3][j] = 1.0F; + } +} + + +/** * Common code for sampling 1D/2D/cube textures. * Could probably extend for 3D... */ @@ -769,7 +844,6 @@ sp_get_samples_2d_common(const struct tgsi_sampler *tgsi_sampler, const uint unit = samp->unit; const struct pipe_texture *texture = sp->texture[unit]; const struct pipe_sampler_state *sampler = sp->sampler[unit]; - const uint compare_func = sampler->compare_func; unsigned level0, level1, j, imgFilter; int width, height; float levelBlend; @@ -794,7 +868,7 @@ sp_get_samples_2d_common(const struct tgsi_sampler *tgsi_sampler, for (j = 0; j < QUAD_SIZE; j++) { get_texel(tgsi_sampler, faces[j], level0, x[j], y[j], 0, rgba, j); if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { - shadow_compare(compare_func, rgba, p, j); + shadow_compare(sampler, rgba, p, j); } if (level0 != level1) { @@ -806,7 +880,7 @@ sp_get_samples_2d_common(const struct tgsi_sampler *tgsi_sampler, get_texel(tgsi_sampler, faces[j], level1, x[j], y[j], 0, rgba2, j); if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){ - shadow_compare(compare_func, rgba2, p, j); + shadow_compare(sampler, rgba2, p, j); } for (c = 0; c < NUM_CHANNELS; c++) { @@ -833,10 +907,7 @@ sp_get_samples_2d_common(const struct tgsi_sampler *tgsi_sampler, get_texel(tgsi_sampler, faces[j], level0, x0[j], y1[j], 0, tx, 2); get_texel(tgsi_sampler, faces[j], level0, x1[j], y1[j], 0, tx, 3); if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { - shadow_compare(compare_func, tx, p, 0); - shadow_compare(compare_func, tx, p, 1); - shadow_compare(compare_func, tx, p, 2); - shadow_compare(compare_func, tx, p, 3); + shadow_compare4(sampler, tx, p); } /* interpolate R, G, B, A */ @@ -858,10 +929,7 @@ sp_get_samples_2d_common(const struct tgsi_sampler *tgsi_sampler, get_texel(tgsi_sampler, faces[j], level1, x0[j], y1[j], 0, tx, 2); get_texel(tgsi_sampler, faces[j], level1, x1[j], y1[j], 0, tx, 3); if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){ - shadow_compare(compare_func, tx, p, 0); - shadow_compare(compare_func, tx, p, 1); - shadow_compare(compare_func, tx, p, 2); - shadow_compare(compare_func, tx, p, 3); + shadow_compare4(sampler, tx, p); } /* interpolate R, G, B, A */ @@ -1076,7 +1144,6 @@ sp_get_samples_rect(const struct tgsi_sampler *tgsi_sampler, const struct pipe_texture *texture = sp->texture[unit]; const struct pipe_sampler_state *sampler = sp->sampler[unit]; const uint face = 0; - const uint compare_func = sampler->compare_func; unsigned level0, level1, j, imgFilter; int width, height; float levelBlend; @@ -1101,7 +1168,7 @@ sp_get_samples_rect(const struct tgsi_sampler *tgsi_sampler, for (j = 0; j < QUAD_SIZE; j++) { get_texel(tgsi_sampler, face, level0, x[j], y[j], 0, rgba, j); if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { - shadow_compare(compare_func, rgba, p, j); + shadow_compare(sampler, rgba, p, j); } } } @@ -1121,10 +1188,7 @@ sp_get_samples_rect(const struct tgsi_sampler *tgsi_sampler, get_texel(tgsi_sampler, face, level0, x0[j], y1[j], 0, tx, 2); get_texel(tgsi_sampler, face, level0, x1[j], y1[j], 0, tx, 3); if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { - shadow_compare(compare_func, tx, p, 0); - shadow_compare(compare_func, tx, p, 1); - shadow_compare(compare_func, tx, p, 2); - shadow_compare(compare_func, tx, p, 3); + shadow_compare4(sampler, tx, p); } for (c = 0; c < 4; c++) { rgba[c][j] = lerp_2d(xw[j], yw[j], diff --git a/src/gallium/drivers/trace/Makefile b/src/gallium/drivers/trace/Makefile index e087db169aa..dd6831c70ab 100644 --- a/src/gallium/drivers/trace/Makefile +++ b/src/gallium/drivers/trace/Makefile @@ -7,8 +7,11 @@ C_SOURCES = \ tr_buffer.c \ tr_context.c \ tr_dump.c \ + tr_dump_state.c \ tr_screen.c \ tr_state.c \ + tr_rbug.c \ + tr_drm.c \ tr_texture.c include ../../Makefile.template diff --git a/src/gallium/drivers/trace/README b/src/gallium/drivers/trace/README index 73dce20372e..1000c31e49a 100644 --- a/src/gallium/drivers/trace/README +++ b/src/gallium/drivers/trace/README @@ -3,7 +3,8 @@ = About = -This directory contains a Gallium3D pipe driver which traces all incoming calls. +This directory contains a Gallium3D debugger pipe driver. +It can traces all incoming calls and/or provide remote debugging functionality. = Build Instructions = @@ -23,7 +24,9 @@ ensure the right libGL.so is being picked by doing ldd progs/trivial/tri -and then try running +== Traceing == + +For traceing then do export XMESA_TRACE=y GALLIUM_TRACE=tri.trace progs/trivial/tri @@ -32,6 +35,16 @@ which should create a tri.trace file, which is an XML file. You can view copying trace.xsl to the same directory, and opening with a XSLT capable browser such as Firefox or Internet Explorer. +== Remote debugging == + +For remote debugging + + export XMESA_TRACE=y + GALLIUM_RBUG=true progs/trivial/tri + +which should open gallium remote debugging session. While the program is running +you can launch the small remote debugging application from progs/rbug. More +information is in that directory. = Integrating = @@ -62,3 +75,4 @@ trace_screen with real_screen when creating them. -- Jose Fonseca <[email protected]> +Jakob Bornecrantz <[email protected]> diff --git a/src/gallium/drivers/trace/SConscript b/src/gallium/drivers/trace/SConscript index 4215215d1a1..c1675d1c165 100644 --- a/src/gallium/drivers/trace/SConscript +++ b/src/gallium/drivers/trace/SConscript @@ -7,9 +7,12 @@ trace = env.ConvenienceLibrary( source = [ 'tr_buffer.c', 'tr_context.c', + 'tr_drm.c', 'tr_dump.c', + 'tr_dump_state.c', 'tr_screen.c', 'tr_state.c', + 'tr_rbug.c', 'tr_texture.c', ]) diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c index 47280459a75..4ab718f233d 100644 --- a/src/gallium/drivers/trace/tr_context.c +++ b/src/gallium/drivers/trace/tr_context.c @@ -31,11 +31,11 @@ #include "pipe/p_screen.h" #include "tr_dump.h" +#include "tr_dump_state.h" #include "tr_state.h" #include "tr_buffer.h" #include "tr_screen.h" #include "tr_texture.h" -#include "tr_context.h" static INLINE struct pipe_buffer * @@ -113,6 +113,65 @@ trace_context_set_edgeflags(struct pipe_context *_pipe, } +static INLINE void +trace_context_draw_block(struct trace_context *tr_ctx, int flag) +{ + int k; + + pipe_mutex_lock(tr_ctx->draw_mutex); + + if (tr_ctx->draw_blocker & flag) { + tr_ctx->draw_blocked |= flag; + } else if ((tr_ctx->draw_rule.blocker & flag) && + (tr_ctx->draw_blocker & 4)) { + boolean block = FALSE; + debug_printf("%s (%lu %lu) (%lu %lu) (%lu %u) (%lu %u)\n", __FUNCTION__, + tr_ctx->draw_rule.fs, tr_ctx->curr.fs, + tr_ctx->draw_rule.vs, tr_ctx->curr.vs, + tr_ctx->draw_rule.surf, 0, + tr_ctx->draw_rule.tex, 0); + if (tr_ctx->draw_rule.fs && + tr_ctx->draw_rule.fs == tr_ctx->curr.fs) + block = TRUE; + if (tr_ctx->draw_rule.vs && + tr_ctx->draw_rule.vs == tr_ctx->curr.vs) + block = TRUE; + if (tr_ctx->draw_rule.surf && + tr_ctx->draw_rule.surf == tr_ctx->curr.zsbuf) + block = TRUE; + if (tr_ctx->draw_rule.surf) + for (k = 0; k < tr_ctx->curr.nr_cbufs; k++) + if (tr_ctx->draw_rule.surf == tr_ctx->curr.cbufs[k]) + block = TRUE; + if (tr_ctx->draw_rule.tex) + for (k = 0; k < tr_ctx->curr.num_texs; k++) + if (tr_ctx->draw_rule.tex == tr_ctx->curr.tex[k]) + block = TRUE; + + if (block) + tr_ctx->draw_blocked |= (flag | 4); + } + + if (tr_ctx->draw_blocked) + trace_rbug_notify_draw_blocked(tr_ctx); + + /* wait for rbug to clear the blocked flag */ + while (tr_ctx->draw_blocked & flag) { + tr_ctx->draw_blocked |= flag; +#ifdef PIPE_THREAD_HAVE_CONDVAR + pipe_condvar_wait(tr_ctx->draw_cond, tr_ctx->draw_mutex); +#else + pipe_mutex_unlock(tr_ctx->draw_mutex); +#ifdef PIPE_SUBSYSTEM_WINDOWS_USER + Sleep(1); +#endif + pipe_mutex_lock(tr_ctx->draw_mutex); +#endif + } + + pipe_mutex_unlock(tr_ctx->draw_mutex); +} + static INLINE boolean trace_context_draw_arrays(struct pipe_context *_pipe, unsigned mode, unsigned start, unsigned count) @@ -121,6 +180,11 @@ trace_context_draw_arrays(struct pipe_context *_pipe, struct pipe_context *pipe = tr_ctx->pipe; boolean result; + if (tr_ctx->curr.fs->disabled || tr_ctx->curr.vs->disabled) + return 0; + + trace_context_draw_block(tr_ctx, 1); + trace_dump_call_begin("pipe_context", "draw_arrays"); trace_dump_arg(ptr, pipe); @@ -134,6 +198,8 @@ trace_context_draw_arrays(struct pipe_context *_pipe, trace_dump_call_end(); + trace_context_draw_block(tr_ctx, 2); + return result; } @@ -150,6 +216,11 @@ trace_context_draw_elements(struct pipe_context *_pipe, struct pipe_buffer *indexBuffer = tr_buf->buffer; boolean result; + if (tr_ctx->curr.fs->disabled || tr_ctx->curr.vs->disabled) + return 0; + + trace_context_draw_block(tr_ctx, 1); + trace_screen_user_buffer_update(_pipe->screen, indexBuffer); trace_dump_call_begin("pipe_context", "draw_elements"); @@ -167,6 +238,8 @@ trace_context_draw_elements(struct pipe_context *_pipe, trace_dump_call_end(); + trace_context_draw_block(tr_ctx, 2); + return result; } @@ -187,6 +260,11 @@ trace_context_draw_range_elements(struct pipe_context *_pipe, struct pipe_buffer *indexBuffer = tr_buf->buffer; boolean result; + if (tr_ctx->curr.fs->disabled || tr_ctx->curr.vs->disabled) + return 0; + + trace_context_draw_block(tr_ctx, 1); + trace_screen_user_buffer_update(_pipe->screen, indexBuffer); trace_dump_call_begin("pipe_context", "draw_range_elements"); @@ -209,6 +287,8 @@ trace_context_draw_range_elements(struct pipe_context *_pipe, trace_dump_call_end(); + trace_context_draw_block(tr_ctx, 2); + return result; } @@ -573,23 +653,32 @@ trace_context_create_fs_state(struct pipe_context *_pipe, trace_dump_call_end(); + result = trace_shader_create(tr_ctx, state, result, TRACE_SHADER_FRAGMENT); + return result; } static INLINE void trace_context_bind_fs_state(struct pipe_context *_pipe, - void *state) + void *_state) { struct trace_context *tr_ctx = trace_context(_pipe); + struct trace_shader *tr_shdr = trace_shader(_state); struct pipe_context *pipe = tr_ctx->pipe; + void *state = tr_shdr ? tr_shdr->state : NULL; trace_dump_call_begin("pipe_context", "bind_fs_state"); trace_dump_arg(ptr, pipe); trace_dump_arg(ptr, state); - pipe->bind_fs_state(pipe, state);; + tr_ctx->curr.fs = tr_shdr; + + if (tr_shdr && tr_shdr->replaced) + state = tr_shdr->replaced; + + pipe->bind_fs_state(pipe, state); trace_dump_call_end(); } @@ -597,19 +686,23 @@ trace_context_bind_fs_state(struct pipe_context *_pipe, static INLINE void trace_context_delete_fs_state(struct pipe_context *_pipe, - void *state) + void *_state) { struct trace_context *tr_ctx = trace_context(_pipe); + struct trace_shader *tr_shdr = trace_shader(_state); struct pipe_context *pipe = tr_ctx->pipe; + void *state = tr_shdr->state; trace_dump_call_begin("pipe_context", "delete_fs_state"); trace_dump_arg(ptr, pipe); trace_dump_arg(ptr, state); - pipe->delete_fs_state(pipe, state);; + pipe->delete_fs_state(pipe, state); trace_dump_call_end(); + + trace_shader_destroy(tr_ctx, tr_shdr); } @@ -626,28 +719,37 @@ trace_context_create_vs_state(struct pipe_context *_pipe, trace_dump_arg(ptr, pipe); trace_dump_arg(shader_state, state); - result = pipe->create_vs_state(pipe, state);; + result = pipe->create_vs_state(pipe, state); trace_dump_ret(ptr, result); trace_dump_call_end(); + result = trace_shader_create(tr_ctx, state, result, TRACE_SHADER_VERTEX); + return result; } static INLINE void trace_context_bind_vs_state(struct pipe_context *_pipe, - void *state) + void *_state) { struct trace_context *tr_ctx = trace_context(_pipe); + struct trace_shader *tr_shdr = trace_shader(_state); struct pipe_context *pipe = tr_ctx->pipe; + void *state = tr_shdr ? tr_shdr->state : NULL; trace_dump_call_begin("pipe_context", "bind_vs_state"); trace_dump_arg(ptr, pipe); trace_dump_arg(ptr, state); + tr_ctx->curr.vs = tr_shdr; + + if (tr_shdr && tr_shdr->replaced) + state = tr_shdr->replaced; + pipe->bind_vs_state(pipe, state);; trace_dump_call_end(); @@ -656,10 +758,12 @@ trace_context_bind_vs_state(struct pipe_context *_pipe, static INLINE void trace_context_delete_vs_state(struct pipe_context *_pipe, - void *state) + void *_state) { struct trace_context *tr_ctx = trace_context(_pipe); + struct trace_shader *tr_shdr = trace_shader(_state); struct pipe_context *pipe = tr_ctx->pipe; + void *state = tr_shdr->state; trace_dump_call_begin("pipe_context", "delete_vs_state"); @@ -669,6 +773,8 @@ trace_context_delete_vs_state(struct pipe_context *_pipe, pipe->delete_vs_state(pipe, state);; trace_dump_call_end(); + + trace_shader_destroy(tr_ctx, tr_shdr); } @@ -747,6 +853,19 @@ trace_context_set_framebuffer_state(struct pipe_context *_pipe, struct pipe_framebuffer_state unwrapped_state; unsigned i; + { + tr_ctx->curr.nr_cbufs = state->nr_cbufs; + for (i = 0; i < state->nr_cbufs; i++) + if (state->cbufs[i]) + tr_ctx->curr.cbufs[i] = trace_texture(state->cbufs[i]->texture); + else + tr_ctx->curr.cbufs[i] = NULL; + if (state->zsbuf) + tr_ctx->curr.zsbuf = trace_texture(state->zsbuf->texture); + else + tr_ctx->curr.zsbuf = NULL; + } + /* Unwrap the input state */ memcpy(&unwrapped_state, state, sizeof(unwrapped_state)); for(i = 0; i < state->nr_cbufs; ++i) @@ -827,12 +946,17 @@ trace_context_set_sampler_textures(struct pipe_context *_pipe, struct pipe_texture **textures) { struct trace_context *tr_ctx = trace_context(_pipe); + struct trace_texture *tr_tex; struct pipe_context *pipe = tr_ctx->pipe; struct pipe_texture *unwrapped_textures[PIPE_MAX_SAMPLERS]; unsigned i; - for(i = 0; i < num_textures; ++i) - unwrapped_textures[i] = trace_texture_unwrap(tr_ctx, textures[i]); + tr_ctx->curr.num_texs = num_textures; + for(i = 0; i < num_textures; ++i) { + tr_tex = trace_texture(textures[i]); + tr_ctx->curr.tex[i] = tr_tex; + unwrapped_textures[i] = tr_tex ? tr_tex->texture : NULL; + } textures = unwrapped_textures; trace_dump_call_begin("pipe_context", "set_sampler_textures"); @@ -1078,6 +1202,12 @@ trace_is_buffer_referenced( struct pipe_context *_pipe, return referenced; } +static const struct debug_named_value rbug_blocker_flags[] = { + {"before", 1}, + {"after", 2}, + {NULL, 0}, +}; + struct pipe_context * trace_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) @@ -1089,7 +1219,7 @@ trace_context_create(struct pipe_screen *_screen, if(!pipe) goto error1; - if(!trace_dump_trace_enabled()) + if(!trace_enabled()) goto error1; tr_scr = trace_screen(_screen); @@ -1099,6 +1229,14 @@ trace_context_create(struct pipe_screen *_screen, if(!tr_ctx) goto error1; + tr_ctx->draw_blocker = debug_get_flags_option("RBUG_BLOCK", + rbug_blocker_flags, + 0); + pipe_mutex_init(tr_ctx->draw_mutex); + pipe_condvar_init(tr_ctx->draw_cond); + pipe_mutex_init(tr_ctx->list_mutex); + make_empty_list(&tr_ctx->shaders); + tr_ctx->base.winsys = _screen->winsys; tr_ctx->base.screen = _screen; tr_ctx->base.destroy = trace_context_destroy; diff --git a/src/gallium/drivers/trace/tr_context.h b/src/gallium/drivers/trace/tr_context.h index 2512a0a2328..6febe4b4114 100644 --- a/src/gallium/drivers/trace/tr_context.h +++ b/src/gallium/drivers/trace/tr_context.h @@ -33,6 +33,7 @@ #include "util/u_debug.h" #include "pipe/p_context.h" +#include "tr_screen.h" #ifdef __cplusplus extern "C" { @@ -45,7 +46,41 @@ struct trace_context struct pipe_context *pipe; + /* current state */ + struct { + struct trace_shader *fs; + struct trace_shader *vs; + + struct trace_texture *tex[PIPE_MAX_SAMPLERS]; + unsigned num_texs; + + unsigned nr_cbufs; + struct trace_texture *cbufs[PIPE_MAX_COLOR_BUFS]; + struct trace_texture *zsbuf; + } curr; + + struct { + struct trace_shader *fs; + struct trace_shader *vs; + + struct trace_texture *tex; + struct trace_texture *surf; + + int blocker; + } draw_rule; + unsigned draw_num_rules; + pipe_condvar draw_cond; + pipe_mutex draw_mutex; + int draw_blocker; + int draw_blocked; + + /* for list on screen */ struct tr_list list; + + /* list of state objects */ + pipe_mutex list_mutex; + unsigned num_shaders; + struct tr_list shaders; }; @@ -62,6 +97,9 @@ struct pipe_context * trace_context_create(struct pipe_screen *screen, struct pipe_context *pipe); +void +trace_rbug_notify_draw_blocked(struct trace_context *tr_ctx); + #ifdef __cplusplus } diff --git a/src/gallium/drivers/trace/tr_drm.c b/src/gallium/drivers/trace/tr_drm.c new file mode 100644 index 00000000000..98ac75e3fa3 --- /dev/null +++ b/src/gallium/drivers/trace/tr_drm.c @@ -0,0 +1,211 @@ +/************************************************************************** + * + * 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 "state_tracker/drm_api.h" + +#include "util/u_memory.h" +#include "trace/tr_drm.h" +#include "trace/tr_screen.h" +#include "trace/tr_context.h" +#include "trace/tr_buffer.h" +#include "trace/tr_texture.h" + +struct trace_drm_api +{ + struct drm_api base; + + struct drm_api *api; +}; + +static INLINE struct trace_drm_api * +trace_drm_api(struct drm_api *_api) +{ + return (struct trace_drm_api *)_api; +} + +static struct pipe_screen * +trace_drm_create_screen(struct drm_api *_api, int fd, + struct drm_create_screen_arg *arg) +{ + struct trace_drm_api *tr_api = trace_drm_api(_api); + struct drm_api *api = tr_api->api; + struct pipe_screen *screen; + + /* TODO trace call */ + + if (arg && arg->mode != DRM_CREATE_NORMAL) + return NULL; + + screen = api->create_screen(api, fd, arg); + + return trace_screen_create(screen); +}; + +static struct pipe_context * +trace_drm_create_context(struct drm_api *_api, + struct pipe_screen *_screen) +{ + struct trace_screen *tr_screen = trace_screen(_screen); + struct trace_drm_api *tr_api = trace_drm_api(_api); + struct pipe_screen *screen = tr_screen->screen; + struct drm_api *api = tr_api->api; + struct pipe_context *pipe; + + /* TODO trace call */ + + pipe = api->create_context(api, screen); + + pipe = trace_context_create(_screen, pipe); + + return pipe; +}; + +static boolean +trace_drm_buffer_from_texture(struct drm_api *_api, + struct pipe_texture *_texture, + struct pipe_buffer **_buffer, + unsigned *stride) +{ + struct trace_texture *tr_texture = trace_texture(_texture); + struct trace_drm_api *tr_api = trace_drm_api(_api); + struct pipe_texture *texture = tr_texture->texture; + struct drm_api *api = tr_api->api; + struct pipe_buffer *buffer = NULL; + boolean result; + + /* TODO trace call */ + + result = api->buffer_from_texture(api, texture, &buffer, stride); + + if (result && _buffer) + buffer = trace_buffer_create(trace_screen(texture->screen), buffer); + + if (_buffer) + *_buffer = buffer; + else + pipe_buffer_reference(&buffer, NULL); + + return result; +} + +static struct pipe_buffer * +trace_drm_buffer_from_handle(struct drm_api *_api, + struct pipe_screen *_screen, + const char *name, + unsigned handle) +{ + struct trace_screen *tr_screen = trace_screen(_screen); + struct trace_drm_api *tr_api = trace_drm_api(_api); + struct pipe_screen *screen = tr_screen->screen; + struct drm_api *api = tr_api->api; + struct pipe_buffer *result; + + /* TODO trace call */ + + result = api->buffer_from_handle(api, screen, name, handle); + + result = trace_buffer_create(trace_screen(_screen), result); + + return result; +} + +static boolean +trace_drm_handle_from_buffer(struct drm_api *_api, + struct pipe_screen *_screen, + struct pipe_buffer *_buffer, + unsigned *handle) +{ + struct trace_screen *tr_screen = trace_screen(_screen); + struct trace_buffer *tr_buffer = trace_buffer(_buffer); + struct trace_drm_api *tr_api = trace_drm_api(_api); + struct pipe_screen *screen = tr_screen->screen; + struct pipe_buffer *buffer = tr_buffer->buffer; + struct drm_api *api = tr_api->api; + + /* TODO trace call */ + + return api->handle_from_buffer(api, screen, buffer, handle); +} + +static boolean +trace_drm_global_handle_from_buffer(struct drm_api *_api, + struct pipe_screen *_screen, + struct pipe_buffer *_buffer, + unsigned *handle) +{ + struct trace_screen *tr_screen = trace_screen(_screen); + struct trace_buffer *tr_buffer = trace_buffer(_buffer); + struct trace_drm_api *tr_api = trace_drm_api(_api); + struct pipe_screen *screen = tr_screen->screen; + struct pipe_buffer *buffer = tr_buffer->buffer; + struct drm_api *api = tr_api->api; + + /* TODO trace call */ + + return api->global_handle_from_buffer(api, screen, buffer, handle); +} + +static void +trace_drm_destroy(struct drm_api *_api) +{ + struct trace_drm_api *tr_api = trace_drm_api(_api); + struct drm_api *api = tr_api->api; + api->destroy(api); + + free(tr_api); +} + +struct drm_api * +trace_drm_create(struct drm_api *api) +{ + struct trace_drm_api *tr_api; + + if (!api) + goto error; + + if (!trace_enabled()) + goto error; + + tr_api = CALLOC_STRUCT(trace_drm_api); + + if (!tr_api) + goto error; + + tr_api->base.create_screen = trace_drm_create_screen; + tr_api->base.create_context = trace_drm_create_context; + tr_api->base.buffer_from_texture = trace_drm_buffer_from_texture; + tr_api->base.buffer_from_handle = trace_drm_buffer_from_handle; + tr_api->base.handle_from_buffer = trace_drm_handle_from_buffer; + tr_api->base.global_handle_from_buffer = trace_drm_global_handle_from_buffer; + tr_api->base.destroy = trace_drm_destroy; + tr_api->api = api; + + return &tr_api->base; + +error: + return api; +} diff --git a/src/gallium/drivers/trace/tr_drm.h b/src/gallium/drivers/trace/tr_drm.h new file mode 100644 index 00000000000..845c66a32aa --- /dev/null +++ b/src/gallium/drivers/trace/tr_drm.h @@ -0,0 +1,35 @@ +/************************************************************************** + * + * 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 TR_DRM_H +#define TR_DRM_H + +struct drm_api; + +struct drm_api* trace_drm_create(struct drm_api *api); + +#endif /* ID_DRM_H */ diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c new file mode 100644 index 00000000000..bcf6751af4f --- /dev/null +++ b/src/gallium/drivers/trace/tr_dump_state.c @@ -0,0 +1,549 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + + +#include "pipe/p_compiler.h" +#include "util/u_memory.h" +#include "tgsi/tgsi_dump.h" + +#include "tr_dump.h" +#include "tr_dump_state.h" + + +void trace_dump_format(enum pipe_format format) +{ + if (!trace_dumping_enabled_locked()) + return; + + trace_dump_enum(pf_name(format) ); +} + + +void trace_dump_block(const struct pipe_format_block *block) +{ + if (!trace_dumping_enabled_locked()) + return; + + trace_dump_struct_begin("pipe_format_block"); + trace_dump_member(uint, block, size); + trace_dump_member(uint, block, width); + trace_dump_member(uint, block, height); + trace_dump_struct_end(); +} + + +static void trace_dump_reference(const struct pipe_reference *reference) +{ + if (!trace_dumping_enabled_locked()) + return; + + trace_dump_struct_begin("pipe_reference"); + trace_dump_member(int, &reference->count, count); + trace_dump_struct_end(); +} + + +void trace_dump_template(const struct pipe_texture *templat) +{ + if (!trace_dumping_enabled_locked()) + return; + + if(!templat) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_texture"); + + trace_dump_member(int, templat, target); + trace_dump_member(format, templat, format); + + trace_dump_member_begin("width"); + trace_dump_array(uint, templat->width, 1); + trace_dump_member_end(); + + trace_dump_member_begin("height"); + trace_dump_array(uint, templat->height, 1); + trace_dump_member_end(); + + trace_dump_member_begin("depth"); + trace_dump_array(uint, templat->depth, 1); + trace_dump_member_end(); + + trace_dump_member_begin("block"); + trace_dump_block(&templat->block); + trace_dump_member_end(); + + trace_dump_member(uint, templat, last_level); + trace_dump_member(uint, templat, tex_usage); + + trace_dump_struct_end(); +} + + +void trace_dump_rasterizer_state(const struct pipe_rasterizer_state *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_rasterizer_state"); + + trace_dump_member(bool, state, flatshade); + trace_dump_member(bool, state, light_twoside); + trace_dump_member(uint, state, front_winding); + trace_dump_member(uint, state, cull_mode); + trace_dump_member(uint, state, fill_cw); + trace_dump_member(uint, state, fill_ccw); + trace_dump_member(bool, state, offset_cw); + trace_dump_member(bool, state, offset_ccw); + trace_dump_member(bool, state, scissor); + trace_dump_member(bool, state, poly_smooth); + trace_dump_member(bool, state, poly_stipple_enable); + trace_dump_member(bool, state, point_smooth); + trace_dump_member(bool, state, point_sprite); + trace_dump_member(bool, state, point_size_per_vertex); + trace_dump_member(bool, state, multisample); + trace_dump_member(bool, state, line_smooth); + trace_dump_member(bool, state, line_stipple_enable); + trace_dump_member(uint, state, line_stipple_factor); + trace_dump_member(uint, state, line_stipple_pattern); + trace_dump_member(bool, state, line_last_pixel); + trace_dump_member(bool, state, bypass_vs_clip_and_viewport); + trace_dump_member(bool, state, flatshade_first); + trace_dump_member(bool, state, gl_rasterization_rules); + + trace_dump_member(float, state, line_width); + trace_dump_member(float, state, point_size); + trace_dump_member(float, state, point_size_min); + trace_dump_member(float, state, point_size_max); + trace_dump_member(float, state, offset_units); + trace_dump_member(float, state, offset_scale); + + trace_dump_member_array(uint, state, sprite_coord_mode); + + trace_dump_struct_end(); +} + + +void trace_dump_poly_stipple(const struct pipe_poly_stipple *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_poly_stipple"); + + trace_dump_member_begin("stipple"); + trace_dump_array(uint, + state->stipple, + Elements(state->stipple)); + trace_dump_member_end(); + + trace_dump_struct_end(); +} + + +void trace_dump_viewport_state(const struct pipe_viewport_state *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_viewport_state"); + + trace_dump_member_array(float, state, scale); + trace_dump_member_array(float, state, translate); + + trace_dump_struct_end(); +} + + +void trace_dump_scissor_state(const struct pipe_scissor_state *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_scissor_state"); + + trace_dump_member(uint, state, minx); + trace_dump_member(uint, state, miny); + trace_dump_member(uint, state, maxx); + trace_dump_member(uint, state, maxy); + + trace_dump_struct_end(); +} + + +void trace_dump_clip_state(const struct pipe_clip_state *state) +{ + unsigned i; + + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_clip_state"); + + trace_dump_member_begin("ucp"); + trace_dump_array_begin(); + for(i = 0; i < PIPE_MAX_CLIP_PLANES; ++i) { + trace_dump_elem_begin(); + trace_dump_array(float, state->ucp[i], 4); + trace_dump_elem_end(); + } + trace_dump_array_end(); + trace_dump_member_end(); + + trace_dump_member(uint, state, nr); + + trace_dump_struct_end(); +} + + +void trace_dump_constant_buffer(const struct pipe_constant_buffer *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_constant_buffer"); + + trace_dump_member(buffer_ptr, state, buffer); + + trace_dump_struct_end(); +} + + +void trace_dump_shader_state(const struct pipe_shader_state *state) +{ + static char str[8192]; + + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + tgsi_dump_str(state->tokens, 0, str, sizeof(str)); + + trace_dump_struct_begin("pipe_shader_state"); + + trace_dump_member_begin("tokens"); + trace_dump_string(str); + trace_dump_member_end(); + + trace_dump_struct_end(); +} + + +void trace_dump_depth_stencil_alpha_state(const struct pipe_depth_stencil_alpha_state *state) +{ + unsigned i; + + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_depth_stencil_alpha_state"); + + trace_dump_member_begin("depth"); + trace_dump_struct_begin("pipe_depth_state"); + trace_dump_member(bool, &state->depth, enabled); + trace_dump_member(bool, &state->depth, writemask); + trace_dump_member(uint, &state->depth, func); + trace_dump_struct_end(); + trace_dump_member_end(); + + trace_dump_member_begin("stencil"); + trace_dump_array_begin(); + for(i = 0; i < Elements(state->stencil); ++i) { + trace_dump_elem_begin(); + trace_dump_struct_begin("pipe_stencil_state"); + trace_dump_member(bool, &state->stencil[i], enabled); + trace_dump_member(uint, &state->stencil[i], func); + trace_dump_member(uint, &state->stencil[i], fail_op); + trace_dump_member(uint, &state->stencil[i], zpass_op); + trace_dump_member(uint, &state->stencil[i], zfail_op); + trace_dump_member(uint, &state->stencil[i], ref_value); + trace_dump_member(uint, &state->stencil[i], valuemask); + trace_dump_member(uint, &state->stencil[i], writemask); + trace_dump_struct_end(); + trace_dump_elem_end(); + } + trace_dump_array_end(); + trace_dump_member_end(); + + trace_dump_member_begin("alpha"); + trace_dump_struct_begin("pipe_alpha_state"); + trace_dump_member(bool, &state->alpha, enabled); + trace_dump_member(uint, &state->alpha, func); + trace_dump_member(float, &state->alpha, ref_value); + trace_dump_struct_end(); + trace_dump_member_end(); + + trace_dump_struct_end(); +} + + +void trace_dump_blend_state(const struct pipe_blend_state *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_blend_state"); + + trace_dump_member(bool, state, blend_enable); + + trace_dump_member(uint, state, rgb_func); + trace_dump_member(uint, state, rgb_src_factor); + trace_dump_member(uint, state, rgb_dst_factor); + + trace_dump_member(uint, state, alpha_func); + trace_dump_member(uint, state, alpha_src_factor); + trace_dump_member(uint, state, alpha_dst_factor); + + trace_dump_member(bool, state, logicop_enable); + trace_dump_member(uint, state, logicop_func); + + trace_dump_member(uint, state, colormask); + trace_dump_member(bool, state, dither); + + trace_dump_struct_end(); +} + + +void trace_dump_blend_color(const struct pipe_blend_color *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_blend_color"); + + trace_dump_member_array(float, state, color); + + trace_dump_struct_end(); +} + + +void trace_dump_framebuffer_state(const struct pipe_framebuffer_state *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + trace_dump_struct_begin("pipe_framebuffer_state"); + + trace_dump_member(uint, state, width); + trace_dump_member(uint, state, height); + trace_dump_member(uint, state, nr_cbufs); + trace_dump_member_array(ptr, state, cbufs); + trace_dump_member(ptr, state, zsbuf); + + trace_dump_struct_end(); +} + + +void trace_dump_sampler_state(const struct pipe_sampler_state *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_sampler_state"); + + trace_dump_member(uint, state, wrap_s); + trace_dump_member(uint, state, wrap_t); + trace_dump_member(uint, state, wrap_r); + trace_dump_member(uint, state, min_img_filter); + trace_dump_member(uint, state, min_mip_filter); + trace_dump_member(uint, state, mag_img_filter); + trace_dump_member(bool, state, compare_mode); + trace_dump_member(uint, state, compare_func); + trace_dump_member(bool, state, normalized_coords); + trace_dump_member(uint, state, prefilter); + trace_dump_member(float, state, lod_bias); + trace_dump_member(float, state, min_lod); + trace_dump_member(float, state, max_lod); + trace_dump_member_array(float, state, border_color); + trace_dump_member(float, state, max_anisotropy); + + trace_dump_struct_end(); +} + + +void trace_dump_surface(const struct pipe_surface *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_surface"); + + trace_dump_reference(&state->reference); + + trace_dump_member(format, state, format); + trace_dump_member(uint, state, width); + trace_dump_member(uint, state, height); + + trace_dump_member(uint, state, layout); + trace_dump_member(uint, state, offset); + trace_dump_member(uint, state, usage); + + trace_dump_member(ptr, state, texture); + trace_dump_member(uint, state, face); + trace_dump_member(uint, state, level); + trace_dump_member(uint, state, zslice); + + trace_dump_struct_end(); +} + + +void trace_dump_transfer(const struct pipe_transfer *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_transfer"); + + trace_dump_member(format, state, format); + trace_dump_member(uint, state, width); + trace_dump_member(uint, state, height); + + trace_dump_member_begin("block"); + trace_dump_block(&state->block); + trace_dump_member_end(); + + trace_dump_member(uint, state, nblocksx); + trace_dump_member(uint, state, nblocksy); + trace_dump_member(uint, state, stride); + trace_dump_member(uint, state, usage); + + trace_dump_member(ptr, state, texture); + trace_dump_member(uint, state, face); + trace_dump_member(uint, state, level); + trace_dump_member(uint, state, zslice); + + trace_dump_struct_end(); +} + + +void trace_dump_vertex_buffer(const struct pipe_vertex_buffer *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_vertex_buffer"); + + trace_dump_member(uint, state, stride); + trace_dump_member(uint, state, max_index); + trace_dump_member(uint, state, buffer_offset); + trace_dump_member(buffer_ptr, state, buffer); + + trace_dump_struct_end(); +} + + +void trace_dump_vertex_element(const struct pipe_vertex_element *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_vertex_element"); + + trace_dump_member(uint, state, src_offset); + + trace_dump_member(uint, state, vertex_buffer_index); + trace_dump_member(uint, state, nr_components); + + trace_dump_member(format, state, src_format); + + trace_dump_struct_end(); +} diff --git a/src/gallium/drivers/trace/tr_dump_state.h b/src/gallium/drivers/trace/tr_dump_state.h new file mode 100644 index 00000000000..05b821adb64 --- /dev/null +++ b/src/gallium/drivers/trace/tr_dump_state.h @@ -0,0 +1,78 @@ +/************************************************************************** + * + * 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 TR_DUMP_STATE_H_ +#define TR_DUMP_STATE_H_ + +#include "pipe/p_format.h" +#include "pipe/p_state.h" +#include "pipe/p_shader_tokens.h" + + +void trace_dump_format(enum pipe_format format); + +void trace_dump_block(const struct pipe_format_block *block); + +void trace_dump_template(const struct pipe_texture *templat); + + +void trace_dump_rasterizer_state(const struct pipe_rasterizer_state *state); + +void trace_dump_poly_stipple(const struct pipe_poly_stipple *state); + +void trace_dump_viewport_state(const struct pipe_viewport_state *state); + +void trace_dump_scissor_state(const struct pipe_scissor_state *state); + +void trace_dump_clip_state(const struct pipe_clip_state *state); + +void trace_dump_constant_buffer(const struct pipe_constant_buffer *state); + +void trace_dump_token(const struct tgsi_token *token); + +void trace_dump_shader_state(const struct pipe_shader_state *state); + +void trace_dump_depth_stencil_alpha_state(const struct pipe_depth_stencil_alpha_state *state); + +void trace_dump_blend_state(const struct pipe_blend_state *state); + +void trace_dump_blend_color(const struct pipe_blend_color *state); + +void trace_dump_framebuffer_state(const struct pipe_framebuffer_state *state); + +void trace_dump_sampler_state(const struct pipe_sampler_state *state); + +void trace_dump_surface(const struct pipe_surface *state); + +void trace_dump_transfer(const struct pipe_transfer *state); + +void trace_dump_vertex_buffer(const struct pipe_vertex_buffer *state); + +void trace_dump_vertex_element(const struct pipe_vertex_element *state); + + +#endif /* TR_STATE_H */ diff --git a/src/gallium/drivers/trace/tr_rbug.c b/src/gallium/drivers/trace/tr_rbug.c new file mode 100644 index 00000000000..e85ac15edca --- /dev/null +++ b/src/gallium/drivers/trace/tr_rbug.c @@ -0,0 +1,864 @@ +/************************************************************************** + * + * 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 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. + * + **************************************************************************/ + + +#include "util/u_string.h" +#include "util/u_memory.h" +#include "util/u_simple_list.h" +#include "util/u_network.h" + +#include "tgsi/tgsi_parse.h" + +#include "tr_dump.h" +#include "tr_state.h" +#include "tr_buffer.h" +#include "tr_texture.h" + +#include "rbug/rbug.h" + +#include <errno.h> + +#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) +# define sleep Sleep +#elif defined(PIPE_OS_LINUX) +void usleep(int); +# define sleep usleep +#else +# warning "No socket implementation" +#endif + +#define U642VOID(x) ((void *)(unsigned long)(x)) +#define VOID2U64(x) ((uint64_t)(unsigned long)(x)) + +struct trace_rbug +{ + struct trace_screen *tr_scr; + struct rbug_connection *con; + pipe_thread thread; + boolean running; +}; + +PIPE_THREAD_ROUTINE(trace_rbug_thread, void_tr_rbug); + + +/********************************************************** + * Helper functions + */ + + +static struct trace_context * +trace_rbug_get_context_locked(struct trace_screen *tr_scr, rbug_context_t ctx) +{ + struct trace_context *tr_ctx = NULL; + struct tr_list *ptr; + + foreach(ptr, &tr_scr->contexts) { + tr_ctx = (struct trace_context *)((char*)ptr - offsetof(struct trace_context, list)); + if (ctx == VOID2U64(tr_ctx)) + break; + tr_ctx = NULL; + } + + return tr_ctx; +} + +static struct trace_shader * +trace_rbug_get_shader_locked(struct trace_context *tr_ctx, rbug_shader_t shdr) +{ + struct trace_shader *tr_shdr = NULL; + struct tr_list *ptr; + + foreach(ptr, &tr_ctx->shaders) { + tr_shdr = (struct trace_shader *)((char*)ptr - offsetof(struct trace_shader, list)); + if (shdr == VOID2U64(tr_shdr)) + break; + tr_shdr = NULL; + } + + return tr_shdr; +} + +static void * +trace_shader_create_locked(struct pipe_context *pipe, + struct trace_shader *tr_shdr, + struct tgsi_token *tokens) +{ + void *state = NULL; + struct pipe_shader_state pss = { 0 }; + pss.tokens = tokens; + + if (tr_shdr->type == TRACE_SHADER_FRAGMENT) { + state = pipe->create_fs_state(pipe, &pss); + } else if (tr_shdr->type == TRACE_SHADER_VERTEX) { + state = pipe->create_vs_state(pipe, &pss); + } else + assert(0); + + return state; +} + +static void +trace_shader_bind_locked(struct pipe_context *pipe, + struct trace_shader *tr_shdr, + void *state) +{ + if (tr_shdr->type == TRACE_SHADER_FRAGMENT) { + pipe->bind_fs_state(pipe, state); + } else if (tr_shdr->type == TRACE_SHADER_VERTEX) { + pipe->bind_vs_state(pipe, state); + } else + assert(0); +} + +static void +trace_shader_delete_locked(struct pipe_context *pipe, + struct trace_shader *tr_shdr, + void *state) +{ + if (tr_shdr->type == TRACE_SHADER_FRAGMENT) { + pipe->delete_fs_state(pipe, state); + } else if (tr_shdr->type == TRACE_SHADER_VERTEX) { + pipe->delete_vs_state(pipe, state); + } else + assert(0); +} + +/************************************************ + * Request handler functions + */ + + +static int +trace_rbug_texture_list(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct trace_screen *tr_scr = tr_rbug->tr_scr; + struct trace_texture *tr_tex = NULL; + struct tr_list *ptr; + rbug_texture_t *texs; + int i = 0; + + pipe_mutex_lock(tr_scr->list_mutex); + texs = MALLOC(tr_scr->num_textures * sizeof(rbug_texture_t)); + foreach(ptr, &tr_scr->textures) { + tr_tex = (struct trace_texture *)((char*)ptr - offsetof(struct trace_texture, list)); + texs[i++] = VOID2U64(tr_tex); + } + pipe_mutex_unlock(tr_scr->list_mutex); + + rbug_send_texture_list_reply(tr_rbug->con, serial, texs, i, NULL); + FREE(texs); + + return 0; +} + +static int +trace_rbug_texture_info(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct trace_screen *tr_scr = tr_rbug->tr_scr; + struct trace_texture *tr_tex; + struct rbug_proto_texture_info *gpti = (struct rbug_proto_texture_info *)header; + struct tr_list *ptr; + struct pipe_texture *t; + + pipe_mutex_lock(tr_scr->list_mutex); + foreach(ptr, &tr_scr->textures) { + tr_tex = (struct trace_texture *)((char*)ptr - offsetof(struct trace_texture, list)); + if (gpti->texture == VOID2U64(tr_tex)) + break; + tr_tex = NULL; + } + + if (!tr_tex) { + pipe_mutex_unlock(tr_scr->list_mutex); + return -ESRCH; + } + + t = tr_tex->texture; + rbug_send_texture_info_reply(tr_rbug->con, serial, + t->target, t->format, + t->width, t->last_level + 1, + t->height, t->last_level + 1, + t->depth, t->last_level + 1, + t->block.width, t->block.height, t->block.size, + t->last_level, + t->nr_samples, + t->tex_usage, + NULL); + + pipe_mutex_unlock(tr_scr->list_mutex); + + return 0; +} + +static int +trace_rbug_texture_read(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_texture_read *gptr = (struct rbug_proto_texture_read *)header; + + struct trace_screen *tr_scr = tr_rbug->tr_scr; + struct trace_texture *tr_tex; + struct tr_list *ptr; + + struct pipe_screen *screen = tr_scr->screen; + struct pipe_texture *tex; + struct pipe_transfer *t; + + void *map; + + pipe_mutex_lock(tr_scr->list_mutex); + foreach(ptr, &tr_scr->textures) { + tr_tex = (struct trace_texture *)((char*)ptr - offsetof(struct trace_texture, list)); + if (gptr->texture == VOID2U64(tr_tex)) + break; + tr_tex = NULL; + } + + if (!tr_tex) { + pipe_mutex_unlock(tr_scr->list_mutex); + return -ESRCH; + } + + tex = tr_tex->texture; + t = screen->get_tex_transfer(tr_scr->screen, tex, + gptr->face, gptr->level, gptr->zslice, + PIPE_TRANSFER_READ, + gptr->x, gptr->y, gptr->w, gptr->h); + + map = screen->transfer_map(screen, t); + + rbug_send_texture_read_reply(tr_rbug->con, serial, + t->format, + t->block.width, t->block.height, t->block.size, + (uint8_t*)map, t->stride * t->nblocksy, + t->stride, + NULL); + + screen->transfer_unmap(screen, t); + screen->tex_transfer_destroy(t); + + pipe_mutex_unlock(tr_scr->list_mutex); + + return 0; +} + +static int +trace_rbug_context_list(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct trace_screen *tr_scr = tr_rbug->tr_scr; + struct tr_list *ptr; + struct trace_context *tr_ctx = NULL; + rbug_context_t *ctxs; + int i = 0; + + pipe_mutex_lock(tr_scr->list_mutex); + ctxs = MALLOC(tr_scr->num_contexts * sizeof(rbug_context_t)); + foreach(ptr, &tr_scr->contexts) { + tr_ctx = (struct trace_context *)((char*)ptr - offsetof(struct trace_context, list)); + ctxs[i++] = VOID2U64(tr_ctx); + } + pipe_mutex_unlock(tr_scr->list_mutex); + + rbug_send_context_list_reply(tr_rbug->con, serial, ctxs, i, NULL); + FREE(ctxs); + + return 0; +} + +static int +trace_rbug_context_info(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_info *info = (struct rbug_proto_context_info *)header; + + struct trace_screen *tr_scr = tr_rbug->tr_scr; + struct trace_context *tr_ctx = NULL; + rbug_texture_t cbufs[PIPE_MAX_COLOR_BUFS]; + rbug_texture_t texs[PIPE_MAX_SAMPLERS]; + int i; + + pipe_mutex_lock(tr_scr->list_mutex); + tr_ctx = trace_rbug_get_context_locked(tr_scr, info->context); + + if (!tr_ctx) { + pipe_mutex_unlock(tr_scr->list_mutex); + return -ESRCH; + } + + /* protect the pipe context */ + pipe_mutex_lock(tr_ctx->draw_mutex); + trace_dump_call_lock(); + + for (i = 0; i < tr_ctx->curr.nr_cbufs; i++) + cbufs[i] = VOID2U64(tr_ctx->curr.cbufs[i]); + + for (i = 0; i < tr_ctx->curr.num_texs; i++) + texs[i] = VOID2U64(tr_ctx->curr.tex[i]); + + rbug_send_context_info_reply(tr_rbug->con, serial, + VOID2U64(tr_ctx->curr.vs), VOID2U64(tr_ctx->curr.fs), + texs, tr_ctx->curr.num_texs, + cbufs, tr_ctx->curr.nr_cbufs, + VOID2U64(tr_ctx->curr.zsbuf), + tr_ctx->draw_blocker, tr_ctx->draw_blocked, NULL); + + trace_dump_call_unlock(); + pipe_mutex_unlock(tr_ctx->draw_mutex); + + pipe_mutex_unlock(tr_scr->list_mutex); + + return 0; +} + +static int +trace_rbug_context_draw_block(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_draw_block *block = (struct rbug_proto_context_draw_block *)header; + + struct trace_screen *tr_scr = tr_rbug->tr_scr; + struct trace_context *tr_ctx = NULL; + + pipe_mutex_lock(tr_scr->list_mutex); + tr_ctx = trace_rbug_get_context_locked(tr_scr, block->context); + + if (!tr_ctx) { + pipe_mutex_unlock(tr_scr->list_mutex); + return -ESRCH; + } + + pipe_mutex_lock(tr_ctx->draw_mutex); + tr_ctx->draw_blocker |= block->block; + pipe_mutex_unlock(tr_ctx->draw_mutex); + + pipe_mutex_unlock(tr_scr->list_mutex); + + return 0; +} + +static int +trace_rbug_context_draw_step(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_draw_step *step = (struct rbug_proto_context_draw_step *)header; + + struct trace_screen *tr_scr = tr_rbug->tr_scr; + struct trace_context *tr_ctx = NULL; + + pipe_mutex_lock(tr_scr->list_mutex); + tr_ctx = trace_rbug_get_context_locked(tr_scr, step->context); + + if (!tr_ctx) { + pipe_mutex_unlock(tr_scr->list_mutex); + return -ESRCH; + } + + pipe_mutex_lock(tr_ctx->draw_mutex); + if (tr_ctx->draw_blocked & RBUG_BLOCK_RULE) { + if (step->step & RBUG_BLOCK_RULE) + tr_ctx->draw_blocked &= ~RBUG_BLOCK_MASK; + } else { + tr_ctx->draw_blocked &= ~step->step; + } + pipe_mutex_unlock(tr_ctx->draw_mutex); + +#ifdef PIPE_THREAD_HAVE_CONDVAR + pipe_condvar_broadcast(tr_ctx->draw_cond); +#endif + + pipe_mutex_unlock(tr_scr->list_mutex); + + return 0; +} + +static int +trace_rbug_context_draw_unblock(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_draw_unblock *unblock = (struct rbug_proto_context_draw_unblock *)header; + + struct trace_screen *tr_scr = tr_rbug->tr_scr; + struct trace_context *tr_ctx = NULL; + + pipe_mutex_lock(tr_scr->list_mutex); + tr_ctx = trace_rbug_get_context_locked(tr_scr, unblock->context); + + if (!tr_ctx) { + pipe_mutex_unlock(tr_scr->list_mutex); + return -ESRCH; + } + + pipe_mutex_lock(tr_ctx->draw_mutex); + if (tr_ctx->draw_blocked & RBUG_BLOCK_RULE) { + if (unblock->unblock & RBUG_BLOCK_RULE) + tr_ctx->draw_blocked &= ~RBUG_BLOCK_MASK; + } else { + tr_ctx->draw_blocked &= ~unblock->unblock; + } + tr_ctx->draw_blocker &= ~unblock->unblock; + pipe_mutex_unlock(tr_ctx->draw_mutex); + +#ifdef PIPE_THREAD_HAVE_CONDVAR + pipe_condvar_broadcast(tr_ctx->draw_cond); +#endif + + pipe_mutex_unlock(tr_scr->list_mutex); + + return 0; +} + +static int +trace_rbug_context_draw_rule(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_draw_rule *rule = (struct rbug_proto_context_draw_rule *)header; + + struct trace_screen *tr_scr = tr_rbug->tr_scr; + struct trace_context *tr_ctx = NULL; + + pipe_mutex_lock(tr_scr->list_mutex); + tr_ctx = trace_rbug_get_context_locked(tr_scr, rule->context); + + if (!tr_ctx) { + pipe_mutex_unlock(tr_scr->list_mutex); + return -ESRCH; + } + + pipe_mutex_lock(tr_ctx->draw_mutex); + tr_ctx->draw_rule.vs = U642VOID(rule->vertex); + tr_ctx->draw_rule.fs = U642VOID(rule->fragment); + tr_ctx->draw_rule.tex = U642VOID(rule->texture); + tr_ctx->draw_rule.surf = U642VOID(rule->surface); + tr_ctx->draw_rule.blocker = rule->block; + tr_ctx->draw_blocker |= RBUG_BLOCK_RULE; + pipe_mutex_unlock(tr_ctx->draw_mutex); + +#ifdef PIPE_THREAD_HAVE_CONDVAR + pipe_condvar_broadcast(tr_ctx->draw_cond); +#endif + + pipe_mutex_unlock(tr_scr->list_mutex); + + return 0; +} + +static int +trace_rbug_context_flush(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_context_flush *flush = (struct rbug_proto_context_flush *)header; + + struct trace_screen *tr_scr = tr_rbug->tr_scr; + struct trace_context *tr_ctx = NULL; + + pipe_mutex_lock(tr_scr->list_mutex); + tr_ctx = trace_rbug_get_context_locked(tr_scr, flush->context); + + if (!tr_ctx) { + pipe_mutex_unlock(tr_scr->list_mutex); + return -ESRCH; + } + + /* protect the pipe context */ + trace_dump_call_lock(); + + tr_ctx->pipe->flush(tr_ctx->pipe, flush->flags, NULL); + + trace_dump_call_unlock(); + pipe_mutex_unlock(tr_scr->list_mutex); + + return 0; +} + +static int +trace_rbug_shader_list(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_shader_list *list = (struct rbug_proto_shader_list *)header; + + struct trace_screen *tr_scr = tr_rbug->tr_scr; + struct trace_context *tr_ctx = NULL; + struct trace_shader *tr_shdr = NULL; + struct tr_list *ptr; + rbug_shader_t *shdrs; + int i = 0; + + pipe_mutex_lock(tr_scr->list_mutex); + tr_ctx = trace_rbug_get_context_locked(tr_scr, list->context); + + if (!tr_ctx) { + pipe_mutex_unlock(tr_scr->list_mutex); + return -ESRCH; + } + + pipe_mutex_lock(tr_ctx->list_mutex); + shdrs = MALLOC(tr_ctx->num_shaders * sizeof(rbug_shader_t)); + foreach(ptr, &tr_ctx->shaders) { + tr_shdr = (struct trace_shader *)((char*)ptr - offsetof(struct trace_shader, list)); + shdrs[i++] = VOID2U64(tr_shdr); + } + + pipe_mutex_unlock(tr_ctx->list_mutex); + pipe_mutex_unlock(tr_scr->list_mutex); + + rbug_send_shader_list_reply(tr_rbug->con, serial, shdrs, i, NULL); + FREE(shdrs); + + return 0; +} + +static int +trace_rbug_shader_info(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + struct rbug_proto_shader_info *info = (struct rbug_proto_shader_info *)header; + + struct trace_screen *tr_scr = tr_rbug->tr_scr; + struct trace_context *tr_ctx = NULL; + struct trace_shader *tr_shdr = NULL; + unsigned original_len; + unsigned replaced_len; + + pipe_mutex_lock(tr_scr->list_mutex); + tr_ctx = trace_rbug_get_context_locked(tr_scr, info->context); + + if (!tr_ctx) { + pipe_mutex_unlock(tr_scr->list_mutex); + return -ESRCH; + } + + pipe_mutex_lock(tr_ctx->list_mutex); + + tr_shdr = trace_rbug_get_shader_locked(tr_ctx, info->shader); + + if (!tr_shdr) { + pipe_mutex_unlock(tr_ctx->list_mutex); + pipe_mutex_unlock(tr_scr->list_mutex); + return -ESRCH; + } + + /* just in case */ + assert(sizeof(struct tgsi_token) == 4); + + original_len = tgsi_num_tokens(tr_shdr->tokens); + if (tr_shdr->replaced_tokens) + replaced_len = tgsi_num_tokens(tr_shdr->replaced_tokens); + else + replaced_len = 0; + + rbug_send_shader_info_reply(tr_rbug->con, serial, + (uint32_t*)tr_shdr->tokens, original_len, + (uint32_t*)tr_shdr->replaced_tokens, replaced_len, + tr_shdr->disabled, + NULL); + + pipe_mutex_unlock(tr_ctx->list_mutex); + pipe_mutex_unlock(tr_scr->list_mutex); + + return 0; +} + +static int +trace_rbug_shader_disable(struct trace_rbug *tr_rbug, struct rbug_header *header) +{ + struct rbug_proto_shader_disable *dis = (struct rbug_proto_shader_disable *)header; + + struct trace_screen *tr_scr = tr_rbug->tr_scr; + struct trace_context *tr_ctx = NULL; + struct trace_shader *tr_shdr = NULL; + + pipe_mutex_lock(tr_scr->list_mutex); + tr_ctx = trace_rbug_get_context_locked(tr_scr, dis->context); + + if (!tr_ctx) { + pipe_mutex_unlock(tr_scr->list_mutex); + return -ESRCH; + } + + pipe_mutex_lock(tr_ctx->list_mutex); + + tr_shdr = trace_rbug_get_shader_locked(tr_ctx, dis->shader); + + if (!tr_shdr) { + pipe_mutex_unlock(tr_ctx->list_mutex); + pipe_mutex_unlock(tr_scr->list_mutex); + return -ESRCH; + } + + tr_shdr->disabled = dis->disable; + + pipe_mutex_unlock(tr_ctx->list_mutex); + pipe_mutex_unlock(tr_scr->list_mutex); + + return 0; +} + +static int +trace_rbug_shader_replace(struct trace_rbug *tr_rbug, struct rbug_header *header) +{ + struct rbug_proto_shader_replace *rep = (struct rbug_proto_shader_replace *)header; + + struct trace_screen *tr_scr = tr_rbug->tr_scr; + struct trace_context *tr_ctx = NULL; + struct trace_shader *tr_shdr = NULL; + struct pipe_context *pipe = NULL; + void *state; + + pipe_mutex_lock(tr_scr->list_mutex); + tr_ctx = trace_rbug_get_context_locked(tr_scr, rep->context); + + if (!tr_ctx) { + pipe_mutex_unlock(tr_scr->list_mutex); + return -ESRCH; + } + + pipe_mutex_lock(tr_ctx->list_mutex); + + tr_shdr = trace_rbug_get_shader_locked(tr_ctx, rep->shader); + + if (!tr_shdr) { + pipe_mutex_unlock(tr_ctx->list_mutex); + pipe_mutex_unlock(tr_scr->list_mutex); + return -ESRCH; + } + + /* protect the pipe context */ + trace_dump_call_lock(); + + pipe = tr_ctx->pipe; + + /* remove old replaced shader */ + if (tr_shdr->replaced) { + if (tr_ctx->curr.fs == tr_shdr || tr_ctx->curr.vs == tr_shdr) + trace_shader_bind_locked(pipe, tr_shdr, tr_shdr->state); + + FREE(tr_shdr->replaced_tokens); + trace_shader_delete_locked(pipe, tr_shdr, tr_shdr->replaced); + tr_shdr->replaced = NULL; + tr_shdr->replaced_tokens = NULL; + } + + /* empty inputs means restore old which we did above */ + if (rep->tokens_len == 0) + goto out; + + tr_shdr->replaced_tokens = tgsi_dup_tokens((struct tgsi_token *)rep->tokens); + if (!tr_shdr->replaced_tokens) + goto err; + + state = trace_shader_create_locked(pipe, tr_shdr, tr_shdr->replaced_tokens); + if (!state) + goto err; + + /* bind new shader if the shader is currently a bound */ + if (tr_ctx->curr.fs == tr_shdr || tr_ctx->curr.vs == tr_shdr) + trace_shader_bind_locked(pipe, tr_shdr, state); + + /* save state */ + tr_shdr->replaced = state; + +out: + trace_dump_call_unlock(); + pipe_mutex_unlock(tr_ctx->list_mutex); + pipe_mutex_unlock(tr_scr->list_mutex); + + return 0; + +err: + FREE(tr_shdr->replaced_tokens); + tr_shdr->replaced = NULL; + tr_shdr->replaced_tokens = NULL; + + trace_dump_call_unlock(); + pipe_mutex_unlock(tr_ctx->list_mutex); + pipe_mutex_unlock(tr_scr->list_mutex); + return -EINVAL; +} + +static boolean +trace_rbug_header(struct trace_rbug *tr_rbug, struct rbug_header *header, uint32_t serial) +{ + int ret = 0; + + switch(header->opcode) { + case RBUG_OP_PING: + rbug_send_ping_reply(tr_rbug->con, serial, NULL); + break; + case RBUG_OP_TEXTURE_LIST: + ret = trace_rbug_texture_list(tr_rbug, header, serial); + break; + case RBUG_OP_TEXTURE_INFO: + ret = trace_rbug_texture_info(tr_rbug, header, serial); + break; + case RBUG_OP_TEXTURE_READ: + ret = trace_rbug_texture_read(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_LIST: + ret = trace_rbug_context_list(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_INFO: + ret = trace_rbug_context_info(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_DRAW_BLOCK: + ret = trace_rbug_context_draw_block(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_DRAW_STEP: + ret = trace_rbug_context_draw_step(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_DRAW_UNBLOCK: + ret = trace_rbug_context_draw_unblock(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_DRAW_RULE: + ret = trace_rbug_context_draw_rule(tr_rbug, header, serial); + break; + case RBUG_OP_CONTEXT_FLUSH: + ret = trace_rbug_context_flush(tr_rbug, header, serial); + break; + case RBUG_OP_SHADER_LIST: + ret = trace_rbug_shader_list(tr_rbug, header, serial); + break; + case RBUG_OP_SHADER_INFO: + ret = trace_rbug_shader_info(tr_rbug, header, serial); + break; + case RBUG_OP_SHADER_DISABLE: + ret = trace_rbug_shader_disable(tr_rbug, header); + break; + case RBUG_OP_SHADER_REPLACE: + ret = trace_rbug_shader_replace(tr_rbug, header); + break; + default: + debug_printf("%s - unsupported opcode %u\n", __FUNCTION__, header->opcode); + ret = -ENOSYS; + break; + } + rbug_free_header(header); + + if (ret) + rbug_send_error_reply(tr_rbug->con, serial, ret, NULL); + + return TRUE; +} + +static void +trace_rbug_con(struct trace_rbug *tr_rbug) +{ + struct rbug_header *header; + uint32_t serial; + + debug_printf("%s - connection received\n", __FUNCTION__); + + while(tr_rbug->running) { + header = rbug_get_message(tr_rbug->con, &serial); + if (!header) + break; + + if (!trace_rbug_header(tr_rbug, header, serial)) + break; + } + + debug_printf("%s - connection closed\n", __FUNCTION__); + + rbug_disconnect(tr_rbug->con); + tr_rbug->con = NULL; +} + +PIPE_THREAD_ROUTINE(trace_rbug_thread, void_tr_rbug) +{ + struct trace_rbug *tr_rbug = void_tr_rbug; + uint16_t port = 13370; + int s = -1; + int c; + + u_socket_init(); + + for (;port <= 13379 && s < 0; port++) + s = u_socket_listen_on_port(port); + + if (s < 0) { + debug_printf("trace_rbug - failed to listen\n"); + return NULL; + } + + u_socket_block(s, false); + + debug_printf("trace_rbug - remote debugging listening on port %u\n", --port); + + while(tr_rbug->running) { + sleep(1); + + c = u_socket_accept(s); + if (c < 0) + continue; + + u_socket_block(c, true); + tr_rbug->con = rbug_from_socket(c); + + trace_rbug_con(tr_rbug); + + u_socket_close(c); + } + + u_socket_close(s); + + u_socket_stop(); + + return NULL; +} + +/********************************************************** + * + */ + +struct trace_rbug * +trace_rbug_start(struct trace_screen *tr_scr) +{ + struct trace_rbug *tr_rbug = CALLOC_STRUCT(trace_rbug); + if (!tr_rbug) + return NULL; + + tr_rbug->tr_scr = tr_scr; + tr_rbug->running = TRUE; + tr_rbug->thread = pipe_thread_create(trace_rbug_thread, tr_rbug); + + return tr_rbug; +} + +void +trace_rbug_stop(struct trace_rbug *tr_rbug) +{ + if (!tr_rbug) + return; + + tr_rbug->running = false; + pipe_thread_wait(tr_rbug->thread); + + FREE(tr_rbug); + + return; +} + +void +trace_rbug_notify_draw_blocked(struct trace_context *tr_ctx) +{ + struct trace_screen *tr_scr = trace_screen(tr_ctx->base.screen); + struct trace_rbug *tr_rbug = tr_scr->rbug; + + if (tr_rbug && tr_rbug->con) + rbug_send_context_draw_blocked(tr_rbug->con, + VOID2U64(tr_ctx), tr_ctx->draw_blocked, NULL); +} diff --git a/src/gallium/drivers/trace/tr_screen.c b/src/gallium/drivers/trace/tr_screen.c index 12a85353428..5b1e26a52d7 100644 --- a/src/gallium/drivers/trace/tr_screen.c +++ b/src/gallium/drivers/trace/tr_screen.c @@ -30,13 +30,16 @@ #include "tr_buffer.h" #include "tr_dump.h" -#include "tr_state.h" +#include "tr_dump_state.h" #include "tr_texture.h" #include "tr_screen.h" #include "pipe/p_inlines.h" +static boolean trace = FALSE; +static boolean rbug = FALSE; + static const char * trace_screen_get_name(struct pipe_screen *_screen) { @@ -212,10 +215,12 @@ static struct pipe_texture * trace_screen_texture_blanket(struct pipe_screen *_screen, const struct pipe_texture *templat, const unsigned *ppitch, - struct pipe_buffer *buffer) + struct pipe_buffer *_buffer) { struct trace_screen *tr_scr = trace_screen(_screen); + struct trace_buffer *tr_buf = trace_buffer(_buffer); struct pipe_screen *screen = tr_scr->screen; + struct pipe_buffer *buffer = tr_buf->buffer; unsigned pitch = *ppitch; struct pipe_texture *result; @@ -818,18 +823,41 @@ trace_screen_destroy(struct pipe_screen *_screen) struct pipe_screen *screen = tr_scr->screen; trace_dump_call_begin("pipe_screen", "destroy"); - trace_dump_arg(ptr, screen); - - screen->destroy(screen); - trace_dump_call_end(); - trace_dump_trace_end(); + if (tr_scr->rbug) + trace_rbug_stop(tr_scr->rbug); + + screen->destroy(screen); + FREE(tr_scr); } +boolean +trace_enabled(void) +{ + static boolean firstrun = TRUE; + + if (!firstrun) + return trace; + firstrun = FALSE; + + trace_dump_init(); + + if(trace_dump_trace_begin()) { + trace_dumping_start(); + trace = TRUE; + } + + if (debug_get_bool_option("GALLIUM_RBUG", FALSE)) { + trace = TRUE; + rbug = TRUE; + } + + return trace; +} struct pipe_screen * trace_screen_create(struct pipe_screen *screen) @@ -840,13 +868,9 @@ trace_screen_create(struct pipe_screen *screen) if(!screen) goto error1; - trace_dump_init(); - - if(!trace_dump_trace_begin()) + if (!trace_enabled()) goto error1; - trace_dumping_start(); - trace_dump_call_begin("", "pipe_screen_create"); tr_scr = CALLOC_STRUCT(trace_screen); @@ -904,6 +928,9 @@ trace_screen_create(struct pipe_screen *screen) trace_dump_ret(ptr, screen); trace_dump_call_end(); + if (rbug) + tr_scr->rbug = trace_rbug_start(tr_scr); + return &tr_scr->base; #if 0 diff --git a/src/gallium/drivers/trace/tr_screen.h b/src/gallium/drivers/trace/tr_screen.h index 59f254166d4..dba8cd7c653 100644 --- a/src/gallium/drivers/trace/tr_screen.h +++ b/src/gallium/drivers/trace/tr_screen.h @@ -57,6 +57,9 @@ struct trace_screen struct pipe_screen *screen; + /* remote debugger */ + struct trace_rbug *rbug; + pipe_mutex list_mutex; int num_buffers; int num_contexts; @@ -71,14 +74,34 @@ struct trace_screen }; +/* + * tr_rbug.c + */ + + +struct trace_rbug; + +struct trace_rbug * +trace_rbug_start(struct trace_screen *tr_scr); + +void +trace_rbug_stop(struct trace_rbug *tr_rbug); + + +/* + * tr_screen.c + */ + + +boolean +trace_enabled(void); + struct trace_screen * trace_screen(struct pipe_screen *screen); - struct pipe_screen * trace_screen_create(struct pipe_screen *screen); - void trace_screen_user_buffer_update(struct pipe_screen *screen, struct pipe_buffer *buffer); @@ -99,6 +122,7 @@ trace_screen_user_buffer_update(struct pipe_screen *screen, pipe_mutex_unlock(tr_scr->list_mutex); \ } while (0) + #ifdef __cplusplus } #endif diff --git a/src/gallium/drivers/trace/tr_state.c b/src/gallium/drivers/trace/tr_state.c index a9570c1aebd..d8c11640bf3 100644 --- a/src/gallium/drivers/trace/tr_state.c +++ b/src/gallium/drivers/trace/tr_state.c @@ -1,491 +1,66 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. +/* + * 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. + * 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 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. + * 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 "pipe/p_compiler.h" -#include "util/u_memory.h" -#include "tgsi/tgsi_dump.h" - -#include "tr_dump.h" #include "tr_state.h" +#include "util/u_memory.h" +#include "util/u_simple_list.h" -void trace_dump_format(enum pipe_format format) -{ - trace_dump_enum(pf_name(format) ); -} - - -void trace_dump_block(const struct pipe_format_block *block) -{ - trace_dump_struct_begin("pipe_format_block"); - trace_dump_member(uint, block, size); - trace_dump_member(uint, block, width); - trace_dump_member(uint, block, height); - trace_dump_struct_end(); -} - - -static void trace_dump_reference(const struct pipe_reference *reference) -{ - trace_dump_struct_begin("pipe_reference"); - trace_dump_member(int, &reference->count, count); - trace_dump_struct_end(); -} - - -void trace_dump_template(const struct pipe_texture *templat) -{ - if(!templat) { - trace_dump_null(); - return; - } - - trace_dump_struct_begin("pipe_texture"); - - trace_dump_member(int, templat, target); - trace_dump_member(format, templat, format); - - trace_dump_member_begin("width"); - trace_dump_array(uint, templat->width, 1); - trace_dump_member_end(); - - trace_dump_member_begin("height"); - trace_dump_array(uint, templat->height, 1); - trace_dump_member_end(); - - trace_dump_member_begin("depth"); - trace_dump_array(uint, templat->depth, 1); - trace_dump_member_end(); - - trace_dump_member_begin("block"); - trace_dump_block(&templat->block); - trace_dump_member_end(); - - trace_dump_member(uint, templat, last_level); - trace_dump_member(uint, templat, tex_usage); - - trace_dump_struct_end(); -} - - -void trace_dump_rasterizer_state(const struct pipe_rasterizer_state *state) -{ - if(!state) { - trace_dump_null(); - return; - } - - trace_dump_struct_begin("pipe_rasterizer_state"); - - trace_dump_member(bool, state, flatshade); - trace_dump_member(bool, state, light_twoside); - trace_dump_member(uint, state, front_winding); - trace_dump_member(uint, state, cull_mode); - trace_dump_member(uint, state, fill_cw); - trace_dump_member(uint, state, fill_ccw); - trace_dump_member(bool, state, offset_cw); - trace_dump_member(bool, state, offset_ccw); - trace_dump_member(bool, state, scissor); - trace_dump_member(bool, state, poly_smooth); - trace_dump_member(bool, state, poly_stipple_enable); - trace_dump_member(bool, state, point_smooth); - trace_dump_member(bool, state, point_sprite); - trace_dump_member(bool, state, point_size_per_vertex); - trace_dump_member(bool, state, multisample); - trace_dump_member(bool, state, line_smooth); - trace_dump_member(bool, state, line_stipple_enable); - trace_dump_member(uint, state, line_stipple_factor); - trace_dump_member(uint, state, line_stipple_pattern); - trace_dump_member(bool, state, line_last_pixel); - trace_dump_member(bool, state, bypass_vs_clip_and_viewport); - trace_dump_member(bool, state, flatshade_first); - trace_dump_member(bool, state, gl_rasterization_rules); - - trace_dump_member(float, state, line_width); - trace_dump_member(float, state, point_size); - trace_dump_member(float, state, point_size_min); - trace_dump_member(float, state, point_size_max); - trace_dump_member(float, state, offset_units); - trace_dump_member(float, state, offset_scale); - - trace_dump_member_array(uint, state, sprite_coord_mode); - - trace_dump_struct_end(); -} - - -void trace_dump_poly_stipple(const struct pipe_poly_stipple *state) -{ - if(!state) { - trace_dump_null(); - return; - } - - trace_dump_struct_begin("pipe_poly_stipple"); - - trace_dump_member_begin("stipple"); - trace_dump_array(uint, - state->stipple, - Elements(state->stipple)); - trace_dump_member_end(); - - trace_dump_struct_end(); -} - - -void trace_dump_viewport_state(const struct pipe_viewport_state *state) -{ - if(!state) { - trace_dump_null(); - return; - } - - trace_dump_struct_begin("pipe_viewport_state"); - - trace_dump_member_array(float, state, scale); - trace_dump_member_array(float, state, translate); - - trace_dump_struct_end(); -} - - -void trace_dump_scissor_state(const struct pipe_scissor_state *state) -{ - if(!state) { - trace_dump_null(); - return; - } - - trace_dump_struct_begin("pipe_scissor_state"); - - trace_dump_member(uint, state, minx); - trace_dump_member(uint, state, miny); - trace_dump_member(uint, state, maxx); - trace_dump_member(uint, state, maxy); - - trace_dump_struct_end(); -} - - -void trace_dump_clip_state(const struct pipe_clip_state *state) -{ - unsigned i; - - if(!state) { - trace_dump_null(); - return; - } - - trace_dump_struct_begin("pipe_clip_state"); - - trace_dump_member_begin("ucp"); - trace_dump_array_begin(); - for(i = 0; i < PIPE_MAX_CLIP_PLANES; ++i) { - trace_dump_elem_begin(); - trace_dump_array(float, state->ucp[i], 4); - trace_dump_elem_end(); - } - trace_dump_array_end(); - trace_dump_member_end(); - - trace_dump_member(uint, state, nr); - - trace_dump_struct_end(); -} - - -void trace_dump_constant_buffer(const struct pipe_constant_buffer *state) -{ - if(!state) { - trace_dump_null(); - return; - } - - trace_dump_struct_begin("pipe_constant_buffer"); - - trace_dump_member(buffer_ptr, state, buffer); - - trace_dump_struct_end(); -} - - -void trace_dump_shader_state(const struct pipe_shader_state *state) -{ - static char str[8192]; - - if(!state) { - trace_dump_null(); - return; - } - - tgsi_dump_str(state->tokens, 0, str, sizeof(str)); - - trace_dump_struct_begin("pipe_shader_state"); - - trace_dump_member_begin("tokens"); - trace_dump_string(str); - trace_dump_member_end(); - - trace_dump_struct_end(); -} - - -void trace_dump_depth_stencil_alpha_state(const struct pipe_depth_stencil_alpha_state *state) -{ - unsigned i; - - if(!state) { - trace_dump_null(); - return; - } - - trace_dump_struct_begin("pipe_depth_stencil_alpha_state"); - - trace_dump_member_begin("depth"); - trace_dump_struct_begin("pipe_depth_state"); - trace_dump_member(bool, &state->depth, enabled); - trace_dump_member(bool, &state->depth, writemask); - trace_dump_member(uint, &state->depth, func); - trace_dump_member(bool, &state->depth, occlusion_count); - trace_dump_struct_end(); - trace_dump_member_end(); - - trace_dump_member_begin("stencil"); - trace_dump_array_begin(); - for(i = 0; i < Elements(state->stencil); ++i) { - trace_dump_elem_begin(); - trace_dump_struct_begin("pipe_stencil_state"); - trace_dump_member(bool, &state->stencil[i], enabled); - trace_dump_member(uint, &state->stencil[i], func); - trace_dump_member(uint, &state->stencil[i], fail_op); - trace_dump_member(uint, &state->stencil[i], zpass_op); - trace_dump_member(uint, &state->stencil[i], zfail_op); - trace_dump_member(uint, &state->stencil[i], ref_value); - trace_dump_member(uint, &state->stencil[i], valuemask); - trace_dump_member(uint, &state->stencil[i], writemask); - trace_dump_struct_end(); - trace_dump_elem_end(); - } - trace_dump_array_end(); - trace_dump_member_end(); - - trace_dump_member_begin("alpha"); - trace_dump_struct_begin("pipe_alpha_state"); - trace_dump_member(bool, &state->alpha, enabled); - trace_dump_member(uint, &state->alpha, func); - trace_dump_member(float, &state->alpha, ref_value); - trace_dump_struct_end(); - trace_dump_member_end(); - - trace_dump_struct_end(); -} - - -void trace_dump_blend_state(const struct pipe_blend_state *state) -{ - if(!state) { - trace_dump_null(); - return; - } - - trace_dump_struct_begin("pipe_blend_state"); - - trace_dump_member(bool, state, blend_enable); - - trace_dump_member(uint, state, rgb_func); - trace_dump_member(uint, state, rgb_src_factor); - trace_dump_member(uint, state, rgb_dst_factor); - - trace_dump_member(uint, state, alpha_func); - trace_dump_member(uint, state, alpha_src_factor); - trace_dump_member(uint, state, alpha_dst_factor); - - trace_dump_member(bool, state, logicop_enable); - trace_dump_member(uint, state, logicop_func); - - trace_dump_member(uint, state, colormask); - trace_dump_member(bool, state, dither); - - trace_dump_struct_end(); -} - - -void trace_dump_blend_color(const struct pipe_blend_color *state) -{ - if(!state) { - trace_dump_null(); - return; - } - - trace_dump_struct_begin("pipe_blend_color"); - - trace_dump_member_array(float, state, color); - - trace_dump_struct_end(); -} - - -void trace_dump_framebuffer_state(const struct pipe_framebuffer_state *state) -{ - trace_dump_struct_begin("pipe_framebuffer_state"); - - trace_dump_member(uint, state, width); - trace_dump_member(uint, state, height); - trace_dump_member(uint, state, nr_cbufs); - trace_dump_member_array(ptr, state, cbufs); - trace_dump_member(ptr, state, zsbuf); - - trace_dump_struct_end(); -} - - -void trace_dump_sampler_state(const struct pipe_sampler_state *state) -{ - if(!state) { - trace_dump_null(); - return; - } - - trace_dump_struct_begin("pipe_sampler_state"); - - trace_dump_member(uint, state, wrap_s); - trace_dump_member(uint, state, wrap_t); - trace_dump_member(uint, state, wrap_r); - trace_dump_member(uint, state, min_img_filter); - trace_dump_member(uint, state, min_mip_filter); - trace_dump_member(uint, state, mag_img_filter); - trace_dump_member(bool, state, compare_mode); - trace_dump_member(uint, state, compare_func); - trace_dump_member(bool, state, normalized_coords); - trace_dump_member(uint, state, prefilter); - trace_dump_member(float, state, shadow_ambient); - trace_dump_member(float, state, lod_bias); - trace_dump_member(float, state, min_lod); - trace_dump_member(float, state, max_lod); - trace_dump_member_array(float, state, border_color); - trace_dump_member(float, state, max_anisotropy); - - trace_dump_struct_end(); -} - - -void trace_dump_surface(const struct pipe_surface *state) -{ - if(!state) { - trace_dump_null(); - return; - } - - trace_dump_struct_begin("pipe_surface"); - - trace_dump_reference(&state->reference); - - trace_dump_member(format, state, format); - trace_dump_member(uint, state, width); - trace_dump_member(uint, state, height); - - trace_dump_member(uint, state, layout); - trace_dump_member(uint, state, offset); - trace_dump_member(uint, state, usage); - - trace_dump_member(ptr, state, texture); - trace_dump_member(uint, state, face); - trace_dump_member(uint, state, level); - trace_dump_member(uint, state, zslice); - - trace_dump_struct_end(); -} - +#include "tgsi/tgsi_parse.h" -void trace_dump_transfer(const struct pipe_transfer *state) +struct trace_shader * trace_shader_create(struct trace_context *tr_ctx, + const struct pipe_shader_state *state, + void *result, + enum trace_shader_type type) { - if(!state) { - trace_dump_null(); - return; - } + struct trace_shader *tr_shdr = CALLOC_STRUCT(trace_shader); - trace_dump_struct_begin("pipe_transfer"); + tr_shdr->state = result; + tr_shdr->type = type; + tr_shdr->tokens = tgsi_dup_tokens(state->tokens); - trace_dump_member(format, state, format); - trace_dump_member(uint, state, width); - trace_dump_member(uint, state, height); + /* works on context as well */ + trace_screen_add_to_list(tr_ctx, shaders, tr_shdr); - trace_dump_member_begin("block"); - trace_dump_block(&state->block); - trace_dump_member_end(); - - trace_dump_member(uint, state, nblocksx); - trace_dump_member(uint, state, nblocksy); - trace_dump_member(uint, state, stride); - trace_dump_member(uint, state, usage); - - trace_dump_member(ptr, state, texture); - trace_dump_member(uint, state, face); - trace_dump_member(uint, state, level); - trace_dump_member(uint, state, zslice); - - trace_dump_struct_end(); + return tr_shdr; } - -void trace_dump_vertex_buffer(const struct pipe_vertex_buffer *state) +void trace_shader_destroy(struct trace_context *tr_ctx, + struct trace_shader *tr_shdr) { - if(!state) { - trace_dump_null(); - return; - } + trace_screen_remove_from_list(tr_ctx, shaders, tr_shdr); - trace_dump_struct_begin("pipe_vertex_buffer"); - - trace_dump_member(uint, state, stride); - trace_dump_member(uint, state, max_index); - trace_dump_member(uint, state, buffer_offset); - trace_dump_member(buffer_ptr, state, buffer); - - trace_dump_struct_end(); -} - - -void trace_dump_vertex_element(const struct pipe_vertex_element *state) -{ - if(!state) { - trace_dump_null(); - return; + if (tr_shdr->replaced) { + if (tr_shdr->type == TRACE_SHADER_FRAGMENT) + tr_ctx->pipe->delete_fs_state(tr_ctx->pipe, tr_shdr->replaced); + else if (tr_shdr->type == TRACE_SHADER_VERTEX) + tr_ctx->pipe->delete_vs_state(tr_ctx->pipe, tr_shdr->replaced); + else + assert(0); } - trace_dump_struct_begin("pipe_vertex_element"); - - trace_dump_member(uint, state, src_offset); - - trace_dump_member(uint, state, vertex_buffer_index); - trace_dump_member(uint, state, nr_components); - - trace_dump_member(format, state, src_format); - - trace_dump_struct_end(); + FREE(tr_shdr->replaced_tokens); + FREE(tr_shdr->tokens); + FREE(tr_shdr); } diff --git a/src/gallium/drivers/trace/tr_state.h b/src/gallium/drivers/trace/tr_state.h index 513ed0ac98d..1c16042ee5a 100644 --- a/src/gallium/drivers/trace/tr_state.h +++ b/src/gallium/drivers/trace/tr_state.h @@ -1,78 +1,68 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. +/* + * 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. + * 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 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. + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. * - **************************************************************************/ - -#ifndef TR_STATE_H -#define TR_STATE_H - -#include "pipe/p_format.h" -#include "pipe/p_state.h" -#include "pipe/p_shader_tokens.h" - - -void trace_dump_format(enum pipe_format format); - -void trace_dump_block(const struct pipe_format_block *block); - -void trace_dump_template(const struct pipe_texture *templat); - - -void trace_dump_rasterizer_state(const struct pipe_rasterizer_state *state); - -void trace_dump_poly_stipple(const struct pipe_poly_stipple *state); - -void trace_dump_viewport_state(const struct pipe_viewport_state *state); - -void trace_dump_scissor_state(const struct pipe_scissor_state *state); - -void trace_dump_clip_state(const struct pipe_clip_state *state); + * 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. + */ -void trace_dump_constant_buffer(const struct pipe_constant_buffer *state); +#ifndef TR_STATE_H_ +#define TR_STATE_H_ -void trace_dump_token(const struct tgsi_token *token); +#include "tr_context.h" -void trace_dump_shader_state(const struct pipe_shader_state *state); +struct tgsi_token; -void trace_dump_depth_stencil_alpha_state(const struct pipe_depth_stencil_alpha_state *state); +enum trace_shader_type { + TRACE_SHADER_FRAGMENT = 0, + TRACE_SHADER_VERTEX = 1, + TRACE_SHADER_GEOMETRY = 2, +}; -void trace_dump_blend_state(const struct pipe_blend_state *state); +struct trace_shader +{ + struct tr_list list; -void trace_dump_blend_color(const struct pipe_blend_color *state); + enum trace_shader_type type; -void trace_dump_framebuffer_state(const struct pipe_framebuffer_state *state); + void *state; + void *replaced; -void trace_dump_sampler_state(const struct pipe_sampler_state *state); + struct tgsi_token *tokens; + struct tgsi_token *replaced_tokens; -void trace_dump_surface(const struct pipe_surface *state); + boolean disabled; +}; -void trace_dump_transfer(const struct pipe_transfer *state); -void trace_dump_vertex_buffer(const struct pipe_vertex_buffer *state); +static INLINE struct trace_shader * +trace_shader(void *state) +{ + return (struct trace_shader *)state; +} -void trace_dump_vertex_element(const struct pipe_vertex_element *state); +struct trace_shader * trace_shader_create(struct trace_context *tr_ctx, + const struct pipe_shader_state *state, + void *result, + enum trace_shader_type type); +void trace_shader_destroy(struct trace_context *tr_ctx, + struct trace_shader *tr_shdr); -#endif /* TR_STATE_H */ +#endif diff --git a/src/gallium/include/pipe/p_config.h b/src/gallium/include/pipe/p_config.h index 63238ea46e9..4152d6ac36a 100644 --- a/src/gallium/include/pipe/p_config.h +++ b/src/gallium/include/pipe/p_config.h @@ -102,6 +102,19 @@ /* + * Endian detection. + */ + +#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64) +#define PIPE_ARCH_LITTLE_ENDIAN +#elif defined(PIPE_ARCH_PPC) || defined(PIPE_ARCH_PPC_64) +#define PIPE_ARCH_BIG_ENDIAN +#else +#define PIPE_ARCH_UNKNOWN_ENDIAN +#endif + + +/* * Operating system family. * * See subsystem below for a more fine-grained distinction. @@ -119,6 +132,10 @@ #define PIPE_OS_SOLARIS #endif +#if defined(__APPLE__) +#define PIPE_OS_APPLE +#endif + #if defined(_WIN32) || defined(WIN32) #define PIPE_OS_WINDOWS #endif diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index 5c16884c16f..bc4bc707591 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -132,6 +132,7 @@ enum pipe_texture_target { #define PIPE_TEX_FACE_NEG_Y 3 #define PIPE_TEX_FACE_POS_Z 4 #define PIPE_TEX_FACE_NEG_Z 5 +#define PIPE_TEX_FACE_MAX 6 #define PIPE_TEX_WRAP_REPEAT 0 #define PIPE_TEX_WRAP_CLAMP 1 @@ -158,14 +159,6 @@ enum pipe_texture_target { #define PIPE_TEX_COMPARE_NONE 0 #define PIPE_TEX_COMPARE_R_TO_TEXTURE 1 -#define PIPE_TEX_FACE_POS_X 0 -#define PIPE_TEX_FACE_NEG_X 1 -#define PIPE_TEX_FACE_POS_Y 2 -#define PIPE_TEX_FACE_NEG_Y 3 -#define PIPE_TEX_FACE_POS_Z 4 -#define PIPE_TEX_FACE_NEG_Z 5 -#define PIPE_TEX_FACE_MAX 6 - #define PIPE_TEXTURE_USAGE_RENDER_TARGET 0x1 #define PIPE_TEXTURE_USAGE_DISPLAY_TARGET 0x2 /* ie a backbuffer */ #define PIPE_TEXTURE_USAGE_PRIMARY 0x4 /* ie a frontbuffer */ @@ -281,9 +274,8 @@ enum pipe_transfer_usage { /** - * Implementation capabilities/limits - * Passed to pipe->get_param() - * XXX this will need some fine tuning... + * Implementation capabilities/limits which are queried through + * pipe_screen::get_param() and pipe_screen::get_paramf(). */ #define PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS 1 #define PIPE_CAP_NPOT_TEXTURES 2 @@ -312,6 +304,7 @@ enum pipe_transfer_usage { #define PIPE_CAP_TEXTURE_MIRROR_REPEAT 25 #define PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS 26 #define PIPE_CAP_TGSI_CONT_SUPPORTED 27 +#define PIPE_CAP_BLEND_EQUATION_SEPARATE 28 /** diff --git a/src/gallium/include/pipe/p_shader_tokens.h b/src/gallium/include/pipe/p_shader_tokens.h index b00cfe3423c..c4be604e5a0 100644 --- a/src/gallium/include/pipe/p_shader_tokens.h +++ b/src/gallium/include/pipe/p_shader_tokens.h @@ -78,6 +78,7 @@ enum tgsi_file_type { TGSI_FILE_SAMPLER =5, TGSI_FILE_ADDRESS =6, TGSI_FILE_IMMEDIATE =7, + TGSI_FILE_LOOP =8, TGSI_FILE_COUNT /**< how many TGSI_FILE_ types */ }; @@ -152,13 +153,16 @@ struct tgsi_immediate unsigned Extended : 1; /**< BOOL */ }; -struct tgsi_immediate_float32 +union tgsi_immediate_data { float Float; }; -/* - * GL_NV_vertex_program +/* TGSI opcodes. + * + * For more information on semantics of opcodes and + * which APIs are known to use which opcodes, see + * auxiliary/tgsi/tgsi-instruction-set.txt */ #define TGSI_OPCODE_ARL 0 #define TGSI_OPCODE_MOV 1 @@ -177,62 +181,32 @@ struct tgsi_immediate_float32 #define TGSI_OPCODE_SLT 14 #define TGSI_OPCODE_SGE 15 #define TGSI_OPCODE_MAD 16 - -/* - * GL_ATI_fragment_shader - */ #define TGSI_OPCODE_SUB 17 -#define TGSI_OPCODE_DOT3 TGSI_OPCODE_DP3 -#define TGSI_OPCODE_DOT4 TGSI_OPCODE_DP4 -#define TGSI_OPCODE_LERP 18 +#define TGSI_OPCODE_LRP 18 #define TGSI_OPCODE_CND 19 #define TGSI_OPCODE_CND0 20 -#define TGSI_OPCODE_DOT2ADD 21 - -/* - * GL_EXT_vertex_shader - */ -#define TGSI_OPCODE_INDEX 22 /* considered for removal */ -#define TGSI_OPCODE_NEGATE 23 /* considered for removal */ -#define TGSI_OPCODE_MADD TGSI_OPCODE_MAD -#define TGSI_OPCODE_FRAC 24 -#define TGSI_OPCODE_SETGE TGSI_OPCODE_SGE -#define TGSI_OPCODE_SETLT TGSI_OPCODE_SLT +#define TGSI_OPCODE_DP2A 21 + /* gap */ +#define TGSI_OPCODE_FRC 24 #define TGSI_OPCODE_CLAMP 25 -#define TGSI_OPCODE_FLOOR 26 +#define TGSI_OPCODE_FLR 26 #define TGSI_OPCODE_ROUND 27 -#define TGSI_OPCODE_EXPBASE2 28 -#define TGSI_OPCODE_LOGBASE2 29 -#define TGSI_OPCODE_POWER 30 -#define TGSI_OPCODE_RECIP TGSI_OPCODE_RCP -#define TGSI_OPCODE_RECIPSQRT TGSI_OPCODE_RSQ -#define TGSI_OPCODE_CROSSPRODUCT 31 -#define TGSI_OPCODE_MULTIPLYMATRIX 32 /* considered for removal */ - -/* - * GL_NV_vertex_program1_1 - */ +#define TGSI_OPCODE_EX2 28 +#define TGSI_OPCODE_LG2 29 +#define TGSI_OPCODE_POW 30 +#define TGSI_OPCODE_XPD 31 + /* gap */ #define TGSI_OPCODE_ABS 33 #define TGSI_OPCODE_RCC 34 #define TGSI_OPCODE_DPH 35 - -/* - * GL_NV_fragment_program - */ #define TGSI_OPCODE_COS 36 #define TGSI_OPCODE_DDX 37 #define TGSI_OPCODE_DDY 38 -#define TGSI_OPCODE_EX2 TGSI_OPCODE_EXPBASE2 -#define TGSI_OPCODE_FLR TGSI_OPCODE_FLOOR -#define TGSI_OPCODE_FRC TGSI_OPCODE_FRAC #define TGSI_OPCODE_KILP 39 /* predicated kill */ -#define TGSI_OPCODE_LG2 TGSI_OPCODE_LOGBASE2 -#define TGSI_OPCODE_LRP TGSI_OPCODE_LERP #define TGSI_OPCODE_PK2H 40 #define TGSI_OPCODE_PK2US 41 #define TGSI_OPCODE_PK4B 42 #define TGSI_OPCODE_PK4UB 43 -#define TGSI_OPCODE_POW TGSI_OPCODE_POWER #define TGSI_OPCODE_RFL 44 #define TGSI_OPCODE_SEQ 45 #define TGSI_OPCODE_SFL 46 @@ -249,43 +223,18 @@ struct tgsi_immediate_float32 #define TGSI_OPCODE_UP4B 57 #define TGSI_OPCODE_UP4UB 58 #define TGSI_OPCODE_X2D 59 - -/* - * GL_NV_vertex_program2 - */ #define TGSI_OPCODE_ARA 60 #define TGSI_OPCODE_ARR 61 #define TGSI_OPCODE_BRA 62 #define TGSI_OPCODE_CAL 63 #define TGSI_OPCODE_RET 64 -#define TGSI_OPCODE_SSG 65 - -/* - * GL_ARB_vertex_program - */ -#define TGSI_OPCODE_SWZ 118 -#define TGSI_OPCODE_XPD TGSI_OPCODE_CROSSPRODUCT - -/* - * GL_ARB_fragment_program - */ +#define TGSI_OPCODE_SSG 65 /* SGN */ #define TGSI_OPCODE_CMP 66 -#define TGSI_OPCODE_KIL 116 /* conditional kill */ #define TGSI_OPCODE_SCS 67 #define TGSI_OPCODE_TXB 68 - -/* - * GL_NV_fragment_program_option - */ -/* No new opcode */ - -/* - * GL_NV_fragment_program2 - */ #define TGSI_OPCODE_NRM 69 #define TGSI_OPCODE_DIV 70 #define TGSI_OPCODE_DP2 71 -#define TGSI_OPCODE_DP2A TGSI_OPCODE_DOT2ADD #define TGSI_OPCODE_TXL 72 #define TGSI_OPCODE_BRK 73 #define TGSI_OPCODE_IF 74 @@ -295,20 +244,8 @@ struct tgsi_immediate_float32 #define TGSI_OPCODE_ENDIF 78 #define TGSI_OPCODE_ENDLOOP 79 #define TGSI_OPCODE_ENDREP 80 - -/* - * GL_NV_vertex_program2_option - */ - -/* - * GL_NV_vertex_program3 - */ #define TGSI_OPCODE_PUSHA 81 #define TGSI_OPCODE_POPA 82 - -/* - * GL_NV_gpu_program4 - */ #define TGSI_OPCODE_CEIL 83 #define TGSI_OPCODE_I2F 84 #define TGSI_OPCODE_NOT 85 @@ -323,103 +260,25 @@ struct tgsi_immediate_float32 #define TGSI_OPCODE_TXF 94 #define TGSI_OPCODE_TXQ 95 #define TGSI_OPCODE_CONT 96 - -/* - * GL_NV_vertex_program4 - */ -/* Same as GL_NV_gpu_program4 */ - -/* - * GL_NV_fragment_program4 - */ -/* Same as GL_NV_gpu_program4 */ - -/* - * GL_NV_geometry_program4 - */ -/* Same as GL_NV_gpu_program4 */ #define TGSI_OPCODE_EMIT 97 #define TGSI_OPCODE_ENDPRIM 98 - -/* - * GLSL - */ #define TGSI_OPCODE_BGNLOOP2 99 #define TGSI_OPCODE_BGNSUB 100 #define TGSI_OPCODE_ENDLOOP2 101 #define TGSI_OPCODE_ENDSUB 102 -#define TGSI_OPCODE_INT TGSI_OPCODE_TRUNC #define TGSI_OPCODE_NOISE1 103 #define TGSI_OPCODE_NOISE2 104 #define TGSI_OPCODE_NOISE3 105 #define TGSI_OPCODE_NOISE4 106 #define TGSI_OPCODE_NOP 107 - -/* - * ps_1_1 - */ -#define TGSI_OPCODE_TEXKILL TGSI_OPCODE_KIL - -/* - * ps_1_2 - */ -/* CMP - use TGSI_OPCODE_CND0 */ - -/* - * ps_1_3 - */ -/* CMP - use TGSI_OPCODE_CND0 */ - -/* - * ps_1_4 - */ -#define TGSI_OPCODE_TEXLD TGSI_OPCODE_TEX - -/* - * ps_2_0 - */ -#define TGSI_OPCODE_M4X4 TGSI_OPCODE_MULTIPLYMATRIX -#define TGSI_OPCODE_M4X3 108 -#define TGSI_OPCODE_M3X4 109 -#define TGSI_OPCODE_M3X3 110 -#define TGSI_OPCODE_M3X2 111 -#define TGSI_OPCODE_CRS TGSI_OPCODE_XPD + /* gap */ #define TGSI_OPCODE_NRM4 112 -#define TGSI_OPCODE_SINCOS TGSI_OPCODE_SCS -#define TGSI_OPCODE_TEXLDB TGSI_OPCODE_TXB -#define TGSI_OPCODE_DP2ADD TGSI_OPCODE_DP2A - -/* - * ps_2_x - */ -#define TGSI_OPCODE_CALL TGSI_OPCODE_CAL #define TGSI_OPCODE_CALLNZ 113 #define TGSI_OPCODE_IFC 114 -#define TGSI_OPCODE_BREAK TGSI_OPCODE_BRK #define TGSI_OPCODE_BREAKC 115 -#define TGSI_OPCODE_DSX TGSI_OPCODE_DDX -#define TGSI_OPCODE_DSY TGSI_OPCODE_DDY -#define TGSI_OPCODE_TEXLDD TGSI_OPCODE_TXD - -/* - * vs_1_1 - */ -#define TGSI_OPCODE_EXPP TGSI_OPCODE_EXP -#define TGSI_OPCODE_LOGP TGSI_OPCODE_LG2 - -/* - * vs_2_0 - */ -#define TGSI_OPCODE_SGN TGSI_OPCODE_SSG -#define TGSI_OPCODE_MOVA TGSI_OPCODE_ARR -/* EXPP - use TGSI_OPCODE_EX2 */ - -/* - * vs_2_x - */ - +#define TGSI_OPCODE_KIL 116 /* conditional kill */ #define TGSI_OPCODE_END 117 /* aka HALT */ - +#define TGSI_OPCODE_SWZ 118 #define TGSI_OPCODE_LAST 119 #define TGSI_SAT_NONE 0 /* do not saturate */ diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index 4b590bdc906..626bedb35a8 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -75,11 +75,11 @@ struct pipe_surface; */ struct pipe_buffer { - struct pipe_reference reference; - struct pipe_screen *screen; - unsigned alignment; - unsigned usage; - unsigned size; + struct pipe_reference reference; + unsigned size; + struct pipe_screen *screen; + unsigned alignment; + unsigned usage; }; @@ -265,7 +265,6 @@ struct pipe_sampler_state unsigned compare_func:3; /**< PIPE_FUNC_x */ unsigned normalized_coords:1; /**< Are coords normalized to [0,1]? */ unsigned prefilter:4; /**< Wierd sampling state exposed by some api's */ - float shadow_ambient; /**< shadow test fail color/intensity */ float lod_bias; /**< LOD/lambda bias */ float min_lod, max_lod; /**< LOD clamp range, after bias */ float border_color[4]; @@ -287,10 +286,10 @@ struct pipe_surface unsigned offset; /**< offset from start of buffer, in bytes */ unsigned usage; /**< PIPE_BUFFER_USAGE_* */ + unsigned zslice; struct pipe_texture *texture; /**< texture into which this is a view */ unsigned face; unsigned level; - unsigned zslice; }; diff --git a/src/gallium/include/pipe/p_thread.h b/src/gallium/include/pipe/p_thread.h index ce8d79549ad..96e8e087447 100644 --- a/src/gallium/include/pipe/p_thread.h +++ b/src/gallium/include/pipe/p_thread.h @@ -44,6 +44,8 @@ #include <pthread.h> /* POSIX threads headers */ #include <stdio.h> /* for perror() */ +#define PIPE_THREAD_HAVE_CONDVAR + typedef pthread_t pipe_thread; #define PIPE_THREAD_ROUTINE( name, param ) \ diff --git a/src/gallium/include/state_tracker/drm_api.h b/src/gallium/include/state_tracker/drm_api.h index 5790b2f6c7e..7a38b508fbe 100644 --- a/src/gallium/include/state_tracker/drm_api.h +++ b/src/gallium/include/state_tracker/drm_api.h @@ -32,33 +32,37 @@ struct drm_api * Special buffer functions */ /*@{*/ - struct pipe_screen* (*create_screen)(int drm_fd, - struct drm_create_screen_arg *arg); - struct pipe_context* (*create_context)(struct pipe_screen *screen); + struct pipe_screen* (*create_screen)(struct drm_api *api, int drm_fd, + struct drm_create_screen_arg *arg); + struct pipe_context* (*create_context)(struct drm_api *api, + struct pipe_screen *screen); /*@}*/ /** * Special buffer functions */ /*@{*/ - boolean (*buffer_from_texture)(struct pipe_texture *texture, - struct pipe_buffer **buffer, - unsigned *stride); - struct pipe_buffer* (*buffer_from_handle)(struct pipe_screen *screen, + boolean (*buffer_from_texture)(struct drm_api *api, + struct pipe_texture *texture, + struct pipe_buffer **buffer, + unsigned *stride); + struct pipe_buffer* (*buffer_from_handle)(struct drm_api *api, + struct pipe_screen *screen, const char *name, unsigned handle); - boolean (*handle_from_buffer)(struct pipe_screen *screen, - struct pipe_buffer *buffer, - unsigned *handle); - boolean (*global_handle_from_buffer)(struct pipe_screen *screen, - struct pipe_buffer *buffer, - unsigned *handle); + boolean (*handle_from_buffer)(struct drm_api *api, + struct pipe_screen *screen, + struct pipe_buffer *buffer, + unsigned *handle); + boolean (*global_handle_from_buffer)(struct drm_api *api, + struct pipe_screen *screen, + struct pipe_buffer *buffer, + unsigned *handle); /*@}*/ + + void (*destroy)(struct drm_api *api); }; -/** - * A driver needs to export this symbol - */ -extern struct drm_api drm_api_hooks; +extern struct drm_api * drm_api_create(void); #endif diff --git a/src/gallium/state_trackers/dri/dri_context.c b/src/gallium/state_trackers/dri/dri_context.c index 45eaec4ed39..6c617197eca 100644 --- a/src/gallium/state_trackers/dri/dri_context.c +++ b/src/gallium/state_trackers/dri/dri_context.c @@ -69,7 +69,7 @@ dri_create_context(const __GLcontextModes * visual, driParseConfigFiles(&ctx->optionCache, &screen->optionCache, sPriv->myNum, "dri"); - ctx->pipe = drm_api_hooks.create_context(screen->pipe_screen); + ctx->pipe = screen->api->create_context(screen->api, screen->pipe_screen); if (ctx->pipe == NULL) goto fail; diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c index 5846390d02c..1d91fbb89fb 100644 --- a/src/gallium/state_trackers/dri/dri_drawable.c +++ b/src/gallium/state_trackers/dri/dri_drawable.c @@ -53,7 +53,8 @@ dri_copy_to_front(__DRIdrawablePrivate * dPriv, } static struct pipe_surface * -dri_surface_from_handle(struct pipe_screen *screen, +dri_surface_from_handle(struct drm_api *api, + struct pipe_screen *screen, unsigned handle, enum pipe_format format, unsigned width, unsigned height, unsigned pitch) @@ -63,7 +64,7 @@ dri_surface_from_handle(struct pipe_screen *screen, struct pipe_texture templat; struct pipe_buffer *buf = NULL; - buf = drm_api_hooks.buffer_from_handle(screen, "dri2 buffer", handle); + buf = api->buffer_from_handle(api, screen, "dri2 buffer", handle); if (!buf) return NULL; @@ -100,12 +101,14 @@ dri_surface_from_handle(struct pipe_screen *screen, void dri_get_buffers(__DRIdrawablePrivate * dPriv) { + struct dri_drawable *drawable = dri_drawable(dPriv); struct pipe_surface *surface = NULL; struct pipe_screen *screen = dri_screen(drawable->sPriv)->pipe_screen; __DRIbuffer *buffers = NULL; __DRIscreen *dri_screen = drawable->sPriv; __DRIdrawable *dri_drawable = drawable->dPriv; + struct drm_api *api = ((struct dri_screen*)(dri_screen->private))->api; boolean have_depth = FALSE; int i, count; @@ -138,6 +141,18 @@ dri_get_buffers(__DRIdrawablePrivate * dPriv) dri_drawable->pBackClipRects[0].x2 = dri_drawable->w; dri_drawable->pBackClipRects[0].y2 = dri_drawable->h; + if (drawable->old_num == count && + drawable->old_w == dri_drawable->w && + drawable->old_h == dri_drawable->h && + memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * count) == 0) { + return; + } else { + drawable->old_num = count; + drawable->old_w = dri_drawable->w; + drawable->old_h = dri_drawable->h; + memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count); + } + for (i = 0; i < count; i++) { enum pipe_format format = 0; int index = 0; @@ -145,29 +160,28 @@ dri_get_buffers(__DRIdrawablePrivate * dPriv) switch (buffers[i].attachment) { case __DRI_BUFFER_FRONT_LEFT: index = ST_SURFACE_FRONT_LEFT; - format = PIPE_FORMAT_A8R8G8B8_UNORM; + format = drawable->color_format; break; case __DRI_BUFFER_FAKE_FRONT_LEFT: index = ST_SURFACE_FRONT_LEFT; - format = PIPE_FORMAT_A8R8G8B8_UNORM; + format = drawable->color_format; break; case __DRI_BUFFER_BACK_LEFT: index = ST_SURFACE_BACK_LEFT; - format = PIPE_FORMAT_A8R8G8B8_UNORM; + format = drawable->color_format; break; case __DRI_BUFFER_DEPTH: index = ST_SURFACE_DEPTH; - format = PIPE_FORMAT_Z24S8_UNORM; + format = drawable->depth_format; break; case __DRI_BUFFER_STENCIL: index = ST_SURFACE_DEPTH; - format = PIPE_FORMAT_Z24S8_UNORM; + format = drawable->stencil_format; break; case __DRI_BUFFER_ACCUM: default: assert(0); } - assert(buffers[i].cpp == 4); if (index == ST_SURFACE_DEPTH) { if (have_depth) @@ -176,7 +190,8 @@ dri_get_buffers(__DRIdrawablePrivate * dPriv) have_depth = TRUE; } - surface = dri_surface_from_handle(screen, + surface = dri_surface_from_handle(api, + screen, buffers[i].name, format, dri_drawable->w, @@ -206,10 +221,8 @@ dri_create_buffer(__DRIscreenPrivate * sPriv, __DRIdrawablePrivate * dPriv, const __GLcontextModes * visual, boolean isPixmap) { - enum pipe_format colorFormat, depthFormat, stencilFormat; struct dri_screen *screen = sPriv->private; struct dri_drawable *drawable = NULL; - struct pipe_screen *pscreen = screen->pipe_screen; int i; if (isPixmap) @@ -219,39 +232,52 @@ dri_create_buffer(__DRIscreenPrivate * sPriv, if (drawable == NULL) goto fail; - /* XXX: todo: use the pipe_screen queries to figure out which - * render targets are supportable. - */ - assert(visual->redBits == 8); - assert(visual->depthBits == 24 || visual->depthBits == 0); - assert(visual->stencilBits == 8 || visual->stencilBits == 0); - - colorFormat = PIPE_FORMAT_A8R8G8B8_UNORM; + drawable->color_format = (visual->redBits == 8) ? + PIPE_FORMAT_A8R8G8B8_UNORM : PIPE_FORMAT_R5G6B5_UNORM; + + debug_printf("Red bits is %d\n", visual->redBits); + + switch(visual->depthBits) { + default: + case 0: + debug_printf("Depth buffer 0.\n"); + drawable->depth_format = PIPE_FORMAT_NONE; + break; + case 16: + debug_printf("Depth buffer 16.\n"); + drawable->depth_format = PIPE_FORMAT_Z16_UNORM; + break; + case 24: + if (visual->stencilBits == 0) { + debug_printf("Depth buffer 24. Stencil 0.\n"); + drawable->depth_format = (screen->d_depth_bits_last) ? + PIPE_FORMAT_X8Z24_UNORM: + PIPE_FORMAT_Z24X8_UNORM; + } else { + debug_printf("Combined depth stencil 24 / 8.\n"); + drawable->depth_format = (screen->sd_depth_bits_last) ? + PIPE_FORMAT_S8Z24_UNORM: + PIPE_FORMAT_Z24S8_UNORM; + } + break; + } - if (visual->depthBits) { - if (pscreen->is_format_supported(pscreen, PIPE_FORMAT_Z24S8_UNORM, - PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0)) - depthFormat = PIPE_FORMAT_Z24S8_UNORM; - else - depthFormat = PIPE_FORMAT_S8Z24_UNORM; - } else - depthFormat = PIPE_FORMAT_NONE; - - if (visual->stencilBits) { - if (pscreen->is_format_supported(pscreen, PIPE_FORMAT_Z24S8_UNORM, - PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0)) - stencilFormat = PIPE_FORMAT_Z24S8_UNORM; - else - stencilFormat = PIPE_FORMAT_S8Z24_UNORM; - } else - stencilFormat = PIPE_FORMAT_NONE; + switch(visual->stencilBits) { + default: + case 0: + drawable->stencil_format = PIPE_FORMAT_NONE; + break; + case 8: + drawable->stencil_format = (screen->sd_depth_bits_last) ? + PIPE_FORMAT_S8Z24_UNORM: + PIPE_FORMAT_Z24S8_UNORM; + break; + } drawable->stfb = st_create_framebuffer(visual, - colorFormat, - depthFormat, - stencilFormat, + drawable->color_format, + drawable->depth_format, + drawable->stencil_format, dPriv->w, dPriv->h, (void *)drawable); if (drawable->stfb == NULL) diff --git a/src/gallium/state_trackers/dri/dri_drawable.h b/src/gallium/state_trackers/dri/dri_drawable.h index 78a66624aaf..2fbd5f1eb7c 100644 --- a/src/gallium/state_trackers/dri/dri_drawable.h +++ b/src/gallium/state_trackers/dri/dri_drawable.h @@ -46,6 +46,11 @@ struct dri_drawable unsigned attachments[8]; unsigned num_attachments; + __DRIbuffer old[8]; + unsigned old_num; + unsigned old_w; + unsigned old_h; + /* gallium */ struct st_framebuffer *stfb; struct pipe_fence_handle *swap_fences[DRI_SWAP_FENCES_MAX]; @@ -53,6 +58,10 @@ struct dri_drawable unsigned int tail; unsigned int desired_fences; unsigned int cur_fences; + + enum pipe_format color_format; + enum pipe_format depth_format; + enum pipe_format stencil_format; }; static INLINE struct dri_drawable * diff --git a/src/gallium/state_trackers/dri/dri_extensions.c b/src/gallium/state_trackers/dri/dri_extensions.c index 0c59d42d5c6..7c04c2b970e 100644 --- a/src/gallium/state_trackers/dri/dri_extensions.c +++ b/src/gallium/state_trackers/dri/dri_extensions.c @@ -36,9 +36,11 @@ #define need_GL_ARB_multisample #define need_GL_ARB_occlusion_query #define need_GL_ARB_point_parameters +#define need_GL_ARB_shader_objects #define need_GL_ARB_texture_compression #define need_GL_ARB_vertex_buffer_object #define need_GL_ARB_vertex_program +#define need_GL_ARB_vertex_shader #define need_GL_ARB_window_pos #define need_GL_EXT_blend_color #define need_GL_EXT_blend_equation_separate @@ -50,16 +52,23 @@ #define need_GL_EXT_multi_draw_arrays #define need_GL_EXT_secondary_color #define need_GL_NV_vertex_program +#define need_GL_VERSION_2_0 +#define need_GL_VERSION_2_1 #include "extension_helper.h" /** * Extension strings exported by the driver. */ const struct dri_extension card_extensions[] = { + {"GL_ARB_fragment_shader", NULL}, {"GL_ARB_multisample", GL_ARB_multisample_functions}, {"GL_ARB_multitexture", NULL}, {"GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions}, + {"GL_ARB_pixel_buffer_object", NULL}, {"GL_ARB_point_parameters", GL_ARB_point_parameters_functions}, + {"GL_ARB_shading_language_100", GL_VERSION_2_0_functions }, + {"GL_ARB_shading_language_120", GL_VERSION_2_1_functions }, + {"GL_ARB_shader_objects", GL_ARB_shader_objects_functions}, {"GL_ARB_texture_border_clamp", NULL}, {"GL_ARB_texture_compression", GL_ARB_texture_compression_functions}, {"GL_ARB_texture_cube_map", NULL}, @@ -69,12 +78,11 @@ const struct dri_extension card_extensions[] = { {"GL_ARB_texture_mirrored_repeat", NULL}, {"GL_ARB_texture_rectangle", NULL}, {"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions}, - {"GL_ARB_pixel_buffer_object", NULL}, + {"GL_ARB_vertex_shader", GL_ARB_vertex_shader_functions}, {"GL_ARB_vertex_program", GL_ARB_vertex_program_functions}, {"GL_ARB_window_pos", GL_ARB_window_pos_functions}, {"GL_EXT_blend_color", GL_EXT_blend_color_functions}, - {"GL_EXT_blend_equation_separate", - GL_EXT_blend_equation_separate_functions}, + {"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions}, {"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions}, {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions}, {"GL_EXT_blend_subtract", NULL}, diff --git a/src/gallium/state_trackers/dri/dri_screen.c b/src/gallium/state_trackers/dri/dri_screen.c index d3392ee690b..5f78b7264af 100644 --- a/src/gallium/state_trackers/dri/dri_screen.c +++ b/src/gallium/state_trackers/dri/dri_screen.c @@ -69,39 +69,65 @@ PUBLIC const char __driConfigOptions[] = struct dri1_api *__dri1_api_hooks = NULL; static const __DRIconfig ** -dri_fill_in_modes(__DRIscreenPrivate * psp, - unsigned pixel_bits, unsigned depth_bits, - unsigned stencil_bits, GLboolean have_back_buffer) +dri_fill_in_modes(struct dri_screen *screen, + unsigned pixel_bits) { __DRIconfig **configs; - __GLcontextModes *m; unsigned num_modes; - uint8_t depth_bits_array[3]; - uint8_t stencil_bits_array[3]; + uint8_t depth_bits_array[4]; + uint8_t stencil_bits_array[4]; uint8_t msaa_samples_array[1]; unsigned depth_buffer_factor; unsigned back_buffer_factor; unsigned msaa_samples_factor; GLenum fb_format; GLenum fb_type; - int i; + struct pipe_screen *p_screen = screen->pipe_screen; static const GLenum back_buffer_modes[] = { GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML }; - /* TODO probe the hardware of what is supports */ depth_bits_array[0] = 0; - depth_bits_array[1] = 24; - depth_bits_array[2] = 24; - - stencil_bits_array[0] = 0; /* no depth or stencil */ - stencil_bits_array[1] = 0; /* z24x8 */ - stencil_bits_array[2] = 8; /* z24s8 */ + stencil_bits_array[0] = 0; + depth_buffer_factor = 1; + + if (p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM, + PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0)) { + depth_bits_array[depth_buffer_factor] = 16; + stencil_bits_array[depth_buffer_factor++] = 0; + } + if (p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM, + PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0)) { + depth_bits_array[depth_buffer_factor] = 24; + stencil_bits_array[depth_buffer_factor++] = 0; + screen->d_depth_bits_last = TRUE; + } else if (p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM, + PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_DEPTH_STENCIL, + 0)) { + depth_bits_array[depth_buffer_factor] = 24; + stencil_bits_array[depth_buffer_factor++] = 0; + screen->d_depth_bits_last = FALSE; + } + if (p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8Z24_UNORM, + PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0)) { + depth_bits_array[depth_buffer_factor] = 24; + stencil_bits_array[depth_buffer_factor++] = 8; + screen->sd_depth_bits_last = TRUE; + } else if (p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24S8_UNORM, + PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_DEPTH_STENCIL, + 0)) { + depth_bits_array[depth_buffer_factor] = 24; + stencil_bits_array[depth_buffer_factor++] = 8; + screen->sd_depth_bits_last = FALSE; + } msaa_samples_array[0] = 0; - - depth_buffer_factor = 3; back_buffer_factor = 3; msaa_samples_factor = 1; @@ -109,9 +135,19 @@ dri_fill_in_modes(__DRIscreenPrivate * psp, depth_buffer_factor * back_buffer_factor * msaa_samples_factor * 4; if (pixel_bits == 16) { + if (!p_screen->is_format_supported(p_screen, + PIPE_FORMAT_R5G6B5_UNORM, + PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) + return NULL; fb_format = GL_RGB; fb_type = GL_UNSIGNED_SHORT_5_6_5; } else { + if (!p_screen->is_format_supported(p_screen, + PIPE_FORMAT_A8R8G8B8_UNORM, + PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) + return NULL; fb_format = GL_BGRA; fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; } @@ -126,13 +162,6 @@ dri_fill_in_modes(__DRIscreenPrivate * psp, return NULL; } - for (i = 0; configs[i]; i++) { - m = &configs[i]->modes; - if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) { - m->visualRating = GLX_SLOW_CONFIG; - } - } - return (const const __DRIconfig **)configs; } @@ -170,6 +199,7 @@ dri_init_screen(__DRIscreenPrivate * sPriv) if (!screen) return NULL; + screen->api = drm_api_create(); screen->sPriv = sPriv; screen->fd = sPriv->fd; screen->drmLock = (drmLock *) & sPriv->pSAREA->lock; @@ -187,7 +217,7 @@ dri_init_screen(__DRIscreenPrivate * sPriv) dri_copy_version(&arg.drm_version, &sPriv->drm_version); arg.api = NULL; - screen->pipe_screen = drm_api_hooks.create_screen(screen->fd, &arg.base); + screen->pipe_screen = screen->api->create_screen(screen->api, screen->fd, &arg.base); if (!screen->pipe_screen || !arg.api) { debug_printf("%s: failed to create dri1 screen\n", __FUNCTION__); @@ -200,7 +230,13 @@ dri_init_screen(__DRIscreenPrivate * sPriv) driParseOptionInfo(&screen->optionCache, __driConfigOptions, __driNConfigOptions); - configs = dri_fill_in_modes(sPriv, sPriv->fbBPP, 24, 8, 1); + /** + * FIXME: If the driver supports format conversion swapbuffer blits, we might + * want to support other color bit depths than the server is currently + * using. + */ + + configs = dri_fill_in_modes(screen, sPriv->fbBPP); if (!configs) goto out_no_configs; @@ -230,13 +266,14 @@ dri_init_screen2(__DRIscreenPrivate * sPriv) if (!screen) goto fail; + screen->api = drm_api_create(); screen->sPriv = sPriv; screen->fd = sPriv->fd; sPriv->private = (void *)screen; sPriv->extensions = dri_screen_extensions; arg.mode = DRM_CREATE_NORMAL; - screen->pipe_screen = drm_api_hooks.create_screen(screen->fd, &arg); + screen->pipe_screen = screen->api->create_screen(screen->api, screen->fd, &arg); if (!screen->pipe_screen) { debug_printf("%s: failed to create pipe_screen\n", __FUNCTION__); goto fail; @@ -248,7 +285,7 @@ dri_init_screen2(__DRIscreenPrivate * sPriv) driParseOptionInfo(&screen->optionCache, __driConfigOptions, __driNConfigOptions); - return dri_fill_in_modes(sPriv, 4 * 8, 24, 8, 1); + return dri_fill_in_modes(screen, 32); fail: return NULL; } diff --git a/src/gallium/state_trackers/dri/dri_screen.h b/src/gallium/state_trackers/dri/dri_screen.h index 100d9e50e07..f3335bb09f9 100644 --- a/src/gallium/state_trackers/dri/dri_screen.h +++ b/src/gallium/state_trackers/dri/dri_screen.h @@ -60,8 +60,11 @@ struct dri_screen drmLock *drmLock; /* gallium */ + struct drm_api *api; struct pipe_winsys *pipe_winsys; struct pipe_screen *pipe_screen; + boolean d_depth_bits_last; + boolean sd_depth_bits_last; }; /** cast wrapper */ diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile index 692a3c8b76f..e825aa718b6 100644 --- a/src/gallium/state_trackers/egl/Makefile +++ b/src/gallium/state_trackers/egl/Makefile @@ -1,29 +1,19 @@ -TARGET = libegldrm.a -CFILES = $(wildcard ./*.c) -OBJECTS = $(patsubst ./%.c,./%.o,$(CFILES)) -GALLIUMDIR = ../.. -TOP = ../../../.. +TOP = ../../../.. +include $(TOP)/configs/current -include ${TOP}/configs/current +LIBNAME = egldrm -CFLAGS := \ - -I${GALLIUMDIR}/include \ - -I${GALLIUMDIR}/auxiliary \ - -I${TOP}/src/mesa/drivers/dri/common \ - -I${TOP}/src/mesa \ - -I$(TOP)/include \ - -I$(TOP)/src/egl/main \ - ${LIBDRM_CFLAGS} \ - ${CFLAGS} +LIBRARY_INCLUDES = \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/auxiliary \ + -I$(TOP)/src/mesa/drivers/dri/common \ + -I$(TOP)/src/mesa \ + -I$(TOP)/include \ + -I$(TOP)/src/egl/main \ + $(shell pkg-config --cflags-only-I libdrm) -############################################# -.PHONY = all clean +C_SOURCES = $(wildcard ./*.c) -all: ${TARGET} -${TARGET}: ${OBJECTS} - ar rcs $@ $^ - -clean: - rm -rf ${OBJECTS} ${TARGET} +include ../../Makefile.template diff --git a/src/gallium/state_trackers/egl/egl_context.c b/src/gallium/state_trackers/egl/egl_context.c index 36548fae263..e2da2180f71 100644 --- a/src/gallium/state_trackers/egl/egl_context.c +++ b/src/gallium/state_trackers/egl/egl_context.c @@ -113,9 +113,9 @@ drm_create_context(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext if (!ctx) goto err_c; - _eglInitContext(drv, dpy, &ctx->base, config, attrib_list); + _eglInitContext(drv, &ctx->base, conf, attrib_list); - ctx->pipe = drm_api_hooks.create_context(dev->screen); + ctx->pipe = dev->api->create_context(dev->api, dev->screen); if (!ctx->pipe) goto err_pipe; @@ -129,8 +129,8 @@ drm_create_context(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext if (!ctx->st) goto err_gl; - /* generate handle and insert into hash table */ - _eglSaveContext(&ctx->base); + /* link to display */ + _eglLinkContext(&ctx->base, _eglLookupDisplay(dpy)); assert(_eglGetContextHandle(&ctx->base)); return _eglGetContextHandle(&ctx->base); @@ -147,10 +147,8 @@ EGLBoolean drm_destroy_context(_EGLDriver *drv, EGLDisplay dpy, EGLContext context) { struct drm_context *c = lookup_drm_context(context); - _eglRemoveContext(&c->base); - if (c->base.IsBound) { - c->base.DeletePending = EGL_TRUE; - } else { + _eglUnlinkContext(&c->base); + if (!c->base.IsBound) { st_destroy_context(c->st); c->pipe->destroy(c->pipe); free(c); diff --git a/src/gallium/state_trackers/egl/egl_surface.c b/src/gallium/state_trackers/egl/egl_surface.c index 489aa8d9af5..86f2ea97e54 100644 --- a/src/gallium/state_trackers/egl/egl_surface.c +++ b/src/gallium/state_trackers/egl/egl_surface.c @@ -132,7 +132,7 @@ drm_create_texture(_EGLDriver *drv, scrn->front.width = w; scrn->front.height = h; scrn->front.pitch = pitch; - drm_api_hooks.handle_from_buffer(screen, scrn->buffer, &scrn->front.handle); + dev->api->handle_from_buffer(dev->api, screen, scrn->buffer, &scrn->front.handle); if (0) goto err_handle; @@ -232,7 +232,7 @@ drm_create_pbuffer_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, if (!surf) goto err; - if (!_eglInitSurface(drv, dpy, &surf->base, EGL_PBUFFER_BIT, config, attrib_list)) + if (!_eglInitSurface(drv, &surf->base, EGL_PBUFFER_BIT, conf, attrib_list)) goto err_surf; surf->w = width; @@ -245,7 +245,7 @@ drm_create_pbuffer_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, (void*)surf); drm_visual_modes_destroy(visual); - _eglSaveSurface(&surf->base); + _eglLinkSurface(&surf->base, _eglLookupDisplay(dpy)); return surf->base.Handle; err_surf: @@ -364,10 +364,9 @@ EGLBoolean drm_destroy_surface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) { struct drm_surface *surf = lookup_drm_surface(surface); - _eglRemoveSurface(&surf->base); - if (surf->base.IsBound) { - surf->base.DeletePending = EGL_TRUE; - } else { + _eglUnlinkSurface(&surf->base); + + if (!surf->base.IsBound) { if (surf->screen) drm_takedown_shown_screen(drv, surf->screen); st_unreference_framebuffer(surf->stfb); diff --git a/src/gallium/state_trackers/egl/egl_tracker.c b/src/gallium/state_trackers/egl/egl_tracker.c index 8e620084617..521c91d8958 100644 --- a/src/gallium/state_trackers/egl/egl_tracker.c +++ b/src/gallium/state_trackers/egl/egl_tracker.c @@ -35,6 +35,8 @@ _eglMain(_EGLDisplay *dpy, const char *args) return NULL; } + drm->api = drm_api_create(); + /* First fill in the dispatch table with defaults */ _eglInitDriverFallbacks(&drm->base); /* then plug in our Drm-specific functions */ @@ -146,7 +148,7 @@ drm_initialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor) dev->drmFD = fd; drm_get_device_id(dev); - dev->screen = drm_api_hooks.create_screen(dev->drmFD, NULL); + dev->screen = dev->api->create_screen(dev->api, dev->drmFD, NULL); if (!dev->screen) goto err_screen; dev->winsys = dev->screen->winsys; @@ -234,6 +236,7 @@ drm_terminate(_EGLDriver *drv, EGLDisplay dpy) dev->screen->destroy(dev->screen); dev->winsys = NULL; + dev->api->destroy(dev->api); drmClose(dev->drmFD); diff --git a/src/gallium/state_trackers/egl/egl_tracker.h b/src/gallium/state_trackers/egl/egl_tracker.h index ce2717de639..3b8836720d6 100644 --- a/src/gallium/state_trackers/egl/egl_tracker.h +++ b/src/gallium/state_trackers/egl/egl_tracker.h @@ -38,6 +38,7 @@ struct drm_device * pipe */ + struct drm_api *api; struct pipe_winsys *winsys; struct pipe_screen *screen; diff --git a/src/gallium/state_trackers/g3dvl/vl_basic_csc.c b/src/gallium/state_trackers/g3dvl/vl_basic_csc.c index 16d4f1e32c9..20d682de3fb 100644 --- a/src/gallium/state_trackers/g3dvl/vl_basic_csc.c +++ b/src/gallium/state_trackers/g3dvl/vl_basic_csc.c @@ -82,7 +82,6 @@ static int vlResizeFrameBuffer template.width[0] = width; template.height[0] = height; template.depth[0] = 1; - template.compressed = 0; pf_get_block(template.format, &template.block); template.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET; @@ -669,7 +668,6 @@ static int vlInit sampler.compare_func = PIPE_FUNC_ALWAYS; sampler.normalized_coords = 1; /*sampler.prefilter = ;*/ - /*sampler.shadow_ambient = ;*/ /*sampler.lod_bias = ;*/ /*sampler.min_lod = ;*/ /*sampler.max_lod = ;*/ diff --git a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c index eb8270ecad3..23631adb693 100644 --- a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c +++ b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c @@ -1074,7 +1074,6 @@ static int vlInit sampler.compare_func = PIPE_FUNC_ALWAYS; sampler.normalized_coords = 1; /*sampler.prefilter = ;*/ - /*sampler.shadow_ambient = ;*/ /*sampler.lod_bias = ;*/ sampler.min_lod = 0; /*sampler.max_lod = ;*/ @@ -1090,7 +1089,6 @@ static int vlInit template.width[0] = vlRoundUpPOT(mc->picture_width); template.height[0] = vlRoundUpPOT(mc->picture_height); template.depth[0] = 1; - template.compressed = 0; pf_get_block(template.format, &template.block); template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | PIPE_TEXTURE_USAGE_DYNAMIC; diff --git a/src/gallium/state_trackers/g3dvl/vl_surface.c b/src/gallium/state_trackers/g3dvl/vl_surface.c index 92388f7978d..7f60852cae8 100644 --- a/src/gallium/state_trackers/g3dvl/vl_surface.c +++ b/src/gallium/state_trackers/g3dvl/vl_surface.c @@ -45,7 +45,6 @@ int vlCreateSurface template.width[0] = vlRoundUpPOT(sfc->width); template.height[0] = vlRoundUpPOT(sfc->height); template.depth[0] = 1; - template.compressed = 0; pf_get_block(template.format, &template.block); template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | PIPE_TEXTURE_USAGE_RENDER_TARGET; diff --git a/src/gallium/state_trackers/glx/xlib/fakeglx.c b/src/gallium/state_trackers/glx/xlib/fakeglx.c index 6df4c7d6936..23777c76f6c 100644 --- a/src/gallium/state_trackers/glx/xlib/fakeglx.c +++ b/src/gallium/state_trackers/glx/xlib/fakeglx.c @@ -97,6 +97,9 @@ struct fake_glx_context { +#define DEFAULT_DIRECT GL_TRUE + + /**********************************************************************/ /*** GLX Visual Code ***/ /**********************************************************************/ @@ -1059,7 +1062,7 @@ Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo, return NULL; } - glxCtx->glxContext.isDirect = GL_FALSE; + glxCtx->glxContext.isDirect = DEFAULT_DIRECT; glxCtx->glxContext.currentDpy = dpy; glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */ @@ -1296,9 +1299,9 @@ Fake_glXDestroyContext( Display *dpy, GLXContext ctx ) static Bool Fake_glXIsDirect( Display *dpy, GLXContext ctx ) { - (void) dpy; + struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; (void) ctx; - return False; + return glxCtx->glxContext.isDirect; } @@ -2055,7 +2058,7 @@ Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config, return NULL; } - glxCtx->glxContext.isDirect = GL_FALSE; + glxCtx->glxContext.isDirect = DEFAULT_DIRECT; glxCtx->glxContext.currentDpy = dpy; glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */ @@ -2277,7 +2280,7 @@ Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int re return NULL; } - glxCtx->glxContext.isDirect = GL_FALSE; + glxCtx->glxContext.isDirect = DEFAULT_DIRECT; glxCtx->glxContext.currentDpy = dpy; glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */ diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c index a3d16516531..79c2230588f 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.c +++ b/src/gallium/state_trackers/glx/xlib/xm_api.c @@ -1100,26 +1100,19 @@ XMesaContext XMesaGetCurrentContext( void ) - - - -/* - * Copy the back buffer to the front buffer. If there's no back buffer - * this is a no-op. +/** + * Swap front and back color buffers and have winsys display front buffer. + * If there's no front color buffer no swap actually occurs. */ PUBLIC void XMesaSwapBuffers( XMesaBuffer b ) { - struct pipe_surface *surf; + struct pipe_surface *frontLeftSurf; - /* If we're swapping the buffer associated with the current context - * we have to flush any pending rendering commands first. - */ - st_notify_swapbuffers(b->stfb); + st_swapbuffers(b->stfb, &frontLeftSurf, NULL); - st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT, &surf); - if (surf) { - driver.display_surface(b, surf); + if (frontLeftSurf) { + driver.display_surface(b, frontLeftSurf); } xmesa_check_and_update_buffer_size(NULL, b); diff --git a/src/gallium/state_trackers/vega/Makefile b/src/gallium/state_trackers/vega/Makefile new file mode 100644 index 00000000000..b8c805b06c4 --- /dev/null +++ b/src/gallium/state_trackers/vega/Makefile @@ -0,0 +1,128 @@ +# src/mesa/Makefile + +TOP = ../../../.. +include $(TOP)/configs/current +GALLIUM = $(TOP) + +### Lists of source files, included by Makefiles + +VG_SOURCES = \ + api_context.c \ + api_filters.c \ + api_images.c \ + api_masks.c \ + api_misc.c \ + api_paint.c \ + api_params.c \ + api_path.c \ + api_text.c \ + api_transform.c \ + vgu.c \ + vg_context.c \ + vg_state.c \ + vg_tracker.c \ + vg_translate.c \ + polygon.c \ + bezier.c \ + path.c \ + paint.c \ + arc.c \ + image.c \ + renderer.c \ + stroker.c \ + mask.c \ + shader.c \ + shaders_cache.c + + +### All the core C sources + +ALL_SOURCES = \ + $(VG_SOURCES) + + +### Object files +VG_OBJECTS = \ + $(VG_SOURCES:.c=.o) + +### Include directories + +INCLUDE_DIRS = \ + -I$(TOP)/include \ + -I$(GALLIUM)/include \ + -I$(GALLIUM)/src/gallium/include \ + -I$(GALLIUM)/src/gallium/auxiliary + +VG_LIB = OpenVG +VG_LIB_NAME = lib$(VG_LIB).so + +VG_MAJOR = 1 +VG_MINOR = 0 +VG_TINY = 0 + +GALLIUM_LIBS = \ + $(GALLIUM)/src/gallium/auxiliary/pipebuffer/libpipebuffer.a \ + $(GALLIUM)/src/gallium/auxiliary/sct/libsct.a \ + $(GALLIUM)/src/gallium/auxiliary/draw/libdraw.a \ + $(GALLIUM)/src/gallium/auxiliary/rtasm/librtasm.a \ + $(GALLIUM)/src/gallium/auxiliary/translate/libtranslate.a \ + $(GALLIUM)/src/gallium/auxiliary/cso_cache/libcso_cache.a \ + $(GALLIUM)/src/gallium/auxiliary/util/libutil.a \ + $(GALLIUM)/src/gallium/auxiliary/tgsi/libtgsi.a + +.SUFFIXES : .cpp + +.c.o: + $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ + +.cpp.o: + $(CXX) -c $(INCLUDE_DIRS) $(CXXFLAGS) $< -o $@ + +.S.o: + $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ + + +default: depend subdirs $(TOP)/$(LIB_DIR)/$(VG_LIB_NAME) + +# Make the OpenVG library +$(TOP)/$(LIB_DIR)/$(VG_LIB_NAME): $(VG_OBJECTS) $(GALLIUM_LIBS) + $(TOP)/bin/mklib -o $(VG_LIB) \ + -major $(VG_MAJOR) \ + -minor $(VG_MINOR) \ + -patch $(VG_TINY) \ + -install $(TOP)/$(LIB_DIR) \ + $(VG_OBJECTS) $(GALLIUM_LIBS) \ + -Wl,--whole-archive $(LIBS) -Wl,--no-whole-archive $(SYS_LIBS) + +###################################################################### +# Generic stuff + +depend: $(ALL_SOURCES) + @ echo "running $(MKDEP)" + @ rm -f depend # workaround oops on gutsy?!? + @ touch depend + @ $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) $(ALL_SOURCES) \ + > /dev/null 2>/dev/null + + +subdirs: + +install: default + $(INSTALL) -d $(INSTALL_DIR)/include/VG + $(INSTALL) -d $(INSTALL_DIR)/$(LIB_DIR) + $(INSTALL) -m 644 $(TOP)/include/VG/*.h $(INSTALL_DIR)/include/VG + @if [ -e $(TOP)/$(LIB_DIR)/$(VG_LIB_NAME) ]; then \ + $(INSTALL) $(TOP)/$(LIB_DIR)/libOpenVG* $(INSTALL_DIR)/$(LIB_DIR); \ + fi + +# Emacs tags +tags: + etags `find . -name \*.[ch]` $(TOP)/include/VG/*.h + +clean: + -rm -f *.o + -rm -f */*.o + -rm -f */*/*.o + -rm -f depend depend.bak + +include depend diff --git a/src/gallium/state_trackers/vega/api_consts.h b/src/gallium/state_trackers/vega/api_consts.h new file mode 100644 index 00000000000..e1b48d4a46c --- /dev/null +++ b/src/gallium/state_trackers/vega/api_consts.h @@ -0,0 +1,56 @@ +/************************************************************************** + * + * 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 API_CONSTS_H +#define API_CONSTS_H + +/*must be at least 32*/ +#define VEGA_MAX_SCISSOR_RECTS 32 + +/*must be at least 16*/ +#define VEGA_MAX_DASH_COUNT 32 + +/*must be at least 7*/ +#define VEGA_MAX_KERNEL_SIZE 7 + +/*must be at least 15*/ +#define VEGA_MAX_SEPARABLE_KERNEL_SIZE 15 + +/*must be at least 32*/ +#define VEGA_MAX_COLOR_RAMP_STOPS 256 + +#define VEGA_MAX_IMAGE_WIDTH 2048 + +#define VEGA_MAX_IMAGE_HEIGHT 2048 + +#define VEGA_MAX_IMAGE_PIXELS (2048*2048) + +#define VEGA_MAX_IMAGE_BYTES (2048*2048 * 4) + +/*must be at least 128*/ +#define VEGA_MAX_GAUSSIAN_STD_DEVIATION 128 + +#endif diff --git a/src/gallium/state_trackers/vega/api_context.c b/src/gallium/state_trackers/vega/api_context.c new file mode 100644 index 00000000000..47db102dd2d --- /dev/null +++ b/src/gallium/state_trackers/vega/api_context.c @@ -0,0 +1,75 @@ +/************************************************************************** + * + * 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 "VG/openvg.h" + +#include "vg_context.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" + +VGErrorCode vgGetError(void) +{ + struct vg_context *ctx = vg_current_context(); + VGErrorCode error = VG_NO_CONTEXT_ERROR; + + if (!ctx) + return error; + + error = ctx->_error; + ctx->_error = VG_NO_ERROR; + + return error; +} + +void vgFlush(void) +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_context *pipe; + + if (!ctx) + return; + + pipe = ctx->pipe; + pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); +} + +void vgFinish(void) +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_fence_handle *fence = NULL; + struct pipe_context *pipe; + + if (!ctx) + return; + + pipe = ctx->pipe; + + pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence); + + pipe->screen->fence_finish(pipe->screen, fence, 0); + pipe->screen->fence_reference(pipe->screen, &fence, NULL); +} diff --git a/src/gallium/state_trackers/vega/api_filters.c b/src/gallium/state_trackers/vega/api_filters.c new file mode 100644 index 00000000000..862cbb03c43 --- /dev/null +++ b/src/gallium/state_trackers/vega/api_filters.c @@ -0,0 +1,805 @@ +/************************************************************************** + * + * 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 "VG/openvg.h" + +#include "vg_context.h" +#include "image.h" +#include "renderer.h" +#include "shaders_cache.h" +#include "st_inlines.h" + +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "pipe/p_inlines.h" +#include "pipe/p_screen.h" +#include "pipe/p_shader_tokens.h" + +#include "util/u_memory.h" + + +#include "asm_filters.h" + + +struct filter_info { + struct vg_image *dst; + struct vg_image *src; + struct vg_shader * (*setup_shader)(struct vg_context *, void *); + void *user_data; + const void *const_buffer; + VGint const_buffer_len; + VGTilingMode tiling_mode; + struct pipe_texture *extra_texture; +}; + +static INLINE struct pipe_texture *create_texture_1d(struct vg_context *ctx, + const VGuint *color_data, + const VGint color_data_len) +{ + struct pipe_context *pipe = ctx->pipe; + struct pipe_screen *screen = pipe->screen; + struct pipe_texture *tex = 0; + struct pipe_texture templ; + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_1D; + templ.format = PIPE_FORMAT_A8R8G8B8_UNORM; + templ.last_level = 0; + templ.width[0] = color_data_len; + templ.height[0] = 1; + templ.depth[0] = 1; + pf_get_block(PIPE_FORMAT_A8R8G8B8_UNORM, &templ.block); + templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; + + tex = screen->texture_create(screen, &templ); + + { /* upload color_data */ + struct pipe_transfer *transfer = + screen->get_tex_transfer(screen, tex, + 0, 0, 0, + PIPE_TRANSFER_READ_WRITE , + 0, 0, tex->width[0], tex->height[0]); + void *map = screen->transfer_map(screen, transfer); + memcpy(map, color_data, sizeof(VGint)*color_data_len); + screen->transfer_unmap(screen, transfer); + screen->tex_transfer_destroy(transfer); + } + + return tex; +} + +static INLINE struct pipe_surface * setup_framebuffer(struct vg_image *dst) +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_context *pipe = ctx->pipe; + struct pipe_framebuffer_state fb; + struct pipe_surface *dst_surf = pipe->screen->get_tex_surface( + pipe->screen, dst->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_WRITE); + + /* drawing dest */ + memset(&fb, 0, sizeof(fb)); + fb.width = dst->x + dst_surf->width; + fb.height = dst->y + dst_surf->height; + fb.nr_cbufs = 1; + fb.cbufs[0] = dst_surf; + { + VGint i; + for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) + fb.cbufs[i] = 0; + } + cso_set_framebuffer(ctx->cso_context, &fb); + + return dst_surf; +} + +static void setup_viewport(struct vg_image *dst) +{ + struct vg_context *ctx = vg_current_context(); + vg_set_viewport(ctx, VEGA_Y0_TOP); +} + +static void setup_blend() +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_blend_state blend; + memset(&blend, 0, sizeof(blend)); + blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + if (ctx->state.vg.filter_channel_mask & VG_RED) + blend.colormask |= PIPE_MASK_R; + if (ctx->state.vg.filter_channel_mask & VG_GREEN) + blend.colormask |= PIPE_MASK_G; + if (ctx->state.vg.filter_channel_mask & VG_BLUE) + blend.colormask |= PIPE_MASK_B; + if (ctx->state.vg.filter_channel_mask & VG_ALPHA) + blend.colormask |= PIPE_MASK_A; + blend.blend_enable = 1; + cso_set_blend(ctx->cso_context, &blend); +} + +static void setup_constant_buffer(struct vg_context *ctx, const void *buffer, + VGint param_bytes) +{ + struct pipe_context *pipe = ctx->pipe; + struct pipe_constant_buffer *cbuf = &ctx->filter.buffer; + + /* We always need to get a new buffer, to keep the drivers simple and + * avoid gratuitous rendering synchronization. */ + pipe_buffer_reference(&cbuf->buffer, NULL); + + cbuf->buffer = pipe_buffer_create(pipe->screen, 16, + PIPE_BUFFER_USAGE_CONSTANT, + param_bytes); + + if (cbuf->buffer) { + st_no_flush_pipe_buffer_write(ctx, cbuf->buffer, + 0, param_bytes, buffer); + } + + ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf); +} + +static void setup_samplers(struct vg_context *ctx, struct filter_info *info) +{ + struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; + struct pipe_texture *textures[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_state sampler[3]; + int num_samplers = 0; + int num_textures = 0; + + samplers[0] = NULL; + samplers[1] = NULL; + samplers[2] = NULL; + samplers[3] = NULL; + textures[0] = NULL; + textures[1] = NULL; + textures[2] = NULL; + textures[3] = NULL; + + memset(&sampler[0], 0, sizeof(struct pipe_sampler_state)); + sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler[0].wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler[0].min_img_filter = PIPE_TEX_MIPFILTER_LINEAR; + sampler[0].mag_img_filter = PIPE_TEX_MIPFILTER_LINEAR; + sampler[0].normalized_coords = 1; + + switch(info->tiling_mode) { + case VG_TILE_FILL: + sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_BORDER; + sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_BORDER; + memcpy(sampler[0].border_color, + ctx->state.vg.tile_fill_color, + sizeof(VGfloat) * 4); + break; + case VG_TILE_PAD: + sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + break; + case VG_TILE_REPEAT: + sampler[0].wrap_s = PIPE_TEX_WRAP_REPEAT; + sampler[0].wrap_t = PIPE_TEX_WRAP_REPEAT; + break; + case VG_TILE_REFLECT: + sampler[0].wrap_s = PIPE_TEX_WRAP_MIRROR_REPEAT; + sampler[0].wrap_t = PIPE_TEX_WRAP_MIRROR_REPEAT; + break; + default: + debug_assert(!"Unknown tiling mode"); + } + + samplers[0] = &sampler[0]; + textures[0] = info->src->texture; + ++num_samplers; + ++num_textures; + + if (info->extra_texture) { + memcpy(&sampler[1], &sampler[0], sizeof(struct pipe_sampler_state)); + samplers[1] = &sampler[1]; + textures[1] = info->extra_texture; + ++num_samplers; + ++num_textures; + } + + + cso_set_samplers(ctx->cso_context, num_samplers, (const struct pipe_sampler_state **)samplers); + cso_set_sampler_textures(ctx->cso_context, num_textures, textures); +} + +static struct vg_shader * setup_color_matrix(struct vg_context *ctx, void *user_data) +{ + struct vg_shader *shader = + shader_create_from_text(ctx->pipe, color_matrix_asm, 200, + PIPE_SHADER_FRAGMENT); + cso_set_fragment_shader_handle(ctx->cso_context, shader->driver); + return shader; +} + +static struct vg_shader * setup_convolution(struct vg_context *ctx, void *user_data) +{ + char buffer[1024]; + VGint num_consts = (VGint)(long)(user_data); + struct vg_shader *shader; + + snprintf(buffer, 1023, convolution_asm, num_consts, num_consts / 2 + 1); + + shader = shader_create_from_text(ctx->pipe, buffer, 200, + PIPE_SHADER_FRAGMENT); + + cso_set_fragment_shader_handle(ctx->cso_context, shader->driver); + return shader; +} + +static struct vg_shader * setup_lookup(struct vg_context *ctx, void *user_data) +{ + struct vg_shader *shader = + shader_create_from_text(ctx->pipe, lookup_asm, + 200, PIPE_SHADER_FRAGMENT); + + cso_set_fragment_shader_handle(ctx->cso_context, shader->driver); + return shader; +} + + +static struct vg_shader * setup_lookup_single(struct vg_context *ctx, void *user_data) +{ + char buffer[1024]; + VGImageChannel channel = (VGImageChannel)(user_data); + struct vg_shader *shader; + + switch(channel) { + case VG_RED: + snprintf(buffer, 1023, lookup_single_asm, "xxxx"); + break; + case VG_GREEN: + snprintf(buffer, 1023, lookup_single_asm, "yyyy"); + break; + case VG_BLUE: + snprintf(buffer, 1023, lookup_single_asm, "zzzz"); + break; + case VG_ALPHA: + snprintf(buffer, 1023, lookup_single_asm, "wwww"); + break; + default: + debug_assert(!"Unknown color channel"); + } + + shader = shader_create_from_text(ctx->pipe, buffer, 200, + PIPE_SHADER_FRAGMENT); + + cso_set_fragment_shader_handle(ctx->cso_context, shader->driver); + return shader; +} + +static void execute_filter(struct vg_context *ctx, + struct filter_info *info) +{ + struct pipe_surface *dst_surf; + struct vg_shader *shader; + + cso_save_framebuffer(ctx->cso_context); + cso_save_fragment_shader(ctx->cso_context); + cso_save_viewport(ctx->cso_context); + cso_save_blend(ctx->cso_context); + cso_save_samplers(ctx->cso_context); + cso_save_sampler_textures(ctx->cso_context); + + dst_surf = setup_framebuffer(info->dst); + setup_viewport(info->dst); + setup_blend(); + setup_constant_buffer(ctx, info->const_buffer, info->const_buffer_len); + shader = info->setup_shader(ctx, info->user_data); + setup_samplers(ctx, info); + + renderer_draw_texture(ctx->renderer, + info->src->texture, + info->dst->x, info->dst->y, + info->dst->x + info->dst->width, + info->dst->y + info->dst->height, + info->dst->x, info->dst->y, + info->dst->x + info->dst->width, + info->dst->y + info->dst->height); + + cso_restore_framebuffer(ctx->cso_context); + cso_restore_fragment_shader(ctx->cso_context); + cso_restore_viewport(ctx->cso_context); + cso_restore_blend(ctx->cso_context); + cso_restore_samplers(ctx->cso_context); + cso_restore_sampler_textures(ctx->cso_context); + + vg_shader_destroy(ctx, shader); + + pipe_surface_reference(&dst_surf, NULL); +} + +void vgColorMatrix(VGImage dst, VGImage src, + const VGfloat * matrix) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_image *d, *s; + struct filter_info info; + + if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (!matrix || !is_aligned(matrix)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + d = (struct vg_image*)dst; + s = (struct vg_image*)src; + + if (vg_image_overlaps(d, s)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + info.dst = d; + info.src = s; + info.setup_shader = &setup_color_matrix; + info.user_data = NULL; + info.const_buffer = matrix; + info.const_buffer_len = 20 * sizeof(VGfloat); + info.tiling_mode = VG_TILE_PAD; + info.extra_texture = 0; + execute_filter(ctx, &info); +} + +static VGfloat texture_offset(VGfloat width, VGint kernelSize, VGint current, VGint shift) +{ + VGfloat diff = current - shift; + + return diff / width; +} + +void vgConvolve(VGImage dst, VGImage src, + VGint kernelWidth, VGint kernelHeight, + VGint shiftX, VGint shiftY, + const VGshort * kernel, + VGfloat scale, + VGfloat bias, + VGTilingMode tilingMode) +{ + struct vg_context *ctx = vg_current_context(); + VGfloat *buffer; + VGint buffer_len; + VGint i, j; + VGint idx = 0; + struct vg_image *d, *s; + VGint kernel_size = kernelWidth * kernelHeight; + struct filter_info info; + const VGint max_kernel_size = vgGeti(VG_MAX_KERNEL_SIZE); + + if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + if (kernelWidth <= 0 || kernelHeight <= 0 || + kernelWidth > max_kernel_size || kernelHeight > max_kernel_size) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + if (!kernel || !is_aligned_to(kernel, 2)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + if (tilingMode < VG_TILE_FILL || + tilingMode > VG_TILE_REFLECT) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + d = (struct vg_image*)dst; + s = (struct vg_image*)src; + + if (vg_image_overlaps(d, s)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + vg_validate_state(ctx); + + buffer_len = 8 + 2 * 4 * kernel_size; + buffer = (VGfloat*)malloc(buffer_len * sizeof(VGfloat)); + + buffer[0] = 0.f; + buffer[1] = 1.f; + buffer[2] = 2.f; /*unused*/ + buffer[3] = 4.f; /*unused*/ + + buffer[4] = kernelWidth * kernelHeight; + buffer[5] = scale; + buffer[6] = bias; + buffer[7] = 0.f; + + idx = 8; + for (j = 0; j < kernelHeight; ++j) { + for (i = 0; i < kernelWidth; ++i) { + VGint index = j * kernelWidth + i; + VGfloat x, y; + + x = texture_offset(s->width, kernelWidth, i, shiftX); + y = texture_offset(s->height, kernelHeight, j, shiftY); + + buffer[idx + index*4 + 0] = x; + buffer[idx + index*4 + 1] = y; + buffer[idx + index*4 + 2] = 0.f; + buffer[idx + index*4 + 3] = 0.f; + } + } + idx += kernel_size * 4; + + for (j = 0; j < kernelHeight; ++j) { + for (i = 0; i < kernelWidth; ++i) { + /* transpose the kernel */ + VGint index = j * kernelWidth + i; + VGint kindex = (kernelWidth - i - 1) * kernelHeight + (kernelHeight - j - 1); + buffer[idx + index*4 + 0] = kernel[kindex]; + buffer[idx + index*4 + 1] = kernel[kindex]; + buffer[idx + index*4 + 2] = kernel[kindex]; + buffer[idx + index*4 + 3] = kernel[kindex]; + } + } + + info.dst = d; + info.src = s; + info.setup_shader = &setup_convolution; + info.user_data = (void*)(long)(buffer_len/4); + info.const_buffer = buffer; + info.const_buffer_len = buffer_len * sizeof(VGfloat); + info.tiling_mode = tilingMode; + info.extra_texture = 0; + execute_filter(ctx, &info); + + free(buffer); +} + +void vgSeparableConvolve(VGImage dst, VGImage src, + VGint kernelWidth, + VGint kernelHeight, + VGint shiftX, VGint shiftY, + const VGshort * kernelX, + const VGshort * kernelY, + VGfloat scale, + VGfloat bias, + VGTilingMode tilingMode) +{ + struct vg_context *ctx = vg_current_context(); + VGshort *kernel; + VGint i, j, idx = 0; + const VGint max_kernel_size = vgGeti(VG_MAX_SEPARABLE_KERNEL_SIZE); + + if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + if (kernelWidth <= 0 || kernelHeight <= 0 || + kernelWidth > max_kernel_size || kernelHeight > max_kernel_size) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + if (!kernelX || !kernelY || + !is_aligned_to(kernelX, 2) || !is_aligned_to(kernelY, 2)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + if (tilingMode < VG_TILE_FILL || + tilingMode > VG_TILE_REFLECT) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + kernel = malloc(sizeof(VGshort)*kernelWidth*kernelHeight); + for (i = 0; i < kernelWidth; ++i) { + for (j = 0; j < kernelHeight; ++j) { + kernel[idx] = kernelX[i] * kernelY[j]; + ++idx; + } + } + vgConvolve(dst, src, kernelWidth, kernelHeight, shiftX, shiftY, + kernel, scale, bias, tilingMode); + free(kernel); +} + +static INLINE VGfloat compute_gaussian_componenet(VGfloat x, VGfloat y, + VGfloat stdDeviationX, + VGfloat stdDeviationY) +{ + VGfloat mult = 1 / ( 2 * M_PI * stdDeviationX * stdDeviationY); + VGfloat e = exp( - ( pow(x, 2)/(2*pow(stdDeviationX, 2)) + + pow(y, 2)/(2*pow(stdDeviationY, 2)) ) ); + return mult * e; +} + +static INLINE VGint compute_kernel_size(VGfloat deviation) +{ + VGint size = ceil(2.146 * deviation); + if (size > 11) + return 11; + return size; +} + +static void compute_gaussian_kernel(VGfloat *kernel, + VGint width, VGint height, + VGfloat stdDeviationX, + VGfloat stdDeviationY) +{ + VGint i, j; + VGfloat scale = 0.0f; + + for (j = 0; j < height; ++j) { + for (i = 0; i < width; ++i) { + VGint idx = (height - j -1) * width + (width - i -1); + kernel[idx] = compute_gaussian_componenet(i-(ceil(width/2))-1, + j-ceil(height/2)-1, + stdDeviationX, stdDeviationY); + scale += kernel[idx]; + } + } + + for (j = 0; j < height; ++j) { + for (i = 0; i < width; ++i) { + VGint idx = j * width + i; + kernel[idx] /= scale; + } + } +} + +void vgGaussianBlur(VGImage dst, VGImage src, + VGfloat stdDeviationX, + VGfloat stdDeviationY, + VGTilingMode tilingMode) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_image *d, *s; + VGfloat *buffer, *kernel; + VGint kernel_width, kernel_height, kernel_size; + VGint buffer_len; + VGint idx, i, j; + struct filter_info info; + + if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (stdDeviationX <= 0 || stdDeviationY <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + if (tilingMode < VG_TILE_FILL || + tilingMode > VG_TILE_REFLECT) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + d = (struct vg_image*)dst; + s = (struct vg_image*)src; + + if (vg_image_overlaps(d, s)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + kernel_width = compute_kernel_size(stdDeviationX); + kernel_height = compute_kernel_size(stdDeviationY); + kernel_size = kernel_width * kernel_height; + kernel = malloc(sizeof(VGfloat)*kernel_size); + compute_gaussian_kernel(kernel, kernel_width, kernel_height, + stdDeviationX, stdDeviationY); + + buffer_len = 8 + 2 * 4 * kernel_size; + buffer = (VGfloat*)malloc(buffer_len * sizeof(VGfloat)); + + buffer[0] = 0.f; + buffer[1] = 1.f; + buffer[2] = 2.f; /*unused*/ + buffer[3] = 4.f; /*unused*/ + + buffer[4] = kernel_width * kernel_height; + buffer[5] = 1.f;/*scale*/ + buffer[6] = 0.f;/*bias*/ + buffer[7] = 0.f; + + idx = 8; + for (j = 0; j < kernel_height; ++j) { + for (i = 0; i < kernel_width; ++i) { + VGint index = j * kernel_width + i; + VGfloat x, y; + + x = texture_offset(s->width, kernel_width, i, kernel_width/2); + y = texture_offset(s->height, kernel_height, j, kernel_height/2); + + buffer[idx + index*4 + 0] = x; + buffer[idx + index*4 + 1] = y; + buffer[idx + index*4 + 2] = 0.f; + buffer[idx + index*4 + 3] = 0.f; + } + } + idx += kernel_size * 4; + + for (j = 0; j < kernel_height; ++j) { + for (i = 0; i < kernel_width; ++i) { + /* transpose the kernel */ + VGint index = j * kernel_width + i; + VGint kindex = (kernel_width - i - 1) * kernel_height + (kernel_height - j - 1); + buffer[idx + index*4 + 0] = kernel[kindex]; + buffer[idx + index*4 + 1] = kernel[kindex]; + buffer[idx + index*4 + 2] = kernel[kindex]; + buffer[idx + index*4 + 3] = kernel[kindex]; + } + } + + info.dst = d; + info.src = s; + info.setup_shader = &setup_convolution; + info.user_data = (void*)(long)(buffer_len/4); + info.const_buffer = buffer; + info.const_buffer_len = buffer_len * sizeof(VGfloat); + info.tiling_mode = tilingMode; + info.extra_texture = 0; + execute_filter(ctx, &info); + + free(buffer); + free(kernel); +} + +void vgLookup(VGImage dst, VGImage src, + const VGubyte * redLUT, + const VGubyte * greenLUT, + const VGubyte * blueLUT, + const VGubyte * alphaLUT, + VGboolean outputLinear, + VGboolean outputPremultiplied) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_image *d, *s; + VGuint color_data[256]; + VGint i; + struct pipe_texture *lut_texture; + VGfloat buffer[4]; + struct filter_info info; + + if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + if (!redLUT || !greenLUT || !blueLUT || !alphaLUT) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + d = (struct vg_image*)dst; + s = (struct vg_image*)src; + + if (vg_image_overlaps(d, s)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + for (i = 0; i < 256; ++i) { + color_data[i] = blueLUT[i] << 24 | greenLUT[i] << 16 | + redLUT[i] << 8 | alphaLUT[i]; + } + lut_texture = create_texture_1d(ctx, color_data, 255); + + buffer[0] = 0.f; + buffer[1] = 0.f; + buffer[2] = 1.f; + buffer[3] = 1.f; + + info.dst = d; + info.src = s; + info.setup_shader = &setup_lookup; + info.user_data = NULL; + info.const_buffer = buffer; + info.const_buffer_len = 4 * sizeof(VGfloat); + info.tiling_mode = VG_TILE_PAD; + info.extra_texture = lut_texture; + + execute_filter(ctx, &info); + + pipe_texture_reference(&lut_texture, NULL); +} + +void vgLookupSingle(VGImage dst, VGImage src, + const VGuint * lookupTable, + VGImageChannel sourceChannel, + VGboolean outputLinear, + VGboolean outputPremultiplied) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_image *d, *s; + struct pipe_texture *lut_texture; + VGfloat buffer[4]; + struct filter_info info; + VGuint color_data[256]; + VGint i; + + if (dst == VG_INVALID_HANDLE || src == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + if (!lookupTable || !is_aligned(lookupTable)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + if (sourceChannel != VG_RED && sourceChannel != VG_GREEN && + sourceChannel != VG_BLUE && sourceChannel != VG_ALPHA) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + d = (struct vg_image*)dst; + s = (struct vg_image*)src; + + if (vg_image_overlaps(d, s)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + for (i = 0; i < 256; ++i) { + VGuint rgba = lookupTable[i]; + VGubyte blue, green, red, alpha; + red = (rgba & 0xff000000)>>24; + green = (rgba & 0x00ff0000)>>16; + blue = (rgba & 0x0000ff00)>> 8; + alpha = (rgba & 0x000000ff)>> 0; + color_data[i] = blue << 24 | green << 16 | + red << 8 | alpha; + } + lut_texture = create_texture_1d(ctx, color_data, 256); + + buffer[0] = 0.f; + buffer[1] = 0.f; + buffer[2] = 1.f; + buffer[3] = 1.f; + + info.dst = d; + info.src = s; + info.setup_shader = &setup_lookup_single; + info.user_data = (void*)sourceChannel; + info.const_buffer = buffer; + info.const_buffer_len = 4 * sizeof(VGfloat); + info.tiling_mode = VG_TILE_PAD; + info.extra_texture = lut_texture; + + execute_filter(ctx, &info); + + pipe_texture_reference(&lut_texture, NULL); +} diff --git a/src/gallium/state_trackers/vega/api_images.c b/src/gallium/state_trackers/vega/api_images.c new file mode 100644 index 00000000000..c437553bc23 --- /dev/null +++ b/src/gallium/state_trackers/vega/api_images.c @@ -0,0 +1,489 @@ +/************************************************************************** + * + * 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 "image.h" + +#include "VG/openvg.h" + +#include "vg_context.h" +#include "vg_translate.h" +#include "api_consts.h" +#include "image.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "pipe/p_inlines.h" +#include "util/u_blit.h" +#include "util/u_tile.h" +#include "util/u_memory.h" + +static INLINE VGboolean supported_image_format(VGImageFormat format) +{ + switch(format) { + case VG_sRGBX_8888: + case VG_sRGBA_8888: + case VG_sRGBA_8888_PRE: + case VG_sRGB_565: + case VG_sRGBA_5551: + case VG_sRGBA_4444: + case VG_sL_8: + case VG_lRGBX_8888: + case VG_lRGBA_8888: + case VG_lRGBA_8888_PRE: + case VG_lL_8: + case VG_A_8: + case VG_BW_1: +#ifdef OPENVG_VERSION_1_1 + case VG_A_1: + case VG_A_4: +#endif + case VG_sXRGB_8888: + case VG_sARGB_8888: + case VG_sARGB_8888_PRE: + case VG_sARGB_1555: + case VG_sARGB_4444: + case VG_lXRGB_8888: + case VG_lARGB_8888: + case VG_lARGB_8888_PRE: + case VG_sBGRX_8888: + case VG_sBGRA_8888: + case VG_sBGRA_8888_PRE: + case VG_sBGR_565: + case VG_sBGRA_5551: + case VG_sBGRA_4444: + case VG_lBGRX_8888: + case VG_lBGRA_8888: + case VG_lBGRA_8888_PRE: + case VG_sXBGR_8888: + case VG_sABGR_8888: + case VG_sABGR_8888_PRE: + case VG_sABGR_1555: + case VG_sABGR_4444: + case VG_lXBGR_8888: + case VG_lABGR_8888: + case VG_lABGR_8888_PRE: + return VG_TRUE; + default: + return VG_FALSE; + } + return VG_FALSE; +} + +VGImage vgCreateImage(VGImageFormat format, + VGint width, VGint height, + VGbitfield allowedQuality) +{ + struct vg_context *ctx = vg_current_context(); + + if (!supported_image_format(format)) { + vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); + return VG_INVALID_HANDLE; + } + if (width <= 0 || height <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return VG_INVALID_HANDLE; + } + if (width > vgGeti(VG_MAX_IMAGE_WIDTH) || + height > vgGeti(VG_MAX_IMAGE_HEIGHT)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return VG_INVALID_HANDLE; + } + if (width * height > vgGeti(VG_MAX_IMAGE_PIXELS)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return VG_INVALID_HANDLE; + } + + if (!(allowedQuality & ((VG_IMAGE_QUALITY_NONANTIALIASED | + VG_IMAGE_QUALITY_FASTER | + VG_IMAGE_QUALITY_BETTER)))) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return VG_INVALID_HANDLE; + } + + return (VGImage)image_create(format, width, height); +} + +void vgDestroyImage(VGImage image) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_image *img = (struct vg_image *)image; + + if (image == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (!vg_object_is_valid((void*)image, VG_OBJECT_IMAGE)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + image_destroy(img); +} + +void vgClearImage(VGImage image, + VGint x, VGint y, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_image *img; + + if (image == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (width <= 0 || height <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + img = (struct vg_image*)image; + + if (x + width < 0 || y + height < 0) + return; + + image_clear(img, x, y, width, height); + +} + +void vgImageSubData(VGImage image, + const void * data, + VGint dataStride, + VGImageFormat dataFormat, + VGint x, VGint y, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_image *img; + + if (image == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (!supported_image_format(dataFormat)) { + vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); + return; + } + if (width <= 0 || height <= 0 || !data || !is_aligned(data)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + img = (struct vg_image*)(image); + image_sub_data(img, data, dataStride, dataFormat, + x, y, width, height); +} + +void vgGetImageSubData(VGImage image, + void * data, + VGint dataStride, + VGImageFormat dataFormat, + VGint x, VGint y, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_image *img; + + if (image == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (!supported_image_format(dataFormat)) { + vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); + return; + } + if (width <= 0 || height <= 0 || !data || !is_aligned(data)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + img = (struct vg_image*)image; + image_get_sub_data(img, data, dataStride, dataFormat, + x, y, width, height); +} + +VGImage vgChildImage(VGImage parent, + VGint x, VGint y, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_image *p; + + if (parent == VG_INVALID_HANDLE || + !vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, (void*)parent) || + !vg_object_is_valid((void*)parent, VG_OBJECT_IMAGE)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return VG_INVALID_HANDLE; + } + if (width <= 0 || height <= 0 || x < 0 || y < 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return VG_INVALID_HANDLE; + } + p = (struct vg_image *)parent; + if (x > p->width || y > p->height) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return VG_INVALID_HANDLE; + } + if (x + width > p->width || y + height > p->height) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return VG_INVALID_HANDLE; + } + + return (VGImage)image_child_image(p, x, y, width, height); +} + +VGImage vgGetParent(VGImage image) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_image *img; + + if (image == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return VG_INVALID_HANDLE; + } + + img = (struct vg_image*)image; + if (img->parent) + return (VGImage)img->parent; + else + return image; +} + +void vgCopyImage(VGImage dst, VGint dx, VGint dy, + VGImage src, VGint sx, VGint sy, + VGint width, VGint height, + VGboolean dither) +{ + struct vg_context *ctx = vg_current_context(); + + if (src == VG_INVALID_HANDLE || dst == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + if (width <= 0 || height <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + vg_validate_state(ctx); + image_copy((struct vg_image*)dst, dx, dy, + (struct vg_image*)src, sx, sy, + width, height, dither); +} + +void vgDrawImage(VGImage image) +{ + struct vg_context *ctx = vg_current_context(); + + if (!ctx) + return; + + if (image == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + vg_validate_state(ctx); + image_draw((struct vg_image*)image); +} + +void vgSetPixels(VGint dx, VGint dy, + VGImage src, VGint sx, VGint sy, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + + vg_validate_state(ctx); + + if (src == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (width <= 0 || height <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + image_set_pixels(dx, dy, (struct vg_image*)src, sx, sy, width, + height); +} + +void vgGetPixels(VGImage dst, VGint dx, VGint dy, + VGint sx, VGint sy, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_image *img; + + if (dst == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (width <= 0 || height <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + img = (struct vg_image*)dst; + + image_get_pixels(img, dx, dy, + sx, sy, width, height); +} + +void vgWritePixels(const void * data, VGint dataStride, + VGImageFormat dataFormat, + VGint dx, VGint dy, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_context *pipe = ctx->pipe; + + if (!supported_image_format(dataFormat)) { + vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); + return; + } + if (!data || !is_aligned(data)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + if (width <= 0 || height <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + vg_validate_state(ctx); + { + struct vg_image *img = image_create(dataFormat, width, height); + image_sub_data(img, data, dataStride, dataFormat, 0, 0, + width, height); +#if 0 + struct matrix *matrix = &ctx->state.vg.image_user_to_surface_matrix; + matrix_translate(matrix, dx, dy); + image_draw(img); + matrix_translate(matrix, -dx, -dy); +#else + /* this looks like a better approach */ + image_set_pixels(dx, dy, img, 0, 0, width, height); +#endif + image_destroy(img); + } + /* make sure rendering has completed */ + pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); +} + +void vgReadPixels(void * data, VGint dataStride, + VGImageFormat dataFormat, + VGint sx, VGint sy, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_context *pipe = ctx->pipe; + struct pipe_screen *screen = pipe->screen; + + struct st_framebuffer *stfb = ctx->draw_buffer; + struct st_renderbuffer *strb = stfb->strb; + struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; + + VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4]; + VGfloat *df = (VGfloat*)temp; + VGint y = (fb->height - sy) - 1, yStep = -1; + VGint i; + VGubyte *dst = (VGubyte *)data; + VGint xoffset = 0, yoffset = 0; + + if (!supported_image_format(dataFormat)) { + vg_set_error(ctx, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR); + return; + } + if (!data || !is_aligned(data)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + if (width <= 0 || height <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + /* make sure rendering has completed */ + pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); + if (sx < 0) { + xoffset = -sx; + xoffset *= _vega_size_for_format(dataFormat); + width += sx; + sx = 0; + } + if (sy < 0) { + yoffset = -sy; + height += sy; + sy = 0; + y = (fb->height - sy) - 1; + yoffset *= dataStride; + } + + { + struct pipe_transfer *transfer; + + transfer = screen->get_tex_transfer(screen, strb->texture, 0, 0, 0, + PIPE_TRANSFER_READ, + 0, 0, width, height); + + /* Do a row at a time to flip image data vertically */ + for (i = 0; i < height; i++) { +#if 0 + debug_printf("%d-%d == %d\n", sy, height, y); +#endif + pipe_get_tile_rgba(transfer, sx, y, width, 1, df); + y += yStep; + _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, + dst + yoffset + xoffset); + dst += dataStride; + } + + screen->tex_transfer_destroy(transfer); + } +} + +void vgCopyPixels(VGint dx, VGint dy, + VGint sx, VGint sy, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; + struct st_renderbuffer *strb = ctx->draw_buffer->strb; + + if (width <= 0 || height <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + /* do nothing if we copy from outside the fb */ + if (dx >= (VGint)fb->width || dy >= (VGint)fb->height || + sx >= (VGint)fb->width || sy >= (VGint)fb->height) + return; + + vg_validate_state(ctx); + /* make sure rendering has completed */ + vgFinish(); + + vg_copy_surface(ctx, strb->surface, dx, dy, + strb->surface, sx, sy, width, height); +} diff --git a/src/gallium/state_trackers/vega/api_masks.c b/src/gallium/state_trackers/vega/api_masks.c new file mode 100644 index 00000000000..4f9f3dae173 --- /dev/null +++ b/src/gallium/state_trackers/vega/api_masks.c @@ -0,0 +1,373 @@ +/************************************************************************** + * + * 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 "VG/openvg.h" + +#include "mask.h" +#include "renderer.h" + +#include "vg_context.h" +#include "pipe/p_context.h" +#include "pipe/p_inlines.h" +#include "pipe/internal/p_winsys_screen.h" /* for winsys->update_buffer */ + +#include "util/u_pack_color.h" +#include "util/u_draw_quad.h" +#include "util/u_memory.h" + + +#define DISABLE_1_1_MASKING 1 + +/** + * Draw a screen-aligned quadrilateral. + * Coords are window coords with y=0=bottom. These coords will be transformed + * by the vertex shader and viewport transform. + */ +static void +draw_clear_quad(struct vg_context *st, + float x0, float y0, float x1, float y1, float z, + const VGfloat color[4]) +{ + struct pipe_context *pipe = st->pipe; + struct pipe_buffer *buf; + VGuint i; + + /* positions */ + st->clear.vertices[0][0][0] = x0; + st->clear.vertices[0][0][1] = y0; + + st->clear.vertices[1][0][0] = x1; + st->clear.vertices[1][0][1] = y0; + + st->clear.vertices[2][0][0] = x1; + st->clear.vertices[2][0][1] = y1; + + st->clear.vertices[3][0][0] = x0; + st->clear.vertices[3][0][1] = y1; + + /* same for all verts: */ + for (i = 0; i < 4; i++) { + st->clear.vertices[i][0][2] = z; + st->clear.vertices[i][0][3] = 1.0; + st->clear.vertices[i][1][0] = color[0]; + st->clear.vertices[i][1][1] = color[1]; + st->clear.vertices[i][1][2] = color[2]; + st->clear.vertices[i][1][3] = color[3]; + } + + + /* put vertex data into vbuf */ + buf = pipe_user_buffer_create(pipe->screen, + st->clear.vertices, + sizeof(st->clear.vertices)); + + + /* draw */ + if (buf) { + util_draw_vertex_buffer(pipe, buf, 0, + PIPE_PRIM_TRIANGLE_FAN, + 4, /* verts */ + 2); /* attribs/vert */ + + pipe_buffer_reference(&buf, NULL); + } +} + +/** + * Do vgClear by drawing a quadrilateral. + */ +static void +clear_with_quad(struct vg_context *st, float x0, float y0, + float width, float height, const VGfloat clear_color[4]) +{ + VGfloat x1, y1; + + vg_validate_state(st); + + x1 = x0 + width; + y1 = y0 + height; + + /* + printf("%s %f,%f %f,%f\n", __FUNCTION__, + x0, y0, + x1, y1); + */ + + if (st->pipe->winsys && st->pipe->winsys->update_buffer) + st->pipe->winsys->update_buffer( st->pipe->winsys, + st->pipe->priv ); + + cso_save_blend(st->cso_context); + cso_save_rasterizer(st->cso_context); + cso_save_fragment_shader(st->cso_context); + cso_save_vertex_shader(st->cso_context); + + /* blend state: RGBA masking */ + { + struct pipe_blend_state blend; + memset(&blend, 0, sizeof(blend)); + blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.colormask |= PIPE_MASK_R; + blend.colormask |= PIPE_MASK_G; + blend.colormask |= PIPE_MASK_B; + blend.colormask |= PIPE_MASK_A; + cso_set_blend(st->cso_context, &blend); + } + + cso_set_rasterizer(st->cso_context, &st->clear.raster); + + cso_set_fragment_shader_handle(st->cso_context, st->clear.fs); + cso_set_vertex_shader_handle(st->cso_context, vg_clear_vs(st)); + + /* draw quad matching scissor rect (XXX verify coord round-off) */ + draw_clear_quad(st, x0, y0, x1, y1, 0, clear_color); + + /* Restore pipe state */ + cso_restore_blend(st->cso_context); + cso_restore_rasterizer(st->cso_context); + cso_restore_fragment_shader(st->cso_context); + cso_restore_vertex_shader(st->cso_context); +} + + +void vgMask(VGHandle mask, VGMaskOperation operation, + VGint x, VGint y, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + + if (width <=0 || height <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + if (operation < VG_CLEAR_MASK || operation > VG_SUBTRACT_MASK) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + + vg_validate_state(ctx); + + if (operation == VG_CLEAR_MASK) { + mask_fill(x, y, width, height, 0.f); + } else if (operation == VG_FILL_MASK) { + mask_fill(x, y, width, height, 1.f); + } else if (vg_object_is_valid((void*)mask, VG_OBJECT_IMAGE)) { + struct vg_image *image = (struct vg_image *)mask; + mask_using_image(image, operation, x, y, width, height); + } else if (vg_object_is_valid((void*)mask, VG_OBJECT_MASK)) { +#if DISABLE_1_1_MASKING + return; +#else + struct vg_mask_layer *layer = (struct vg_mask_layer *)mask; + mask_using_layer(layer, operation, x, y, width, height); +#endif + } else { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + } +} + +void vgClear(VGint x, VGint y, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_framebuffer_state *fb; + + if (width <= 0 || height <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + vg_validate_state(ctx); +#if 0 + debug_printf("Clear [%d, %d, %d, %d] with [%f, %f, %f, %f]\n", + x, y, width, height, + ctx->state.vg.clear_color[0], + ctx->state.vg.clear_color[1], + ctx->state.vg.clear_color[2], + ctx->state.vg.clear_color[3]); +#endif + + fb = &ctx->state.g3d.fb; + /* check for a whole surface clear */ + if (!ctx->state.vg.scissoring && + (x == 0 && y == 0 && width == fb->width && height == fb->height)) { + ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL, + ctx->state.vg.clear_color, 1., 0); + } else { + clear_with_quad(ctx, x, y, width, height, ctx->state.vg.clear_color); + } +} + + +#ifdef OPENVG_VERSION_1_1 + + +void vgRenderToMask(VGPath path, + VGbitfield paintModes, + VGMaskOperation operation) +{ + struct vg_context *ctx = vg_current_context(); + + if (path == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (!paintModes || (paintModes&(~(VG_STROKE_PATH|VG_FILL_PATH)))) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + if (operation < VG_CLEAR_MASK || + operation > VG_SUBTRACT_MASK) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + if (!vg_object_is_valid((void*)path, VG_OBJECT_PATH)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + +#if DISABLE_1_1_MASKING + return; +#endif + + vg_validate_state(ctx); + + mask_render_to((struct path *)path, paintModes, operation); +} + +VGMaskLayer vgCreateMaskLayer(VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + + if (width <= 0 || height <= 0 || + width > vgGeti(VG_MAX_IMAGE_WIDTH) || + height > vgGeti(VG_MAX_IMAGE_HEIGHT)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return VG_INVALID_HANDLE; + } + + return (VGMaskLayer)mask_layer_create(width, height); +} + +void vgDestroyMaskLayer(VGMaskLayer maskLayer) +{ + struct vg_mask_layer *mask = 0; + struct vg_context *ctx = vg_current_context(); + + if (maskLayer == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (!vg_object_is_valid((void*)maskLayer, VG_OBJECT_MASK)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + mask = (struct vg_mask_layer *)maskLayer; + mask_layer_destroy(mask); +} + +void vgFillMaskLayer(VGMaskLayer maskLayer, + VGint x, VGint y, + VGint width, VGint height, + VGfloat value) +{ + struct vg_mask_layer *mask = 0; + struct vg_context *ctx = vg_current_context(); + + if (maskLayer == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + if (value < 0 || value > 1) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + if (width <= 0 || height <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + if (x < 0 || y < 0 || (x + width) < 0 || (y + height) < 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + if (!vg_object_is_valid((void*)maskLayer, VG_OBJECT_MASK)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + mask = (struct vg_mask_layer*)maskLayer; + + if (x + width > mask_layer_width(mask) || + y + height > mask_layer_height(mask)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + +#if DISABLE_1_1_MASKING + return; +#endif + mask_layer_fill(mask, x, y, width, height, value); +} + +void vgCopyMask(VGMaskLayer maskLayer, + VGint sx, VGint sy, + VGint dx, VGint dy, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_mask_layer *mask = 0; + + if (maskLayer == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (width <= 0 || height <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + if (!vg_object_is_valid((void*)maskLayer, VG_OBJECT_MASK)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + +#if DISABLE_1_1_MASKING + return; +#endif + + mask = (struct vg_mask_layer*)maskLayer; + mask_copy(mask, sx, sy, dx, dy, width, height); +} + +#endif diff --git a/src/gallium/state_trackers/vega/api_misc.c b/src/gallium/state_trackers/vega/api_misc.c new file mode 100644 index 00000000000..78ba0bc1103 --- /dev/null +++ b/src/gallium/state_trackers/vega/api_misc.c @@ -0,0 +1,83 @@ +/************************************************************************** + * + * 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 "VG/openvg.h" + +#include "vg_context.h" + +/* Hardware Queries */ +VGHardwareQueryResult vgHardwareQuery(VGHardwareQueryType key, + VGint setting) +{ + struct vg_context *ctx = vg_current_context(); + + if (key < VG_IMAGE_FORMAT_QUERY || + key > VG_PATH_DATATYPE_QUERY) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return VG_HARDWARE_UNACCELERATED; + } + + if (key == VG_IMAGE_FORMAT_QUERY) { + if (setting < VG_sRGBX_8888 || + setting > VG_lABGR_8888_PRE) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return VG_HARDWARE_UNACCELERATED; + } + } else if (key == VG_PATH_DATATYPE_QUERY) { + if (setting < VG_PATH_DATATYPE_S_8 || + setting > VG_PATH_DATATYPE_F) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return VG_HARDWARE_UNACCELERATED; + } + } + /* we're supposed to accelerate everything */ + return VG_HARDWARE_ACCELERATED; +} + +/* Renderer and Extension Information */ +const VGubyte *vgGetString(VGStringID name) +{ + struct vg_context *ctx = vg_current_context(); + static const VGubyte *vendor = (VGubyte *)"Tungsten Graphics, Inc"; + static const VGubyte *renderer = (VGubyte *)"Vega OpenVG 1.0"; + static const VGubyte *version = (VGubyte *)"1.0"; + + if (!ctx) + return NULL; + + switch(name) { + case VG_VENDOR: + return vendor; + case VG_RENDERER: + return renderer; + case VG_VERSION: + return version; + case VG_EXTENSIONS: + return NULL; + default: + return NULL; + } +} diff --git a/src/gallium/state_trackers/vega/api_paint.c b/src/gallium/state_trackers/vega/api_paint.c new file mode 100644 index 00000000000..dd3ac5bdb09 --- /dev/null +++ b/src/gallium/state_trackers/vega/api_paint.c @@ -0,0 +1,166 @@ +/************************************************************************** + * + * 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 "VG/openvg.h" + +#include "vg_context.h" +#include "paint.h" +#include "image.h" + +VGPaint vgCreatePaint(void) +{ + return (VGPaint) paint_create(vg_current_context()); +} + +void vgDestroyPaint(VGPaint p) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_paint *paint; + + if (p == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + paint = (struct vg_paint *)p; + paint_destroy(paint); +} + +void vgSetPaint(VGPaint paint, VGbitfield paintModes) +{ + struct vg_context *ctx = vg_current_context(); + + if (paint == VG_INVALID_HANDLE) { + /* restore the default */ + paint = (VGPaint)ctx->default_paint; + } else if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + if (!(paintModes & ((VG_FILL_PATH|VG_STROKE_PATH)))) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + if (paintModes & VG_FILL_PATH) { + ctx->state.vg.fill_paint = (struct vg_paint *)paint; + } + if (paintModes & VG_STROKE_PATH) { + ctx->state.vg.stroke_paint = (struct vg_paint *)paint; + } +} + +VGPaint vgGetPaint(VGPaintMode paintMode) +{ + struct vg_context *ctx = vg_current_context(); + VGPaint paint = VG_INVALID_HANDLE; + + if (paintMode < VG_STROKE_PATH || paintMode > VG_FILL_PATH) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return VG_INVALID_HANDLE; + } + + if (paintMode == VG_FILL_PATH) + paint = (VGPaint)ctx->state.vg.fill_paint; + else if (paintMode == VG_STROKE_PATH) + paint = (VGPaint)ctx->state.vg.stroke_paint; + + if (paint == (VGPaint)ctx->default_paint) + paint = VG_INVALID_HANDLE; + + return paint; +} + +void vgSetColor(VGPaint paint, VGuint rgba) +{ + struct vg_context *ctx = vg_current_context(); + + if (paint == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + { + struct vg_paint *p = (struct vg_paint *)paint; + paint_set_colori(p, rgba); + } +} + +VGuint vgGetColor(VGPaint paint) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_paint *p; + VGuint rgba = 0; + + if (paint == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return rgba; + } + + if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return rgba; + } + p = (struct vg_paint *)paint; + + return paint_colori(p); +} + +void vgPaintPattern(VGPaint paint, VGImage pattern) +{ + struct vg_context *ctx = vg_current_context(); + + if (paint == VG_INVALID_HANDLE || + !vg_context_is_object_valid(ctx, VG_OBJECT_PAINT, (void *)paint)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + if (pattern == VG_INVALID_HANDLE) { + paint_set_type((struct vg_paint*)paint, VG_PAINT_TYPE_COLOR); + return; + } + + if (!vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, (void *)pattern)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + + if (!vg_object_is_valid((void*)paint, VG_OBJECT_PAINT) || + !vg_object_is_valid((void*)pattern, VG_OBJECT_IMAGE)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + paint_set_pattern((struct vg_paint*)paint, + (struct vg_image*)pattern); +} + diff --git a/src/gallium/state_trackers/vega/api_params.c b/src/gallium/state_trackers/vega/api_params.c new file mode 100644 index 00000000000..db77fd9cb05 --- /dev/null +++ b/src/gallium/state_trackers/vega/api_params.c @@ -0,0 +1,1673 @@ +/************************************************************************** + * + * 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 "VG/openvg.h" + +#include "vg_context.h" +#include "paint.h" +#include "path.h" +#include "image.h" +#include "matrix.h" +#include "api_consts.h" + +#include "pipe/p_compiler.h" +#include "util/u_pointer.h" +#include "util/u_math.h" + +#include <math.h> + +static INLINE struct vg_state *current_state() +{ + struct vg_context *ctx = vg_current_context(); + if (!ctx) + return 0; + else + return &ctx->state.vg; +} + +static INLINE VGboolean count_in_bounds(VGParamType type, VGint count) +{ + if (count < 0) + return VG_FALSE; + + if (type == VG_SCISSOR_RECTS) + return (!(count % 4) && (count >= 0 || count <= VEGA_MAX_SCISSOR_RECTS * 4)); + else if (type == VG_STROKE_DASH_PATTERN) { + return count <= VEGA_MAX_DASH_COUNT; + } else { + VGint real_count = vgGetVectorSize(type); + return count == real_count; + } +} + +void vgSetf (VGParamType type, VGfloat value) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_state *state = current_state(); + VGErrorCode error = VG_NO_ERROR; + + switch(type) { + case VG_MATRIX_MODE: + case VG_FILL_RULE: + case VG_IMAGE_QUALITY: + case VG_RENDERING_QUALITY: + case VG_BLEND_MODE: + case VG_IMAGE_MODE: +#ifdef OPENVG_VERSION_1_1 + case VG_COLOR_TRANSFORM: +#endif + case VG_STROKE_CAP_STYLE: + case VG_STROKE_JOIN_STYLE: + case VG_STROKE_DASH_PHASE_RESET: + case VG_MASKING: + case VG_SCISSORING: + case VG_PIXEL_LAYOUT: + case VG_SCREEN_LAYOUT: + case VG_FILTER_FORMAT_LINEAR: + case VG_FILTER_FORMAT_PREMULTIPLIED: + case VG_FILTER_CHANNEL_MASK: + + case VG_MAX_SCISSOR_RECTS: + case VG_MAX_DASH_COUNT: + case VG_MAX_KERNEL_SIZE: + case VG_MAX_SEPARABLE_KERNEL_SIZE: + case VG_MAX_COLOR_RAMP_STOPS: + case VG_MAX_IMAGE_WIDTH: + case VG_MAX_IMAGE_HEIGHT: + case VG_MAX_IMAGE_PIXELS: + case VG_MAX_IMAGE_BYTES: + case VG_MAX_GAUSSIAN_STD_DEVIATION: + case VG_MAX_FLOAT: + vgSeti(type, floor(value)); + return; + break; + case VG_STROKE_LINE_WIDTH: + state->stroke.line_width.f = value; + state->stroke.line_width.i = float_to_int_floor(*((VGuint*)(&value))); + break; + case VG_STROKE_MITER_LIMIT: + state->stroke.miter_limit.f = value; + state->stroke.miter_limit.i = float_to_int_floor(*((VGuint*)(&value))); + break; + case VG_STROKE_DASH_PHASE: + state->stroke.dash_phase.f = value; + state->stroke.dash_phase.i = float_to_int_floor(*((VGuint*)(&value))); + break; + default: + error = VG_ILLEGAL_ARGUMENT_ERROR; + break; + } + vg_set_error(ctx, error); +} + +void vgSeti (VGParamType type, VGint value) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_state *state = current_state(); + VGErrorCode error = VG_NO_ERROR; + + switch(type) { + case VG_MATRIX_MODE: + if (value < VG_MATRIX_PATH_USER_TO_SURFACE || +#ifdef OPENVG_VERSION_1_1 + value > VG_MATRIX_GLYPH_USER_TO_SURFACE) +#else + value > VG_MATRIX_STROKE_PAINT_TO_USER) +#endif + error = VG_ILLEGAL_ARGUMENT_ERROR; + else + state->matrix_mode = value; + break; + case VG_FILL_RULE: + if (value < VG_EVEN_ODD || + value > VG_NON_ZERO) + error = VG_ILLEGAL_ARGUMENT_ERROR; + else + state->fill_rule = value; + break; + case VG_IMAGE_QUALITY: + state->image_quality = value; + break; + case VG_RENDERING_QUALITY: + if (value < VG_RENDERING_QUALITY_NONANTIALIASED || + value > VG_RENDERING_QUALITY_BETTER) + error = VG_ILLEGAL_ARGUMENT_ERROR; + else + state->rendering_quality = value; + break; + case VG_BLEND_MODE: + if (value < VG_BLEND_SRC || + value > VG_BLEND_ADDITIVE) + error = VG_ILLEGAL_ARGUMENT_ERROR; + else { + ctx->state.dirty |= BLEND_DIRTY; + state->blend_mode = value; + } + break; + case VG_IMAGE_MODE: + if (value < VG_DRAW_IMAGE_NORMAL || + value > VG_DRAW_IMAGE_STENCIL) + error = VG_ILLEGAL_ARGUMENT_ERROR; + else + state->image_mode = value; +#ifdef OPENVG_VERSION_1_1 + case VG_COLOR_TRANSFORM: + state->color_transform = value; +#endif + break; + case VG_STROKE_LINE_WIDTH: + state->stroke.line_width.f = value; + state->stroke.line_width.i = value; + break; + case VG_STROKE_CAP_STYLE: + if (value < VG_CAP_BUTT || + value > VG_CAP_SQUARE) + error = VG_ILLEGAL_ARGUMENT_ERROR; + else + state->stroke.cap_style = value; + break; + case VG_STROKE_JOIN_STYLE: + if (value < VG_JOIN_MITER || + value > VG_JOIN_BEVEL) + error = VG_ILLEGAL_ARGUMENT_ERROR; + else + state->stroke.join_style = value; + break; + case VG_STROKE_MITER_LIMIT: + state->stroke.miter_limit.f = value; + state->stroke.miter_limit.i = value; + break; + case VG_STROKE_DASH_PHASE: + state->stroke.dash_phase.f = value; + state->stroke.dash_phase.i = value; + break; + case VG_STROKE_DASH_PHASE_RESET: + state->stroke.dash_phase_reset = value; + break; + case VG_MASKING: + state->masking = value; + break; + case VG_SCISSORING: + state->scissoring = value; + ctx->state.dirty |= DEPTH_STENCIL_DIRTY; + break; + case VG_PIXEL_LAYOUT: + if (value < VG_PIXEL_LAYOUT_UNKNOWN || + value > VG_PIXEL_LAYOUT_BGR_HORIZONTAL) + error = VG_ILLEGAL_ARGUMENT_ERROR; + else + state->pixel_layout = value; + break; + case VG_SCREEN_LAYOUT: + /* read only ignore */ + break; + case VG_FILTER_FORMAT_LINEAR: + state->filter_format_linear = value; + break; + case VG_FILTER_FORMAT_PREMULTIPLIED: + state->filter_format_premultiplied = value; + break; + case VG_FILTER_CHANNEL_MASK: + state->filter_channel_mask = value; + break; + + case VG_MAX_SCISSOR_RECTS: + case VG_MAX_DASH_COUNT: + case VG_MAX_KERNEL_SIZE: + case VG_MAX_SEPARABLE_KERNEL_SIZE: + case VG_MAX_COLOR_RAMP_STOPS: + case VG_MAX_IMAGE_WIDTH: + case VG_MAX_IMAGE_HEIGHT: + case VG_MAX_IMAGE_PIXELS: + case VG_MAX_IMAGE_BYTES: + case VG_MAX_GAUSSIAN_STD_DEVIATION: + case VG_MAX_FLOAT: + /* read only ignore */ + break; + default: + error = VG_ILLEGAL_ARGUMENT_ERROR; + break; + } + vg_set_error(ctx, error); +} + +void vgSetfv(VGParamType type, VGint count, + const VGfloat * values) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_state *state = current_state(); + VGErrorCode error = VG_NO_ERROR; + + if ((count && !values) || !count_in_bounds(type, count) || !is_aligned(values)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + switch(type) { + case VG_MATRIX_MODE: + case VG_FILL_RULE: + case VG_IMAGE_QUALITY: + case VG_RENDERING_QUALITY: + case VG_BLEND_MODE: + case VG_IMAGE_MODE: +#ifdef OPENVG_VERSION_1_1 + case VG_COLOR_TRANSFORM: +#endif + case VG_STROKE_CAP_STYLE: + case VG_STROKE_JOIN_STYLE: + case VG_STROKE_DASH_PHASE_RESET: + case VG_MASKING: + case VG_SCISSORING: + case VG_PIXEL_LAYOUT: + case VG_SCREEN_LAYOUT: + case VG_FILTER_FORMAT_LINEAR: + case VG_FILTER_FORMAT_PREMULTIPLIED: + case VG_FILTER_CHANNEL_MASK: + vgSeti(type, floor(values[0])); + return; + break; + case VG_SCISSOR_RECTS: { + VGint i; + VGuint *x = (VGuint*)values; + for (i = 0; i < count; ++i) { + state->scissor_rects[i].f = values[i]; + state->scissor_rects[i].i = float_to_int_floor(x[i]); + } + state->scissor_rects_num = count / 4; + ctx->state.dirty |= DEPTH_STENCIL_DIRTY; + } + break; +#ifdef OPENVG_VERSION_1_1 + case VG_COLOR_TRANSFORM_VALUES: { + VGint i; + for (i = 0; i < count; ++i) { + state->color_transform_values[i] = values[i]; + } + } + break; +#endif + case VG_STROKE_LINE_WIDTH: + state->stroke.line_width.f = values[0]; + state->stroke.line_width.i = float_to_int_floor(*((VGuint*)(values))); + break; + case VG_STROKE_MITER_LIMIT: + state->stroke.miter_limit.f = values[0]; + state->stroke.miter_limit.i = float_to_int_floor(*((VGuint*)(values))); + break; + case VG_STROKE_DASH_PATTERN: { + int i; + for (i = 0; i < count; ++i) { + state->stroke.dash_pattern[i].f = values[i]; + state->stroke.dash_pattern[i].i = + float_to_int_floor(*((VGuint*)(values + i))); + } + state->stroke.dash_pattern_num = count; + } + break; + case VG_STROKE_DASH_PHASE: + state->stroke.dash_phase.f = values[0]; + state->stroke.dash_phase.i = float_to_int_floor(*((VGuint*)(values))); + break; + case VG_TILE_FILL_COLOR: + state->tile_fill_color[0] = values[0]; + state->tile_fill_color[1] = values[1]; + state->tile_fill_color[2] = values[2]; + state->tile_fill_color[3] = values[3]; + + state->tile_fill_colori[0] = float_to_int_floor(*((VGuint*)(values + 0))); + state->tile_fill_colori[1] = float_to_int_floor(*((VGuint*)(values + 1))); + state->tile_fill_colori[2] = float_to_int_floor(*((VGuint*)(values + 2))); + state->tile_fill_colori[3] = float_to_int_floor(*((VGuint*)(values + 3))); + break; + case VG_CLEAR_COLOR: + state->clear_color[0] = values[0]; + state->clear_color[1] = values[1]; + state->clear_color[2] = values[2]; + state->clear_color[3] = values[3]; + + state->clear_colori[0] = float_to_int_floor(*((VGuint*)(values + 0))); + state->clear_colori[1] = float_to_int_floor(*((VGuint*)(values + 1))); + state->clear_colori[2] = float_to_int_floor(*((VGuint*)(values + 2))); + state->clear_colori[3] = float_to_int_floor(*((VGuint*)(values + 3))); + break; +#ifdef OPENVG_VERSION_1_1 + case VG_GLYPH_ORIGIN: + state->glyph_origin[0].f = values[0]; + state->glyph_origin[1].f = values[1]; + + state->glyph_origin[0].i = float_to_int_floor(*((VGuint*)(values + 0))); + state->glyph_origin[1].i = float_to_int_floor(*((VGuint*)(values + 1))); + break; +#endif + + case VG_MAX_SCISSOR_RECTS: + case VG_MAX_DASH_COUNT: + case VG_MAX_KERNEL_SIZE: + case VG_MAX_SEPARABLE_KERNEL_SIZE: + case VG_MAX_COLOR_RAMP_STOPS: + case VG_MAX_IMAGE_WIDTH: + case VG_MAX_IMAGE_HEIGHT: + case VG_MAX_IMAGE_PIXELS: + case VG_MAX_IMAGE_BYTES: + case VG_MAX_GAUSSIAN_STD_DEVIATION: + case VG_MAX_FLOAT: + break; + default: + error = VG_ILLEGAL_ARGUMENT_ERROR; + break; + } + vg_set_error(ctx, error); +} + +void vgSetiv(VGParamType type, VGint count, + const VGint * values) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_state *state = current_state(); + + if ((count && !values) || !count_in_bounds(type, count) || !is_aligned(values)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + switch(type) { + case VG_MATRIX_MODE: + case VG_FILL_RULE: + case VG_IMAGE_QUALITY: + case VG_RENDERING_QUALITY: + case VG_BLEND_MODE: + case VG_IMAGE_MODE: +#ifdef OPENVG_VERSION_1_1 + case VG_COLOR_TRANSFORM: +#endif + case VG_STROKE_CAP_STYLE: + case VG_STROKE_JOIN_STYLE: + case VG_STROKE_DASH_PHASE_RESET: + case VG_MASKING: + case VG_SCISSORING: + case VG_PIXEL_LAYOUT: + case VG_SCREEN_LAYOUT: + case VG_FILTER_FORMAT_LINEAR: + case VG_FILTER_FORMAT_PREMULTIPLIED: + case VG_FILTER_CHANNEL_MASK: + vgSeti(type, values[0]); + return; + break; + case VG_SCISSOR_RECTS: { + VGint i; + for (i = 0; i < count; ++i) { + state->scissor_rects[i].i = values[i]; + state->scissor_rects[i].f = values[i]; + } + state->scissor_rects_num = count / 4; + ctx->state.dirty |= DEPTH_STENCIL_DIRTY; + } + break; +#ifdef OPENVG_VERSION_1_1 + case VG_COLOR_TRANSFORM_VALUES: { + VGint i; + for (i = 0; i < count; ++i) { + state->color_transform_values[i] = values[i]; + } + } + break; +#endif + case VG_STROKE_LINE_WIDTH: + state->stroke.line_width.f = values[0]; + state->stroke.line_width.i = values[0]; + break; + case VG_STROKE_MITER_LIMIT: + state->stroke.miter_limit.f = values[0]; + state->stroke.miter_limit.i = values[0]; + break; + case VG_STROKE_DASH_PATTERN: { + int i; + for (i = 0; i < count; ++i) { + state->stroke.dash_pattern[i].f = values[i]; + state->stroke.dash_pattern[i].i = values[i]; + } + state->stroke.dash_pattern_num = count; + } + break; + case VG_STROKE_DASH_PHASE: + state->stroke.dash_phase.f = values[0]; + state->stroke.dash_phase.i = values[0]; + break; + case VG_TILE_FILL_COLOR: + state->tile_fill_color[0] = values[0]; + state->tile_fill_color[1] = values[1]; + state->tile_fill_color[2] = values[2]; + state->tile_fill_color[3] = values[3]; + + state->tile_fill_colori[0] = values[0]; + state->tile_fill_colori[1] = values[1]; + state->tile_fill_colori[2] = values[2]; + state->tile_fill_colori[3] = values[3]; + break; + case VG_CLEAR_COLOR: + state->clear_color[0] = values[0]; + state->clear_color[1] = values[1]; + state->clear_color[2] = values[2]; + state->clear_color[3] = values[3]; + + state->clear_colori[0] = values[0]; + state->clear_colori[1] = values[1]; + state->clear_colori[2] = values[2]; + state->clear_colori[3] = values[3]; + break; +#ifdef OPENVG_VERSION_1_1 + case VG_GLYPH_ORIGIN: + state->glyph_origin[0].f = values[0]; + state->glyph_origin[1].f = values[1]; + state->glyph_origin[0].i = values[0]; + state->glyph_origin[1].i = values[1]; + break; +#endif + + case VG_MAX_SCISSOR_RECTS: + case VG_MAX_DASH_COUNT: + case VG_MAX_KERNEL_SIZE: + case VG_MAX_SEPARABLE_KERNEL_SIZE: + case VG_MAX_COLOR_RAMP_STOPS: + case VG_MAX_IMAGE_WIDTH: + case VG_MAX_IMAGE_HEIGHT: + case VG_MAX_IMAGE_PIXELS: + case VG_MAX_IMAGE_BYTES: + case VG_MAX_GAUSSIAN_STD_DEVIATION: + case VG_MAX_FLOAT: + break; + + default: + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + break; + } +} + +VGfloat vgGetf(VGParamType type) +{ + struct vg_context *ctx = vg_current_context(); + const struct vg_state *state = current_state(); + VGErrorCode error = VG_NO_ERROR; + VGfloat value = 0.0f; + + switch(type) { + case VG_MATRIX_MODE: + case VG_FILL_RULE: + case VG_IMAGE_QUALITY: + case VG_RENDERING_QUALITY: + case VG_BLEND_MODE: + case VG_IMAGE_MODE: +#ifdef OPENVG_VERSION_1_1 + case VG_COLOR_TRANSFORM: +#endif + case VG_STROKE_CAP_STYLE: + case VG_STROKE_JOIN_STYLE: + case VG_STROKE_DASH_PHASE_RESET: + case VG_MASKING: + case VG_SCISSORING: + case VG_PIXEL_LAYOUT: + case VG_SCREEN_LAYOUT: + case VG_FILTER_FORMAT_LINEAR: + case VG_FILTER_FORMAT_PREMULTIPLIED: + case VG_FILTER_CHANNEL_MASK: + return vgGeti(type); + break; + case VG_STROKE_LINE_WIDTH: + value = state->stroke.line_width.f; + break; + case VG_STROKE_MITER_LIMIT: + value = state->stroke.miter_limit.f; + break; + case VG_STROKE_DASH_PHASE: + value = state->stroke.dash_phase.f; + break; + + case VG_MAX_SCISSOR_RECTS: + case VG_MAX_DASH_COUNT: + case VG_MAX_KERNEL_SIZE: + case VG_MAX_SEPARABLE_KERNEL_SIZE: + case VG_MAX_COLOR_RAMP_STOPS: + case VG_MAX_IMAGE_WIDTH: + case VG_MAX_IMAGE_HEIGHT: + case VG_MAX_IMAGE_PIXELS: + case VG_MAX_IMAGE_BYTES: + case VG_MAX_GAUSSIAN_STD_DEVIATION: + return vgGeti(type); + break; + case VG_MAX_FLOAT: + value = 1e+10;/*must be at least 1e+10*/ + break; + default: + error = VG_ILLEGAL_ARGUMENT_ERROR; + break; + } + vg_set_error(ctx, error); + return value; +} + +VGint vgGeti(VGParamType type) +{ + const struct vg_state *state = current_state(); + struct vg_context *ctx = vg_current_context(); + VGErrorCode error = VG_NO_ERROR; + VGint value = 0; + + switch(type) { + case VG_MATRIX_MODE: + value = state->matrix_mode; + break; + case VG_FILL_RULE: + value = state->fill_rule; + break; + case VG_IMAGE_QUALITY: + value = state->image_quality; + break; + case VG_RENDERING_QUALITY: + value = state->rendering_quality; + break; + case VG_BLEND_MODE: + value = state->blend_mode; + break; + case VG_IMAGE_MODE: + value = state->image_mode; + break; +#ifdef OPENVG_VERSION_1_1 + case VG_COLOR_TRANSFORM: + value = state->color_transform; + break; +#endif + case VG_STROKE_LINE_WIDTH: + value = state->stroke.line_width.i; + break; + case VG_STROKE_CAP_STYLE: + value = state->stroke.cap_style; + break; + case VG_STROKE_JOIN_STYLE: + value = state->stroke.join_style; + break; + case VG_STROKE_MITER_LIMIT: + value = state->stroke.miter_limit.i; + break; + case VG_STROKE_DASH_PHASE: + value = state->stroke.dash_phase.i; + break; + case VG_STROKE_DASH_PHASE_RESET: + value = state->stroke.dash_phase_reset; + break; + case VG_MASKING: + value = state->masking; + break; + case VG_SCISSORING: + value = state->scissoring; + break; + case VG_PIXEL_LAYOUT: + value = state->pixel_layout; + break; + case VG_SCREEN_LAYOUT: + value = state->screen_layout; + break; + case VG_FILTER_FORMAT_LINEAR: + value = state->filter_format_linear; + break; + case VG_FILTER_FORMAT_PREMULTIPLIED: + value = state->filter_format_premultiplied; + break; + case VG_FILTER_CHANNEL_MASK: + value = state->filter_channel_mask; + break; + + case VG_MAX_SCISSOR_RECTS: + value = 32; /*must be at least 32*/ + break; + case VG_MAX_DASH_COUNT: + value = 16; /*must be at least 16*/ + break; + case VG_MAX_KERNEL_SIZE: + value = 7; /*must be at least 7*/ + break; + case VG_MAX_SEPARABLE_KERNEL_SIZE: + value = 15; /*must be at least 15*/ + break; + case VG_MAX_COLOR_RAMP_STOPS: + value = 256; /*must be at least 32*/ + break; + case VG_MAX_IMAGE_WIDTH: + value = 2048; + break; + case VG_MAX_IMAGE_HEIGHT: + value = 2048; + break; + case VG_MAX_IMAGE_PIXELS: + value = 2048*2048; + break; + case VG_MAX_IMAGE_BYTES: + value = 2048*2048 * 4; + break; + case VG_MAX_GAUSSIAN_STD_DEVIATION: + value = 128; /*must be at least 128*/ + break; + + case VG_MAX_FLOAT: { + VGfloat val = vgGetf(type); + value = float_to_int_floor(*((VGuint*)&val)); + } + break; + default: + error = VG_ILLEGAL_ARGUMENT_ERROR; + break; + } + vg_set_error(ctx, error); + return value; +} + +VGint vgGetVectorSize(VGParamType type) +{ + struct vg_context *ctx = vg_current_context(); + const struct vg_state *state = current_state(); + switch(type) { + case VG_MATRIX_MODE: + case VG_FILL_RULE: + case VG_IMAGE_QUALITY: + case VG_RENDERING_QUALITY: + case VG_BLEND_MODE: + case VG_IMAGE_MODE: + return 1; + case VG_SCISSOR_RECTS: + return state->scissor_rects_num * 4; +#ifdef OPENVG_VERSION_1_1 + case VG_COLOR_TRANSFORM: + return 1; + case VG_COLOR_TRANSFORM_VALUES: + return 8; +#endif + case VG_STROKE_LINE_WIDTH: + case VG_STROKE_CAP_STYLE: + case VG_STROKE_JOIN_STYLE: + case VG_STROKE_MITER_LIMIT: + return 1; + case VG_STROKE_DASH_PATTERN: + return state->stroke.dash_pattern_num; + case VG_STROKE_DASH_PHASE: + return 1; + case VG_STROKE_DASH_PHASE_RESET: + return 1; + case VG_TILE_FILL_COLOR: + return 4; + case VG_CLEAR_COLOR: + return 4; +#ifdef OPENVG_VERSION_1_1 + case VG_GLYPH_ORIGIN: + return 2; +#endif + case VG_MASKING: + return 1; + case VG_SCISSORING: + return 1; + case VG_PIXEL_LAYOUT: + return 1; + case VG_SCREEN_LAYOUT: + return 1; + case VG_FILTER_FORMAT_LINEAR: + return 1; + case VG_FILTER_FORMAT_PREMULTIPLIED: + return 1; + case VG_FILTER_CHANNEL_MASK: + return 1; + + case VG_MAX_COLOR_RAMP_STOPS: + return 1; + case VG_MAX_SCISSOR_RECTS: + case VG_MAX_DASH_COUNT: + case VG_MAX_KERNEL_SIZE: + case VG_MAX_SEPARABLE_KERNEL_SIZE: + case VG_MAX_IMAGE_WIDTH: + case VG_MAX_IMAGE_HEIGHT: + case VG_MAX_IMAGE_PIXELS: + case VG_MAX_IMAGE_BYTES: + case VG_MAX_FLOAT: + case VG_MAX_GAUSSIAN_STD_DEVIATION: + return 1; + default: + if (ctx) + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return 0; + } +} + +void vgGetfv(VGParamType type, VGint count, + VGfloat * values) +{ + const struct vg_state *state = current_state(); + struct vg_context *ctx = vg_current_context(); + VGint real_count = vgGetVectorSize(type); + + if (!values || count <= 0 || count > real_count || !is_aligned(values)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + switch(type) { + case VG_MATRIX_MODE: + case VG_FILL_RULE: + case VG_IMAGE_QUALITY: + case VG_RENDERING_QUALITY: + case VG_BLEND_MODE: + case VG_IMAGE_MODE: +#ifdef OPENVG_VERSION_1_1 + case VG_COLOR_TRANSFORM: +#endif + case VG_STROKE_CAP_STYLE: + case VG_STROKE_JOIN_STYLE: + case VG_STROKE_DASH_PHASE_RESET: + case VG_MASKING: + case VG_SCISSORING: + case VG_PIXEL_LAYOUT: + case VG_SCREEN_LAYOUT: + case VG_FILTER_FORMAT_LINEAR: + case VG_FILTER_FORMAT_PREMULTIPLIED: + case VG_FILTER_CHANNEL_MASK: + case VG_MAX_SCISSOR_RECTS: + case VG_MAX_DASH_COUNT: + case VG_MAX_KERNEL_SIZE: + case VG_MAX_SEPARABLE_KERNEL_SIZE: + case VG_MAX_COLOR_RAMP_STOPS: + case VG_MAX_IMAGE_WIDTH: + case VG_MAX_IMAGE_HEIGHT: + case VG_MAX_IMAGE_PIXELS: + case VG_MAX_IMAGE_BYTES: + case VG_MAX_GAUSSIAN_STD_DEVIATION: + values[0] = vgGeti(type); + break; + case VG_MAX_FLOAT: + values[0] = vgGetf(type); + break; + case VG_SCISSOR_RECTS: { + VGint i; + for (i = 0; i < count; ++i) { + values[i] = state->scissor_rects[i].f; + } + } + break; +#ifdef OPENVG_VERSION_1_1 + case VG_COLOR_TRANSFORM_VALUES: { + memcpy(values, state->color_transform_values, + sizeof(VGfloat) * count); + } + break; +#endif + case VG_STROKE_LINE_WIDTH: + values[0] = state->stroke.line_width.f; + break; + case VG_STROKE_MITER_LIMIT: + values[0] = state->stroke.miter_limit.f; + break; + case VG_STROKE_DASH_PATTERN: { + VGint i; + for (i = 0; i < count; ++i) { + values[i] = state->stroke.dash_pattern[i].f; + } + } + break; + case VG_STROKE_DASH_PHASE: + values[0] = state->stroke.dash_phase.f; + break; + case VG_TILE_FILL_COLOR: + values[0] = state->tile_fill_color[0]; + values[1] = state->tile_fill_color[1]; + values[2] = state->tile_fill_color[2]; + values[3] = state->tile_fill_color[3]; + break; + case VG_CLEAR_COLOR: + values[0] = state->clear_color[0]; + values[1] = state->clear_color[1]; + values[2] = state->clear_color[2]; + values[3] = state->clear_color[3]; + break; +#ifdef OPENVG_VERSION_1_1 + case VG_GLYPH_ORIGIN: + values[0] = state->glyph_origin[0].f; + values[1] = state->glyph_origin[1].f; + break; +#endif + default: + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + break; + } +} + +void vgGetiv(VGParamType type, VGint count, + VGint * values) +{ + const struct vg_state *state = current_state(); + struct vg_context *ctx = vg_current_context(); + VGint real_count = vgGetVectorSize(type); + + if (!values || count <= 0 || count > real_count || !is_aligned(values)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + switch(type) { + case VG_MATRIX_MODE: + case VG_FILL_RULE: + case VG_IMAGE_QUALITY: + case VG_RENDERING_QUALITY: + case VG_BLEND_MODE: + case VG_IMAGE_MODE: +#ifdef OPENVG_VERSION_1_1 + case VG_COLOR_TRANSFORM: +#endif + case VG_STROKE_CAP_STYLE: + case VG_STROKE_JOIN_STYLE: + case VG_STROKE_DASH_PHASE_RESET: + case VG_MASKING: + case VG_SCISSORING: + case VG_PIXEL_LAYOUT: + case VG_SCREEN_LAYOUT: + case VG_FILTER_FORMAT_LINEAR: + case VG_FILTER_FORMAT_PREMULTIPLIED: + case VG_FILTER_CHANNEL_MASK: + case VG_MAX_SCISSOR_RECTS: + case VG_MAX_DASH_COUNT: + case VG_MAX_KERNEL_SIZE: + case VG_MAX_SEPARABLE_KERNEL_SIZE: + case VG_MAX_COLOR_RAMP_STOPS: + case VG_MAX_IMAGE_WIDTH: + case VG_MAX_IMAGE_HEIGHT: + case VG_MAX_IMAGE_PIXELS: + case VG_MAX_IMAGE_BYTES: + case VG_MAX_GAUSSIAN_STD_DEVIATION: + values[0] = vgGeti(type); + break; + case VG_MAX_FLOAT: { + VGfloat val = vgGetf(type); + values[0] = float_to_int_floor(*((VGuint*)&val)); + } + break; + case VG_SCISSOR_RECTS: { + VGint i; + for (i = 0; i < count; ++i) { + values[i] = state->scissor_rects[i].i; + } + } + break; +#ifdef OPENVG_VERSION_1_1 + case VG_COLOR_TRANSFORM_VALUES: { + VGint i; + VGuint *x = (VGuint*)state->color_transform_values; + for (i = 0; i < count; ++i) { + values[i] = float_to_int_floor(x[i]); + } + } + break; +#endif + case VG_STROKE_LINE_WIDTH: + values[0] = state->stroke.line_width.i; + break; + case VG_STROKE_MITER_LIMIT: + values[0] = state->stroke.miter_limit.i; + break; + case VG_STROKE_DASH_PATTERN: { + VGint i; + for (i = 0; i < count; ++i) { + values[i] = state->stroke.dash_pattern[i].i; + } + } + break; + case VG_STROKE_DASH_PHASE: + values[0] = state->stroke.dash_phase.i; + break; + case VG_TILE_FILL_COLOR: + values[0] = state->tile_fill_colori[0]; + values[1] = state->tile_fill_colori[1]; + values[2] = state->tile_fill_colori[2]; + values[3] = state->tile_fill_colori[3]; + break; + case VG_CLEAR_COLOR: + values[0] = state->clear_colori[0]; + values[1] = state->clear_colori[1]; + values[2] = state->clear_colori[2]; + values[3] = state->clear_colori[3]; + break; +#ifdef OPENVG_VERSION_1_1 + case VG_GLYPH_ORIGIN: + values[0] = state->glyph_origin[0].i; + values[1] = state->glyph_origin[1].i; + break; +#endif + default: + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + break; + } +} + +void vgSetParameterf(VGHandle object, + VGint paramType, + VGfloat value) +{ + struct vg_context *ctx = vg_current_context(); + void *ptr = (void*)object; + + if (!object || object == VG_INVALID_HANDLE || !is_aligned(ptr)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + switch(paramType) { + case VG_PAINT_TYPE: + case VG_PAINT_COLOR_RAMP_SPREAD_MODE: + case VG_PAINT_PATTERN_TILING_MODE: + vgSetParameteri(object, paramType, floor(value)); + return; + break; + case VG_PAINT_COLOR: + case VG_PAINT_COLOR_RAMP_STOPS: + case VG_PAINT_LINEAR_GRADIENT: + case VG_PAINT_RADIAL_GRADIENT: + /* it's an error if paramType refers to a vector parameter */ + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + break; + case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: { + struct vg_paint *p = (struct vg_paint *)object; + paint_set_color_ramp_premultiplied(p, value); + } + break; + + case VG_PATH_DATATYPE: + case VG_PATH_FORMAT: + case VG_PATH_SCALE: + case VG_PATH_BIAS: + case VG_PATH_NUM_SEGMENTS: + case VG_PATH_NUM_COORDS: + + case VG_IMAGE_FORMAT: + case VG_IMAGE_WIDTH: + case VG_IMAGE_HEIGHT: + +#ifdef OPENVG_VERSION_1_1 + case VG_FONT_NUM_GLYPHS: + /* read only don't produce an error */ + break; +#endif + default: + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + break; + } +} + +void vgSetParameteri(VGHandle object, + VGint paramType, + VGint value) +{ + struct vg_context *ctx = vg_current_context(); + void *ptr = (void*)object; + + if (!object || object == VG_INVALID_HANDLE || !is_aligned(ptr)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + switch(paramType) { + case VG_PAINT_TYPE: + if (value < VG_PAINT_TYPE_COLOR || + value > VG_PAINT_TYPE_PATTERN) + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + else { + struct vg_paint *paint = (struct vg_paint *)ptr; + paint_set_type(paint, value); + } + break; + case VG_PAINT_COLOR: + case VG_PAINT_COLOR_RAMP_STOPS: + case VG_PAINT_LINEAR_GRADIENT: + case VG_PAINT_RADIAL_GRADIENT: + /* it's an error if paramType refers to a vector parameter */ + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + break; + case VG_PAINT_COLOR_RAMP_SPREAD_MODE: + if (value < VG_COLOR_RAMP_SPREAD_PAD || + value > VG_COLOR_RAMP_SPREAD_REFLECT) + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + else { + struct vg_paint *paint = (struct vg_paint *)ptr; + paint_set_spread_mode(paint, value); + } + break; + case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: { + struct vg_paint *p = (struct vg_paint *)object; + paint_set_color_ramp_premultiplied(p, value); + } + break; + case VG_PAINT_PATTERN_TILING_MODE: + if (value < VG_TILE_FILL || + value > VG_TILE_REFLECT) + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + else { + struct vg_paint *paint = (struct vg_paint *)ptr; + paint_set_pattern_tiling(paint, value); + } + break; + + case VG_PATH_DATATYPE: + case VG_PATH_FORMAT: + case VG_PATH_SCALE: + case VG_PATH_BIAS: + case VG_PATH_NUM_SEGMENTS: + case VG_PATH_NUM_COORDS: + + case VG_IMAGE_FORMAT: + case VG_IMAGE_WIDTH: + case VG_IMAGE_HEIGHT: + +#ifdef OPENVG_VERSION_1_1 + case VG_FONT_NUM_GLYPHS: + /* read only don't produce an error */ + break; +#endif + default: + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } +} + +void vgSetParameterfv(VGHandle object, + VGint paramType, + VGint count, + const VGfloat * values) +{ + struct vg_context *ctx = vg_current_context(); + void *ptr = (void*)object; + VGint real_count = vgGetParameterVectorSize(object, paramType); + + if (!object || object == VG_INVALID_HANDLE || !is_aligned(ptr)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + if (count < 0 || count < real_count || + (values == NULL && count != 0) || + !is_aligned(values)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + switch(paramType) { + case VG_PAINT_TYPE: + case VG_PAINT_COLOR_RAMP_SPREAD_MODE: + case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: + case VG_PAINT_PATTERN_TILING_MODE: + if (count != 1) + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + else + vgSetParameterf(object, paramType, values[0]); + return; + break; + case VG_PAINT_COLOR: { + if (count != 4) + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + else { + struct vg_paint *paint = (struct vg_paint *)object; + paint_set_color(paint, values); + } + } + break; + case VG_PAINT_COLOR_RAMP_STOPS: { + if (count && count < 4) + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + else { + struct vg_paint *paint = (struct vg_paint *)object; + count = MIN2(count, VEGA_MAX_COLOR_RAMP_STOPS); + paint_set_ramp_stops(paint, values, count); + { + VGint stopsi[VEGA_MAX_COLOR_RAMP_STOPS]; + int i = 0; + for (i = 0; i < count; ++i) { + stopsi[i] = float_to_int_floor(*((VGuint*)(values + i))); + } + paint_set_ramp_stopsi(paint, stopsi, count); + } + } + } + break; + case VG_PAINT_LINEAR_GRADIENT: { + if (count != 4) + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + else { + struct vg_paint *paint = (struct vg_paint *)object; + paint_set_linear_gradient(paint, values); + { + VGint vals[4]; + vals[0] = FLT_TO_INT(values[0]); + vals[1] = FLT_TO_INT(values[1]); + vals[2] = FLT_TO_INT(values[2]); + vals[3] = FLT_TO_INT(values[3]); + paint_set_linear_gradienti(paint, vals); + } + } + } + break; + case VG_PAINT_RADIAL_GRADIENT: { + if (count != 5) + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + else { + struct vg_paint *paint = (struct vg_paint *)object; + paint_set_radial_gradient(paint, values); + { + VGint vals[5]; + vals[0] = FLT_TO_INT(values[0]); + vals[1] = FLT_TO_INT(values[1]); + vals[2] = FLT_TO_INT(values[2]); + vals[3] = FLT_TO_INT(values[3]); + vals[4] = FLT_TO_INT(values[4]); + paint_set_radial_gradienti(paint, vals); + } + } + } + break; + + case VG_PATH_DATATYPE: + case VG_PATH_FORMAT: + case VG_PATH_SCALE: + case VG_PATH_BIAS: + case VG_PATH_NUM_SEGMENTS: + case VG_PATH_NUM_COORDS: + +#ifdef OPENVG_VERSION_1_1 + case VG_FONT_NUM_GLYPHS: + /* read only don't produce an error */ + break; +#endif + default: + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } +} + +void vgSetParameteriv(VGHandle object, + VGint paramType, + VGint count, + const VGint * values) +{ + struct vg_context *ctx = vg_current_context(); + void *ptr = (void*)object; + VGint real_count = vgGetParameterVectorSize(object, paramType); + + if (!object || object == VG_INVALID_HANDLE || !is_aligned(ptr)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + if (count < 0 || count < real_count || + (values == NULL && count != 0) || + !is_aligned(values)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + switch(paramType) { + case VG_PAINT_TYPE: + case VG_PAINT_COLOR_RAMP_SPREAD_MODE: + case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: + case VG_PAINT_PATTERN_TILING_MODE: + if (count != 1) + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + else + vgSetParameteri(object, paramType, values[0]); + return; + break; + case VG_PAINT_COLOR: { + if (count != 4) + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + else { + struct vg_paint *paint = (struct vg_paint *)object; + paint_set_coloriv(paint, values); + } + } + break; + case VG_PAINT_COLOR_RAMP_STOPS: { + if ((count % 5)) + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + else { + VGfloat *vals = 0; + int i; + struct vg_paint *paint = (struct vg_paint *)object; + if (count) { + vals = malloc(sizeof(VGfloat)*count); + for (i = 0; i < count; ++i) + vals[i] = values[i]; + } + + paint_set_ramp_stopsi(paint, values, count); + paint_set_ramp_stops(paint, vals, count); + free(vals); + } + } + break; + case VG_PAINT_LINEAR_GRADIENT: { + if (count != 4) + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + else { + VGfloat vals[4]; + struct vg_paint *paint = (struct vg_paint *)object; + vals[0] = values[0]; + vals[1] = values[1]; + vals[2] = values[2]; + vals[3] = values[3]; + paint_set_linear_gradient(paint, vals); + paint_set_linear_gradienti(paint, values); + } + } + break; + case VG_PAINT_RADIAL_GRADIENT: { + if (count != 5) + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + else { + VGfloat vals[5]; + struct vg_paint *paint = (struct vg_paint *)object; + vals[0] = values[0]; + vals[1] = values[1]; + vals[2] = values[2]; + vals[3] = values[3]; + vals[4] = values[4]; + paint_set_radial_gradient(paint, vals); + paint_set_radial_gradienti(paint, values); + } + } + break; + case VG_PATH_DATATYPE: + case VG_PATH_FORMAT: + case VG_PATH_SCALE: + case VG_PATH_BIAS: + case VG_PATH_NUM_SEGMENTS: + case VG_PATH_NUM_COORDS: + /* read only don't produce an error */ + break; + default: + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } +} + +VGint vgGetParameterVectorSize(VGHandle object, + VGint paramType) +{ + struct vg_context *ctx = vg_current_context(); + void *ptr = (void*)object; + + if (!ptr || object == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return 0; + } + + switch(paramType) { + case VG_PAINT_TYPE: + case VG_PAINT_COLOR_RAMP_SPREAD_MODE: + case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: + case VG_PAINT_PATTERN_TILING_MODE: + return 1; + case VG_PAINT_COLOR: + return 4; + case VG_PAINT_COLOR_RAMP_STOPS: { + struct vg_paint *p = (struct vg_paint *)object; + return paint_num_ramp_stops(p); + } + break; + case VG_PAINT_LINEAR_GRADIENT: + return 4; + case VG_PAINT_RADIAL_GRADIENT: + return 5; + + + case VG_PATH_FORMAT: + case VG_PATH_DATATYPE: + case VG_PATH_SCALE: + case VG_PATH_BIAS: + case VG_PATH_NUM_SEGMENTS: + case VG_PATH_NUM_COORDS: + return 1; + + case VG_IMAGE_FORMAT: + case VG_IMAGE_WIDTH: + case VG_IMAGE_HEIGHT: + return 1; + +#ifdef OPENVG_VERSION_1_1 + case VG_FONT_NUM_GLYPHS: + return 1; +#endif + + default: + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + break; + } + return 0; +} + + +VGfloat vgGetParameterf(VGHandle object, + VGint paramType) +{ + struct vg_context *ctx = vg_current_context(); + void *ptr = (void*)object; + + if (!ptr || object == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return 0; + } + + switch(paramType) { + case VG_PAINT_TYPE: + case VG_PAINT_COLOR_RAMP_SPREAD_MODE: + case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: + case VG_PAINT_PATTERN_TILING_MODE: + return vgGetParameteri(object, paramType); + break; + case VG_PAINT_COLOR: + case VG_PAINT_COLOR_RAMP_STOPS: + case VG_PAINT_LINEAR_GRADIENT: + case VG_PAINT_RADIAL_GRADIENT: + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + break; + + case VG_PATH_FORMAT: + return VG_PATH_FORMAT_STANDARD; + case VG_PATH_SCALE: { + struct path *p = (struct path*)object; + return path_scale(p); + } + case VG_PATH_BIAS: { + struct path *p = (struct path*)object; + return path_bias(p); + } + case VG_PATH_DATATYPE: + case VG_PATH_NUM_SEGMENTS: + case VG_PATH_NUM_COORDS: + return vgGetParameteri(object, paramType); + break; + + case VG_IMAGE_FORMAT: + case VG_IMAGE_WIDTH: + case VG_IMAGE_HEIGHT: +#ifdef OPENVG_VERSION_1_1 + case VG_FONT_NUM_GLYPHS: + return vgGetParameteri(object, paramType); + break; +#endif + + default: + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + break; + } + return 0; +} + +VGint vgGetParameteri(VGHandle object, + VGint paramType) +{ + struct vg_context *ctx = vg_current_context(); + void *ptr = (void*)object; + + if (!ptr || object == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return 0; + } + + switch(paramType) { + case VG_PAINT_TYPE: { + struct vg_paint *paint = (struct vg_paint *)ptr; + return paint_type(paint); + } + break; + case VG_PAINT_COLOR_RAMP_SPREAD_MODE: { + struct vg_paint *p = (struct vg_paint *)object; + return paint_spread_mode(p); + } + case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: { + struct vg_paint *p = (struct vg_paint *)object; + return paint_color_ramp_premultiplied(p); + } + break; + case VG_PAINT_PATTERN_TILING_MODE: { + struct vg_paint *p = (struct vg_paint *)object; + return paint_pattern_tiling(p); + } + break; + case VG_PAINT_COLOR: + case VG_PAINT_COLOR_RAMP_STOPS: + case VG_PAINT_LINEAR_GRADIENT: + case VG_PAINT_RADIAL_GRADIENT: + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + break; + + case VG_PATH_FORMAT: + return VG_PATH_FORMAT_STANDARD; + case VG_PATH_SCALE: + case VG_PATH_BIAS: + return vgGetParameterf(object, paramType); + case VG_PATH_DATATYPE: { + struct path *p = (struct path*)object; + return path_datatype(p); + } + case VG_PATH_NUM_SEGMENTS: { + struct path *p = (struct path*)object; + return path_num_segments(p); + } + case VG_PATH_NUM_COORDS: { + struct path *p = (struct path*)object; + return path_num_coords(p); + } + break; + + case VG_IMAGE_FORMAT: { + struct vg_image *img = (struct vg_image*)object; + return img->format; + } + break; + case VG_IMAGE_WIDTH: { + struct vg_image *img = (struct vg_image*)object; + return img->width; + } + break; + case VG_IMAGE_HEIGHT: { + struct vg_image *img = (struct vg_image*)object; + return img->height; + } + break; + +#ifdef OPENVG_VERSION_1_1 + case VG_FONT_NUM_GLYPHS: { + return 1; + } + break; +#endif + + default: + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + break; + } + return 0; +} + +void vgGetParameterfv(VGHandle object, + VGint paramType, + VGint count, + VGfloat * values) +{ + struct vg_context *ctx = vg_current_context(); + void *ptr = (void*)object; + VGint real_count = vgGetParameterVectorSize(object, paramType); + + if (!ptr || object == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + if (!values || count <= 0 || count > real_count || + !is_aligned(values)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + switch(paramType) { + case VG_PAINT_TYPE: { + struct vg_paint *p = (struct vg_paint *)object; + values[0] = paint_type(p); + } + break; + case VG_PAINT_COLOR_RAMP_SPREAD_MODE: { + struct vg_paint *p = (struct vg_paint *)object; + values[0] = paint_spread_mode(p); + } + break; + case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: { + struct vg_paint *p = (struct vg_paint *)object; + values[0] = paint_color_ramp_premultiplied(p); + } + break; + case VG_PAINT_PATTERN_TILING_MODE: { + values[0] = vgGetParameterf(object, paramType); + } + break; + case VG_PAINT_COLOR: { + struct vg_paint *paint = (struct vg_paint *)object; + paint_get_color(paint, values); + } + break; + case VG_PAINT_COLOR_RAMP_STOPS: { + struct vg_paint *paint = (struct vg_paint *)object; + paint_ramp_stops(paint, values, count); + } + break; + case VG_PAINT_LINEAR_GRADIENT: { + struct vg_paint *paint = (struct vg_paint *)object; + paint_linear_gradient(paint, values); + } + break; + case VG_PAINT_RADIAL_GRADIENT: { + struct vg_paint *paint = (struct vg_paint *)object; + paint_radial_gradient(paint, values); + } + break; + + case VG_PATH_FORMAT: + case VG_PATH_DATATYPE: + case VG_PATH_NUM_SEGMENTS: + case VG_PATH_NUM_COORDS: + values[0] = vgGetParameteri(object, paramType); + break; + case VG_PATH_SCALE: + case VG_PATH_BIAS: + values[0] = vgGetParameterf(object, paramType); + break; + + case VG_IMAGE_FORMAT: + case VG_IMAGE_WIDTH: + case VG_IMAGE_HEIGHT: +#ifdef OPENVG_VERSION_1_1 + case VG_FONT_NUM_GLYPHS: + values[0] = vgGetParameteri(object, paramType); + break; +#endif + + default: + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + break; + } +} + +void vgGetParameteriv(VGHandle object, + VGint paramType, + VGint count, + VGint * values) +{ + struct vg_context *ctx = vg_current_context(); + void *ptr = (void*)object; + VGint real_count = vgGetParameterVectorSize(object, paramType); + + if (!ptr || object == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + if (!values || count <= 0 || count > real_count || + !is_aligned(values)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + switch(paramType) { + case VG_PAINT_TYPE: + case VG_PAINT_COLOR_RAMP_SPREAD_MODE: + case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: + case VG_PAINT_PATTERN_TILING_MODE: +#ifdef OPENVG_VERSION_1_1 + case VG_FONT_NUM_GLYPHS: + values[0] = vgGetParameteri(object, paramType); + break; +#endif + case VG_PAINT_COLOR: { + struct vg_paint *paint = (struct vg_paint *)object; + paint_get_coloriv(paint, values); + } + break; + case VG_PAINT_COLOR_RAMP_STOPS: { + struct vg_paint *paint = (struct vg_paint *)object; + paint_ramp_stopsi(paint, values, count); + } + break; + case VG_PAINT_LINEAR_GRADIENT: { + struct vg_paint *paint = (struct vg_paint *)object; + paint_linear_gradienti(paint, values); + } + break; + case VG_PAINT_RADIAL_GRADIENT: { + struct vg_paint *paint = (struct vg_paint *)object; + paint_radial_gradienti(paint, values); + } + break; + + case VG_PATH_SCALE: + case VG_PATH_BIAS: + values[0] = vgGetParameterf(object, paramType); + break; + case VG_PATH_FORMAT: + case VG_PATH_DATATYPE: + case VG_PATH_NUM_SEGMENTS: + case VG_PATH_NUM_COORDS: + values[0] = vgGetParameteri(object, paramType); + break; + + case VG_IMAGE_FORMAT: + case VG_IMAGE_WIDTH: + case VG_IMAGE_HEIGHT: + values[0] = vgGetParameteri(object, paramType); + break; + + default: + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + break; + } +} diff --git a/src/gallium/state_trackers/vega/api_path.c b/src/gallium/state_trackers/vega/api_path.c new file mode 100644 index 00000000000..a6b7a2bb93a --- /dev/null +++ b/src/gallium/state_trackers/vega/api_path.c @@ -0,0 +1,488 @@ +/************************************************************************** + * + * 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 "VG/openvg.h" + +#include "vg_context.h" +#include "path.h" +#include "polygon.h" +#include "paint.h" + +#include "pipe/p_context.h" +#include "pipe/p_inlines.h" +#include "util/u_draw_quad.h" + +VGPath vgCreatePath(VGint pathFormat, + VGPathDatatype datatype, + VGfloat scale, VGfloat bias, + VGint segmentCapacityHint, + VGint coordCapacityHint, + VGbitfield capabilities) +{ + struct vg_context *ctx = vg_current_context(); + + if (pathFormat != VG_PATH_FORMAT_STANDARD) { + vg_set_error(ctx, VG_UNSUPPORTED_PATH_FORMAT_ERROR); + return VG_INVALID_HANDLE; + } + if (datatype < VG_PATH_DATATYPE_S_8 || + datatype > VG_PATH_DATATYPE_F) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return VG_INVALID_HANDLE; + } + if (!scale) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return VG_INVALID_HANDLE; + } + + return (VGPath)path_create(datatype, scale, bias, + segmentCapacityHint, coordCapacityHint, + capabilities); +} + +void vgClearPath(VGPath path, VGbitfield capabilities) +{ + struct vg_context *ctx = vg_current_context(); + struct path *p = 0; + + if (path == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + p = (struct path *)path; + path_clear(p, capabilities); +} + +void vgDestroyPath(VGPath p) +{ + struct path *path = 0; + struct vg_context *ctx = vg_current_context(); + + if (p == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + path = (struct path *)p; + path_destroy(path); +} + +void vgRemovePathCapabilities(VGPath path, + VGbitfield capabilities) +{ + struct vg_context *ctx = vg_current_context(); + VGbitfield current; + struct path *p; + + if (path == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + p = (struct path*)path; + current = path_capabilities(p); + path_set_capabilities(p, (current & + (~(capabilities & VG_PATH_CAPABILITY_ALL)))); +} + +VGbitfield vgGetPathCapabilities(VGPath path) +{ + struct vg_context *ctx = vg_current_context(); + struct path *p = 0; + + if (path == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return 0; + } + p = (struct path*)path; + return path_capabilities(p); +} + +void vgAppendPath(VGPath dstPath, VGPath srcPath) +{ + struct vg_context *ctx = vg_current_context(); + struct path *src, *dst; + + if (dstPath == VG_INVALID_HANDLE || srcPath == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + src = (struct path *)srcPath; + dst = (struct path *)dstPath; + + if (!(path_capabilities(src) & VG_PATH_CAPABILITY_APPEND_FROM) || + !(path_capabilities(dst) & VG_PATH_CAPABILITY_APPEND_TO)) { + vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR); + return; + } + path_append_path(dst, src); +} + +void vgAppendPathData(VGPath dstPath, + VGint numSegments, + const VGubyte * pathSegments, + const void * pathData) +{ + struct vg_context *ctx = vg_current_context(); + struct path *p = 0; + VGint i; + + if (dstPath == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (!pathSegments) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + if (numSegments <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + for (i = 0; i < numSegments; ++i) { + if (pathSegments[i] < VG_CLOSE_PATH || + pathSegments[i] > VG_LCWARC_TO_REL) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + } + + p = (struct path*)dstPath; + + if (!pathData || !is_aligned_to(pathData, path_datatype_size(p))) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + if (!(path_capabilities(p)&VG_PATH_CAPABILITY_APPEND_TO)) { + vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR); + return; + } + + path_append_data(p, numSegments, pathSegments, pathData); +} + +void vgModifyPathCoords(VGPath dstPath, + VGint startIndex, + VGint numSegments, + const void * pathData) +{ + struct vg_context *ctx = vg_current_context(); + struct path *p = 0; + + if (dstPath == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (startIndex < 0 || numSegments <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + p = (struct path *)dstPath; + + if (!pathData || !is_aligned_to(pathData, path_datatype_size(p))) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + if (startIndex + numSegments > path_num_segments(p)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + if (!(path_capabilities(p)&VG_PATH_CAPABILITY_MODIFY)) { + vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR); + return; + } + path_modify_coords(p, startIndex, numSegments, pathData); +} + +void vgTransformPath(VGPath dstPath, VGPath srcPath) +{ + struct vg_context *ctx = vg_current_context(); + struct path *src = 0, *dst = 0; + + if (dstPath == VG_INVALID_HANDLE || srcPath == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + src = (struct path *)srcPath; + dst = (struct path *)dstPath; + + if (!(path_capabilities(src) & VG_PATH_CAPABILITY_TRANSFORM_FROM) || + !(path_capabilities(dst) & VG_PATH_CAPABILITY_TRANSFORM_TO)) { + vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR); + return; + } + path_transform(dst, src); +} + +VGboolean vgInterpolatePath(VGPath dstPath, + VGPath startPath, + VGPath endPath, + VGfloat amount) +{ + struct vg_context *ctx = vg_current_context(); + struct path *start = 0, *dst = 0, *end = 0; + + if (dstPath == VG_INVALID_HANDLE || + startPath == VG_INVALID_HANDLE || + endPath == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return VG_FALSE; + } + dst = (struct path *)dstPath; + start = (struct path *)startPath; + end = (struct path *)endPath; + + if (!(path_capabilities(dst) & VG_PATH_CAPABILITY_INTERPOLATE_TO) || + !(path_capabilities(start) & VG_PATH_CAPABILITY_INTERPOLATE_FROM) || + !(path_capabilities(end) & VG_PATH_CAPABILITY_INTERPOLATE_FROM)) { + vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR); + return VG_FALSE; + } + + return path_interpolate(dst, + start, end, amount); +} + +VGfloat vgPathLength(VGPath path, + VGint startSegment, + VGint numSegments) +{ + struct vg_context *ctx = vg_current_context(); + struct path *p = 0; + + if (path == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return -1; + } + if (startSegment < 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return -1; + } + if (numSegments <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return -1; + } + p = (struct path*)path; + + if (!(path_capabilities(p) & VG_PATH_CAPABILITY_PATH_LENGTH)) { + vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR); + return -1; + } + if (startSegment + numSegments > path_num_segments(p)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return -1; + } + + return path_length(p, startSegment, numSegments); +} + +void vgPointAlongPath(VGPath path, + VGint startSegment, + VGint numSegments, + VGfloat distance, + VGfloat * x, VGfloat * y, + VGfloat * tangentX, + VGfloat * tangentY) +{ + struct vg_context *ctx = vg_current_context(); + struct path *p = 0; + VGbitfield caps; + + if (path == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (startSegment < 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + if (numSegments <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + if (!is_aligned(x) || !is_aligned(y) || + !is_aligned(tangentX) || !is_aligned(tangentY)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + p = (struct path*)path; + + caps = path_capabilities(p); + if (!(caps & VG_PATH_CAPABILITY_POINT_ALONG_PATH) || + !(caps & VG_PATH_CAPABILITY_TANGENT_ALONG_PATH)) { + vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR); + return; + } + + if (startSegment + numSegments > path_num_segments(p)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + { + VGfloat point[2], normal[2]; + path_point(p, startSegment, numSegments, distance, + point, normal); + if (x) + *x = point[0]; + if (y) + *y = point[1]; + if (tangentX) + *tangentX = -normal[1]; + if (tangentY) + *tangentY = normal[0]; + } +} + +void vgPathBounds(VGPath path, + VGfloat * minX, + VGfloat * minY, + VGfloat * width, + VGfloat * height) +{ + struct vg_context *ctx = vg_current_context(); + struct path *p = 0; + VGbitfield caps; + + if (path == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + if (!minX || !minY || !width || !height) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + if (!is_aligned(minX) || !is_aligned(minY) || + !is_aligned(width) || !is_aligned(height)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + p = (struct path*)path; + + caps = path_capabilities(p); + if (!(caps & VG_PATH_CAPABILITY_PATH_BOUNDS)) { + vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR); + return; + } + + path_bounding_rect(p, minX, minY, width, height); +} + +void vgPathTransformedBounds(VGPath path, + VGfloat * minX, + VGfloat * minY, + VGfloat * width, + VGfloat * height) +{ + struct vg_context *ctx = vg_current_context(); + struct path *p = 0; + VGbitfield caps; + + if (path == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + if (!minX || !minY || !width || !height) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + if (!is_aligned(minX) || !is_aligned(minY) || + !is_aligned(width) || !is_aligned(height)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + p = (struct path*)path; + + caps = path_capabilities(p); + if (!(caps & VG_PATH_CAPABILITY_PATH_TRANSFORMED_BOUNDS)) { + vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR); + return; + } + +#if 0 + /* faster, but seems to have precision problems... */ + path_bounding_rect(p, minX, minY, width, height); + if (*width > 0 && *height > 0) { + VGfloat pts[] = {*minX, *minY, + *minX + *width, *minY, + *minX + *width, *minY + *height, + *minX, *minY + *height}; + struct matrix *matrix = &ctx->state.vg.path_user_to_surface_matrix; + VGfloat maxX, maxY; + matrix_map_point(matrix, pts[0], pts[1], pts + 0, pts + 1); + matrix_map_point(matrix, pts[2], pts[3], pts + 2, pts + 3); + matrix_map_point(matrix, pts[4], pts[5], pts + 4, pts + 5); + matrix_map_point(matrix, pts[6], pts[7], pts + 6, pts + 7); + *minX = MIN2(pts[0], MIN2(pts[2], MIN2(pts[4], pts[6]))); + *minY = MIN2(pts[1], MIN2(pts[3], MIN2(pts[5], pts[7]))); + maxX = MAX2(pts[0], MAX2(pts[2], MAX2(pts[4], pts[6]))); + maxY = MAX2(pts[1], MAX2(pts[3], MAX2(pts[5], pts[7]))); + *width = maxX - *minX; + *height = maxY - *minY; + } +#else + { + struct path *dst = path_create(VG_PATH_DATATYPE_F, 1.0, 0, + 0, 0, VG_PATH_CAPABILITY_ALL); + path_transform(dst, p); + path_bounding_rect(dst, minX, minY, width, height); + path_destroy(dst); + } +#endif +} + + +void vgDrawPath(VGPath path, VGbitfield paintModes) +{ + struct vg_context *ctx = vg_current_context(); + + if (path == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + if (!(paintModes & (VG_STROKE_PATH | VG_FILL_PATH))) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + if (path_is_empty((struct path*)path)) + return; + path_render((struct path*)path, paintModes); +} + diff --git a/src/gallium/state_trackers/vega/api_text.c b/src/gallium/state_trackers/vega/api_text.c new file mode 100644 index 00000000000..d8411cf3e87 --- /dev/null +++ b/src/gallium/state_trackers/vega/api_text.c @@ -0,0 +1,258 @@ +/************************************************************************** + * + * 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 "VG/openvg.h" + +#include "vg_context.h" + +#include "util/u_memory.h" + +#ifdef OPENVG_VERSION_1_1 + +struct vg_font { + struct vg_object base; + + VGint glyph_indices[200]; + VGint num_glyphs; +}; + +VGFont vgCreateFont(VGint glyphCapacityHint) +{ + struct vg_font *font = 0; + struct vg_context *ctx = vg_current_context(); + + if (glyphCapacityHint < 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return VG_INVALID_HANDLE; + } + + font = CALLOC_STRUCT(vg_font); + vg_init_object(&font->base, ctx, VG_OBJECT_FONT); + vg_context_add_object(ctx, VG_OBJECT_FONT, font); + return (VGFont)font; +} + +void vgDestroyFont(VGFont f) +{ + struct vg_font *font = (struct vg_font *)f; + struct vg_context *ctx = vg_current_context(); + + if (f == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + vg_context_remove_object(ctx, VG_OBJECT_FONT, font); + /*free(font);*/ +} + +void vgSetGlyphToPath(VGFont font, + VGuint glyphIndex, + VGPath path, + VGboolean isHinted, + VGfloat glyphOrigin [2], + VGfloat escapement[2]) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_object *pathObj; + struct vg_font *f; + + if (font == VG_INVALID_HANDLE || + !vg_context_is_object_valid(ctx, VG_OBJECT_FONT, (void *)font)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (!glyphOrigin || !escapement || + !is_aligned(glyphOrigin) || !is_aligned(escapement)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + if (path != VG_INVALID_HANDLE && + !vg_context_is_object_valid(ctx, VG_OBJECT_PATH, (void *)path)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + pathObj = (struct vg_object*)path; + if (pathObj && pathObj->type != VG_OBJECT_PATH) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + + f = (struct vg_font*)font; + f->glyph_indices[f->num_glyphs] = glyphIndex; + ++f->num_glyphs; +} + +void vgSetGlyphToImage(VGFont font, + VGuint glyphIndex, + VGImage image, + VGfloat glyphOrigin [2], + VGfloat escapement[2]) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_object *img_obj; + struct vg_font *f; + + if (font == VG_INVALID_HANDLE || + !vg_context_is_object_valid(ctx, VG_OBJECT_FONT, (void *)font)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (!glyphOrigin || !escapement || + !is_aligned(glyphOrigin) || !is_aligned(escapement)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + if (image != VG_INVALID_HANDLE && + !vg_context_is_object_valid(ctx, VG_OBJECT_IMAGE, (void *)image)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + img_obj = (struct vg_object*)image; + if (img_obj && img_obj->type != VG_OBJECT_IMAGE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + f = (struct vg_font*)font; + f->glyph_indices[f->num_glyphs] = glyphIndex; + ++f->num_glyphs; +} + +static INLINE VGboolean font_contains_glyph(struct vg_font *font, + VGuint glyph_index) +{ + VGint i; + for (i = 0; i < font->num_glyphs; ++i) { + if (font->glyph_indices[i] == glyph_index) { + return VG_TRUE; + } + } + return VG_FALSE; +} + +void vgClearGlyph(VGFont font, + VGuint glyphIndex) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_font *f; + VGint i; + + if (font == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (glyphIndex <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + f = (struct vg_font*)font; + if (!font_contains_glyph(f, glyphIndex)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + for (i = 0; i < f->num_glyphs; ++i) { + if (f->glyph_indices[i] == glyphIndex) { + /*FIXME*/ + f->glyph_indices[f->num_glyphs] = 0; + --f->num_glyphs; + return; + } + } +} + +void vgDrawGlyph(VGFont font, + VGuint glyphIndex, + VGbitfield paintModes, + VGboolean allowAutoHinting) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_font *f; + + if (font == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (glyphIndex <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + if (paintModes & (~(VG_STROKE_PATH|VG_FILL_PATH))) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + f = (struct vg_font*)font; + if (!font_contains_glyph(f, glyphIndex)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } +} + +void vgDrawGlyphs(VGFont font, + VGint glyphCount, + VGuint *glyphIndices, + VGfloat *adjustments_x, + VGfloat *adjustments_y, + VGbitfield paintModes, + VGboolean allowAutoHinting) +{ + struct vg_context *ctx = vg_current_context(); + VGint i; + struct vg_font *f; + + if (font == VG_INVALID_HANDLE) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } + if (glyphCount <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + if (!glyphIndices || !is_aligned(glyphIndices)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + if (!adjustments_x || !is_aligned(adjustments_x) || + !adjustments_y || !is_aligned(adjustments_y)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + if (paintModes & (~(VG_STROKE_PATH|VG_FILL_PATH))) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + f = (struct vg_font*)font; + for (i = 0; i < glyphCount; ++i) { + VGuint glyph_index = glyphIndices[i]; + if (!font_contains_glyph(f, glyph_index)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + } +} + +#endif diff --git a/src/gallium/state_trackers/vega/api_transform.c b/src/gallium/state_trackers/vega/api_transform.c new file mode 100644 index 00000000000..763a5ec415c --- /dev/null +++ b/src/gallium/state_trackers/vega/api_transform.c @@ -0,0 +1,128 @@ +/************************************************************************** + * + * 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 "VG/openvg.h" + +#include "vg_context.h" + +#include "matrix.h" + +void vgLoadIdentity(void) +{ + struct vg_context *ctx = vg_current_context(); + struct matrix *mat = vg_state_matrix(&ctx->state.vg); + matrix_load_identity(mat); +} + +void vgLoadMatrix(const VGfloat * m) +{ + struct vg_context *ctx = vg_current_context(); + struct matrix *mat; + + if (!ctx) + return; + + if (!m || !is_aligned(m)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + mat = vg_state_matrix(&ctx->state.vg); + matrix_init(mat, m); + if (!matrix_is_affine(mat)) { + if (ctx->state.vg.matrix_mode != VG_MATRIX_IMAGE_USER_TO_SURFACE) { + matrix_make_affine(mat); + } + } +} + +void vgGetMatrix(VGfloat * m) +{ + struct vg_context *ctx = vg_current_context(); + struct matrix *mat; + + if (!ctx) + return; + + if (!m || !is_aligned(m)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + mat = vg_state_matrix(&ctx->state.vg); + memcpy(m, mat->m, sizeof(VGfloat)*9); +} + +void vgMultMatrix(const VGfloat * m) +{ + struct vg_context *ctx = vg_current_context(); + struct matrix *dst, src; + + if (!ctx) + return; + + if (!m || !is_aligned(m)) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + matrix_init(&src, m); + dst = vg_state_matrix(&ctx->state.vg); + if (!matrix_is_affine(&src)) { + if (ctx->state.vg.matrix_mode != VG_MATRIX_IMAGE_USER_TO_SURFACE) { + matrix_make_affine(&src); + } + } + matrix_mult(dst, &src); + +} + +void vgTranslate(VGfloat tx, VGfloat ty) +{ + struct vg_context *ctx = vg_current_context(); + struct matrix *dst = vg_state_matrix(&ctx->state.vg); + matrix_translate(dst, tx, ty); +} + +void vgScale(VGfloat sx, VGfloat sy) +{ + struct vg_context *ctx = vg_current_context(); + struct matrix *dst = vg_state_matrix(&ctx->state.vg); + matrix_scale(dst, sx, sy); +} + +void vgShear(VGfloat shx, VGfloat shy) +{ + struct vg_context *ctx = vg_current_context(); + struct matrix *dst = vg_state_matrix(&ctx->state.vg); + matrix_shear(dst, shx, shy); +} + +void vgRotate(VGfloat angle) +{ + struct vg_context *ctx = vg_current_context(); + struct matrix *dst = vg_state_matrix(&ctx->state.vg); + matrix_rotate(dst, angle); +} diff --git a/src/gallium/state_trackers/vega/arc.c b/src/gallium/state_trackers/vega/arc.c new file mode 100644 index 00000000000..e74c7f03345 --- /dev/null +++ b/src/gallium/state_trackers/vega/arc.c @@ -0,0 +1,708 @@ +/************************************************************************** + * + * 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 "arc.h" + +#include "matrix.h" +#include "bezier.h" +#include "polygon.h" +#include "stroker.h" +#include "path.h" + +#include "util/u_debug.h" + +#include <math.h> + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#define DEBUG_ARCS 0 + +static const VGfloat two_pi = M_PI * 2; + + +static const double coeffs3Low[2][4][4] = { + { + { 3.85268, -21.229, -0.330434, 0.0127842 }, + { -1.61486, 0.706564, 0.225945, 0.263682 }, + { -0.910164, 0.388383, 0.00551445, 0.00671814 }, + { -0.630184, 0.192402, 0.0098871, 0.0102527 } + }, + { + { -0.162211, 9.94329, 0.13723, 0.0124084 }, + { -0.253135, 0.00187735, 0.0230286, 0.01264 }, + { -0.0695069, -0.0437594, 0.0120636, 0.0163087 }, + { -0.0328856, -0.00926032, -0.00173573, 0.00527385 } + } +}; + +/* coefficients for error estimation + while using cubic Bézier curves for approximation + 1/4 <= b/a <= 1 */ +static const double coeffs3High[2][4][4] = { + { + { 0.0899116, -19.2349, -4.11711, 0.183362 }, + { 0.138148, -1.45804, 1.32044, 1.38474 }, + { 0.230903, -0.450262, 0.219963, 0.414038 }, + { 0.0590565, -0.101062, 0.0430592, 0.0204699 } + }, + { + { 0.0164649, 9.89394, 0.0919496, 0.00760802 }, + { 0.0191603, -0.0322058, 0.0134667, -0.0825018 }, + { 0.0156192, -0.017535, 0.00326508, -0.228157 }, + { -0.0236752, 0.0405821, -0.0173086, 0.176187 } + } +}; + +/* safety factor to convert the "best" error approximation + into a "max bound" error */ +static const double safety3[] = { + 0.001, 4.98, 0.207, 0.0067 +}; + +/* The code below is from the OpenVG 1.1 Spec + * Section 18.4 */ + +/* Given: Points (x0, y0) and (x1, y1) + * Return: TRUE if a solution exists, FALSE otherwise + * Circle centers are written to (cx0, cy0) and (cx1, cy1) + */ +static VGboolean +find_unit_circles(double x0, double y0, double x1, double y1, + double *cx0, double *cy0, + double *cx1, double *cy1) +{ + /* Compute differences and averages */ + double dx = x0 - x1; + double dy = y0 - y1; + double xm = (x0 + x1)/2; + double ym = (y0 + y1)/2; + double dsq, disc, s, sdx, sdy; + + /* Solve for intersecting unit circles */ + dsq = dx*dx + dy*dy; + if (dsq == 0.0) return VG_FALSE; /* Points are coincident */ + disc = 1.0/dsq - 1.0/4.0; + + /* the precision we care about here is around float so if we're + * around the float defined zero then make it official to avoid + * precision problems later on */ + if (floatIsZero(disc)) + disc = 0.0; + + if (disc < 0.0) return VG_FALSE; /* Points are too far apart */ + s = sqrt(disc); + sdx = s*dx; + sdy = s*dy; + *cx0 = xm + sdy; + *cy0 = ym - sdx; + *cx1 = xm - sdy; + *cy1 = ym + sdx; + return VG_TRUE; +} + + +/* Given: Ellipse parameters rh, rv, rot (in degrees), + * endpoints (x0, y0) and (x1, y1) + * Return: TRUE if a solution exists, FALSE otherwise + * Ellipse centers are written to (cx0, cy0) and (cx1, cy1) + */ +static VGboolean +find_ellipses(double rh, double rv, double rot, + double x0, double y0, double x1, double y1, + double *cx0, double *cy0, double *cx1, double *cy1) +{ + double COS, SIN, x0p, y0p, x1p, y1p, pcx0, pcy0, pcx1, pcy1; + /* Convert rotation angle from degrees to radians */ + rot *= M_PI/180.0; + /* Pre-compute rotation matrix entries */ + COS = cos(rot); SIN = sin(rot); + /* Transform (x0, y0) and (x1, y1) into unit space */ + /* using (inverse) rotate, followed by (inverse) scale */ + x0p = (x0*COS + y0*SIN)/rh; + y0p = (-x0*SIN + y0*COS)/rv; + x1p = (x1*COS + y1*SIN)/rh; + y1p = (-x1*SIN + y1*COS)/rv; + if (!find_unit_circles(x0p, y0p, x1p, y1p, + &pcx0, &pcy0, &pcx1, &pcy1)) { + return VG_FALSE; + } + /* Transform back to original coordinate space */ + /* using (forward) scale followed by (forward) rotate */ + pcx0 *= rh; pcy0 *= rv; + pcx1 *= rh; pcy1 *= rv; + *cx0 = pcx0*COS - pcy0*SIN; + *cy0 = pcx0*SIN + pcy0*COS; + *cx1 = pcx1*COS - pcy1*SIN; + *cy1 = pcx1*SIN + pcy1*COS; + return VG_TRUE; +} + +static INLINE VGboolean +try_to_fix_radii(struct arc *arc) +{ + double COS, SIN, rot, x0p, y0p, x1p, y1p; + double dx, dy, dsq, scale; + + /* Convert rotation angle from degrees to radians */ + rot = DEGREES_TO_RADIANS(arc->theta); + + /* Pre-compute rotation matrix entries */ + COS = cos(rot); SIN = sin(rot); + + /* Transform (x0, y0) and (x1, y1) into unit space */ + /* using (inverse) rotate, followed by (inverse) scale */ + x0p = (arc->x1*COS + arc->y1*SIN)/arc->a; + y0p = (-arc->x1*SIN + arc->y1*COS)/arc->b; + x1p = (arc->x2*COS + arc->y2*SIN)/arc->a; + y1p = (-arc->x2*SIN + arc->y2*COS)/arc->b; + /* Compute differences and averages */ + dx = x0p - x1p; + dy = y0p - y1p; + + dsq = dx*dx + dy*dy; +#if 0 + if (dsq <= 0.001) { + debug_printf("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaaaaa\n"); + } +#endif + scale = 1/(2/sqrt(dsq)); + arc->a *= scale; + arc->b *= scale; + return VG_TRUE; +} + +static INLINE double vector_normalize(double *v) +{ + double sq = v[0] * v[0] + v[1] * v[1]; + return sqrt(sq); +} +static INLINE double vector_orientation(double *v) +{ + double norm = vector_normalize(v); + double cosa = v[0] / norm; + double sina = v[1] / norm; + return (sina>=0 ? acos(cosa) : 2*M_PI - acos(cosa)); +} +static INLINE double vector_dot(double *v0, + double *v1) +{ + return v0[0] * v1[0] + v0[1] * v1[1]; +} + +static INLINE double vector_angles(double *v0, + double *v1) +{ + double dot = vector_dot(v0, v1); + double norm0 = vector_normalize(v0); + double norm1 = vector_normalize(v1); + + return acos(dot / (norm0 * norm1)); +} + +static VGboolean find_angles(struct arc *arc) +{ + double vec0[2], vec1[2]; + double lambda1, lambda2; + double angle; + struct matrix matrix; + + if (floatIsZero(arc->a) || floatIsZero(arc->b)) { + return VG_FALSE; + } + /* map the points to an identity circle */ + matrix_load_identity(&matrix); + matrix_scale(&matrix, 1.f, arc->a/arc->b); + matrix_rotate(&matrix, -arc->theta); + matrix_map_point(&matrix, + arc->x1, arc->y1, + &arc->x1, &arc->y1); + matrix_map_point(&matrix, + arc->x2, arc->y2, + &arc->x2, &arc->y2); + matrix_map_point(&matrix, + arc->cx, arc->cy, + &arc->cx, &arc->cy); + +#if DEBUG_ARCS + debug_printf("Matrix 3 [%f, %f, %f| %f, %f, %f| %f, %f, %f]\n", + matrix.m[0], matrix.m[1], matrix.m[2], + matrix.m[3], matrix.m[4], matrix.m[5], + matrix.m[6], matrix.m[7], matrix.m[8]); + debug_printf("Endpoints [%f, %f], [%f, %f]\n", + arc->x1, arc->y1, arc->x2, arc->y2); +#endif + + vec0[0] = arc->x1 - arc->cx; + vec0[1] = arc->y1 - arc->cy; + vec1[0] = arc->x2 - arc->cx; + vec1[1] = arc->y2 - arc->cy; + +#if DEBUG_ARCS + debug_printf("Vec is [%f, %f], [%f, %f], [%f, %f]\n", + vec0[0], vec0[1], vec1[0], vec1[1], arc->cx, arc->cy); +#endif + + lambda1 = vector_orientation(vec0); + + if (isnan(lambda1)) + lambda1 = 0.f; + + if (arc->type == VG_SCWARC_TO || + arc->type == VG_SCCWARC_TO) + angle = vector_angles(vec0, vec1); + else if (arc->type == VG_LCWARC_TO || + arc->type == VG_LCCWARC_TO) { + angle = 2*M_PI - vector_angles(vec0, vec1); + } else + abort(); + + if (isnan(angle)) + angle = M_PI; + + + if (arc->type == VG_SCWARC_TO || + arc->type == VG_LCWARC_TO) + lambda2 = lambda1 - angle; + else + lambda2 = lambda1 + angle; + +#if DEBUG_ARCS + debug_printf("Angle is %f and (%f, %f)\n", angle, lambda1, lambda2); +#endif + +#if 0 + arc->eta1 = atan2(sin(lambda1) / arc->b, + cos(lambda1) / arc->a); + arc->eta2 = atan2(sin(lambda2) / arc->b, + cos(lambda2) / arc->a); + + /* make sure we have eta1 <= eta2 <= eta1 + 2 PI */ + arc->eta2 -= two_pi * floor((arc->eta2 - arc->eta1) / two_pi); + + /* the preceding correction fails if we have exactly et2 - eta1 = 2 PI + it reduces the interval to zero length */ + if ((lambda2 - lambda1 > M_PI) && (arc->eta2 - arc->eta1 < M_PI)) { + arc->eta2 += 2 * M_PI; + } +#else + arc->eta1 = lambda1; + arc->eta2 = lambda2; +#endif + + return VG_TRUE; +} + +#if DEBUG_ARCS +static void check_endpoints(struct arc *arc) +{ + double x1, y1, x2, y2; + + double a_cos_eta1 = arc->a * cos(arc->eta1); + double b_sin_eta1 = arc->b * sin(arc->eta1); + x1 = arc->cx + a_cos_eta1 * arc->cos_theta - + b_sin_eta1 * arc->sin_theta; + y1 = arc->cy + a_cos_eta1 * arc->sin_theta + + b_sin_eta1 * arc->cos_theta; + + double a_cos_eta2 = arc->a * cos(arc->eta2); + double b_sin_eta2 = arc->b * sin(arc->eta2); + x2 = arc->cx + a_cos_eta2 * arc->cos_theta - + b_sin_eta2 * arc->sin_theta; + y2 = arc->cy + a_cos_eta2 * arc->sin_theta + + b_sin_eta2 * arc->cos_theta; + + debug_printf("Computed (%f, %f), (%f, %f)\n", + x1, y1, x2, y2); + debug_printf("Real (%f, %f), (%f, %f)\n", + arc->x1, arc->y1, + arc->x2, arc->y2); +} +#endif + +void arc_init(struct arc *arc, + VGPathSegment type, + VGfloat x1, VGfloat y1, + VGfloat x2, VGfloat y2, + VGfloat rh, VGfloat rv, + VGfloat rot) +{ + assert(type == VG_SCCWARC_TO || + type == VG_SCWARC_TO || + type == VG_LCCWARC_TO || + type == VG_LCWARC_TO); + arc->type = type; + arc->x1 = x1; + arc->y1 = y1; + arc->x2 = x2; + arc->y2 = y2; + arc->a = rh; + arc->b = rv; + arc->theta = rot; + arc->cos_theta = cos(arc->theta); + arc->sin_theta = sin(arc->theta); + { + double cx0, cy0, cx1, cy1; + double cx, cy; + arc->is_valid = find_ellipses(rh, rv, rot, x1, y1, x2, y2, + &cx0, &cy0, &cx1, &cy1); + + if (!arc->is_valid && try_to_fix_radii(arc)) { + rh = arc->a; + rv = arc->b; + arc->is_valid = + find_ellipses(rh, rv, rot, x1, y1, x2, y2, + &cx0, &cy0, &cx1, &cy1); + } + + if (type == VG_SCWARC_TO || + type == VG_LCCWARC_TO) { + cx = cx1; + cy = cy1; + } else { + cx = cx0; + cy = cy0; + } +#if DEBUG_ARCS + debug_printf("Centers are : (%f, %f) , (%f, %f). Real (%f, %f)\n", + cx0, cy0, cx1, cy1, cx, cy); +#endif + arc->cx = cx; + arc->cy = cy; + if (arc->is_valid) { + arc->is_valid = find_angles(arc); +#if DEBUG_ARCS + check_endpoints(arc); +#endif + /* remap a few points. find_angles requires + * rot in angles, the rest of the code + * will need them in radians. and find_angles + * modifies the center to match an identity + * circle so lets reset it */ + arc->theta = DEGREES_TO_RADIANS(rot); + arc->cos_theta = cos(arc->theta); + arc->sin_theta = sin(arc->theta); + arc->cx = cx; + arc->cy = cy; + } + } +} + +static INLINE double rational_function(double x, const double *c) +{ + return (x * (x * c[0] + c[1]) + c[2]) / (x + c[3]); +} + +static double estimate_error(struct arc *arc, + double etaA, double etaB) +{ + double eta = 0.5 * (etaA + etaB); + + double x = arc->b / arc->a; + double dEta = etaB - etaA; + double cos2 = cos(2 * eta); + double cos4 = cos(4 * eta); + double cos6 = cos(6 * eta); + double c0, c1; + + /* select the right coeficients set according to degree and b/a */ + const double (*coeffs)[4][4]; + const double *safety; + coeffs = (x < 0.25) ? coeffs3Low : coeffs3High; + safety = safety3; + + c0 = rational_function(x, coeffs[0][0]) + + cos2 * rational_function(x, coeffs[0][1]) + + cos4 * rational_function(x, coeffs[0][2]) + + cos6 * rational_function(x, coeffs[0][3]); + + c1 = rational_function(x, coeffs[1][0]) + + cos2 * rational_function(x, coeffs[1][1]) + + cos4 * rational_function(x, coeffs[1][2]) + + cos6 * rational_function(x, coeffs[1][3]); + + return rational_function(x, safety) * arc->a * exp(c0 + c1 * dEta); +} + +struct arc_cb { + void (*move)(struct arc_cb *cb, VGfloat x, VGfloat y); + void (*point)(struct arc_cb *cb, VGfloat x, VGfloat y); + void (*bezier)(struct arc_cb *cb, struct bezier *bezier); + + void *user_data; +}; + +static void cb_null_move(struct arc_cb *cb, VGfloat x, VGfloat y) +{ +} + +static void polygon_point(struct arc_cb *cb, VGfloat x, VGfloat y) +{ + struct polygon *poly = (struct polygon*)cb->user_data; + polygon_vertex_append(poly, x, y); +} + +static void polygon_bezier(struct arc_cb *cb, struct bezier *bezier) +{ + struct polygon *poly = (struct polygon*)cb->user_data; + bezier_add_to_polygon(bezier, poly); +} + +static void stroke_point(struct arc_cb *cb, VGfloat x, VGfloat y) +{ + struct stroker *stroker = (struct stroker*)cb->user_data; + stroker_line_to(stroker, x, y); +} + +static void stroke_curve(struct arc_cb *cb, struct bezier *bezier) +{ + struct stroker *stroker = (struct stroker*)cb->user_data; + stroker_curve_to(stroker, + bezier->x2, bezier->y2, + bezier->x3, bezier->y3, + bezier->x4, bezier->y4); +} + +static void stroke_emit_point(struct arc_cb *cb, VGfloat x, VGfloat y) +{ + struct stroker *stroker = (struct stroker*)cb->user_data; + stroker_emit_line_to(stroker, x, y); +} + +static void stroke_emit_curve(struct arc_cb *cb, struct bezier *bezier) +{ + struct stroker *stroker = (struct stroker*)cb->user_data; + stroker_emit_curve_to(stroker, + bezier->x2, bezier->y2, + bezier->x3, bezier->y3, + bezier->x4, bezier->y4); +} + +static void arc_path_move(struct arc_cb *cb, VGfloat x, VGfloat y) +{ + struct path *path = (struct path*)cb->user_data; + path_move_to(path, x, y); +} + +static void arc_path_point(struct arc_cb *cb, VGfloat x, VGfloat y) +{ + struct path *path = (struct path*)cb->user_data; + path_line_to(path, x, y); +} + +static void arc_path_bezier(struct arc_cb *cb, struct bezier *bezier) +{ + struct path *path = (struct path*)cb->user_data; + path_cubic_to(path, + bezier->x2, bezier->y2, + bezier->x3, bezier->y3, + bezier->x4, bezier->y4); +} + +static INLINE int num_beziers_needed(struct arc *arc) +{ + double threshold = 0.05; + VGboolean found = VG_FALSE; + int n = 1; + double min_eta, max_eta; + + min_eta = MIN2(arc->eta1, arc->eta2); + max_eta = MAX2(arc->eta1, arc->eta2); + + while ((! found) && (n < 1024)) { + double d_eta = (max_eta - min_eta) / n; + if (d_eta <= 0.5 * M_PI) { + double eta_b = min_eta; + found = VG_TRUE; + for (int i = 0; found && (i < n); ++i) { + double etaA = eta_b; + eta_b += d_eta; + found = (estimate_error(arc, etaA, eta_b) <= threshold); + } + } + n = n << 1; + } + + return n; +} + +static void arc_to_beziers(struct arc *arc, + struct arc_cb cb, + struct matrix *matrix) +{ + int n = 1; + double d_eta, eta_b, cos_eta_b, + sin_eta_b, a_cos_eta_b, b_sin_eta_b, a_sin_eta_b, + b_cos_eta_b, x_b, y_b, x_b_dot, y_b_dot, lx, ly; + double t, alpha; + + { /* always move to the start of the arc */ + VGfloat x = arc->x1; + VGfloat y = arc->y1; + matrix_map_point(matrix, x, y, &x, &y); + cb.move(&cb, x, y); + } + + if (!arc->is_valid) { + VGfloat x = arc->x2; + VGfloat y = arc->y2; + matrix_map_point(matrix, x, y, &x, &y); + cb.point(&cb, x, y); + return; + } + + /* find the number of Bézier curves needed */ + n = num_beziers_needed(arc); + + d_eta = (arc->eta2 - arc->eta1) / n; + eta_b = arc->eta1; + + cos_eta_b = cos(eta_b); + sin_eta_b = sin(eta_b); + a_cos_eta_b = arc->a * cos_eta_b; + b_sin_eta_b = arc->b * sin_eta_b; + a_sin_eta_b = arc->a * sin_eta_b; + b_cos_eta_b = arc->b * cos_eta_b; + x_b = arc->cx + a_cos_eta_b * arc->cos_theta - + b_sin_eta_b * arc->sin_theta; + y_b = arc->cy + a_cos_eta_b * arc->sin_theta + + b_sin_eta_b * arc->cos_theta; + x_b_dot = -a_sin_eta_b * arc->cos_theta - + b_cos_eta_b * arc->sin_theta; + y_b_dot = -a_sin_eta_b * arc->sin_theta + + b_cos_eta_b * arc->cos_theta; + + { + VGfloat x = x_b, y = y_b; + matrix_map_point(matrix, x, y, &x, &y); + cb.point(&cb, x, y); + } + lx = x_b; + ly = y_b; + + t = tan(0.5 * d_eta); + alpha = sin(d_eta) * (sqrt(4 + 3 * t * t) - 1) / 3; + + for (int i = 0; i < n; ++i) { + struct bezier bezier; + double xA = x_b; + double yA = y_b; + double xADot = x_b_dot; + double yADot = y_b_dot; + + eta_b += d_eta; + cos_eta_b = cos(eta_b); + sin_eta_b = sin(eta_b); + a_cos_eta_b = arc->a * cos_eta_b; + b_sin_eta_b = arc->b * sin_eta_b; + a_sin_eta_b = arc->a * sin_eta_b; + b_cos_eta_b = arc->b * cos_eta_b; + x_b = arc->cx + a_cos_eta_b * arc->cos_theta - + b_sin_eta_b * arc->sin_theta; + y_b = arc->cy + a_cos_eta_b * arc->sin_theta + + b_sin_eta_b * arc->cos_theta; + x_b_dot = -a_sin_eta_b * arc->cos_theta - + b_cos_eta_b * arc->sin_theta; + y_b_dot = -a_sin_eta_b * arc->sin_theta + + b_cos_eta_b * arc->cos_theta; + + bezier_init(&bezier, + lx, ly, + (float) (xA + alpha * xADot), (float) (yA + alpha * yADot), + (float) (x_b - alpha * x_b_dot), (float) (y_b - alpha * y_b_dot), + (float) x_b, (float) y_b); +#if 0 + debug_printf("%d) Bezier (%f, %f), (%f, %f), (%f, %f), (%f, %f)\n", + i, + bezier.x1, bezier.y1, + bezier.x2, bezier.y2, + bezier.x3, bezier.y3, + bezier.x4, bezier.y4); +#endif + bezier_transform(&bezier, matrix); + cb.bezier(&cb, &bezier); + lx = x_b; + ly = y_b; + } +} + + +void arc_add_to_polygon(struct arc *arc, + struct polygon *poly, + struct matrix *matrix) +{ + struct arc_cb cb; + + cb.move = cb_null_move; + cb.point = polygon_point; + cb.bezier = polygon_bezier; + cb.user_data = poly; + + arc_to_beziers(arc, cb, matrix); +} + +void arc_stroke_cb(struct arc *arc, + struct stroker *stroke, + struct matrix *matrix) +{ + struct arc_cb cb; + + cb.move = cb_null_move; + cb.point = stroke_point; + cb.bezier = stroke_curve; + cb.user_data = stroke; + + arc_to_beziers(arc, cb, matrix); +} + +void arc_stroker_emit(struct arc *arc, + struct stroker *stroker, + struct matrix *matrix) +{ + struct arc_cb cb; + + cb.move = cb_null_move; + cb.point = stroke_emit_point; + cb.bezier = stroke_emit_curve; + cb.user_data = stroker; + + arc_to_beziers(arc, cb, matrix); +} + +void arc_to_path(struct arc *arc, + struct path *path, + struct matrix *matrix) +{ + struct arc_cb cb; + + cb.move = arc_path_move; + cb.point = arc_path_point; + cb.bezier = arc_path_bezier; + cb.user_data = path; + + arc_to_beziers(arc, cb, matrix); +} diff --git a/src/gallium/state_trackers/vega/arc.h b/src/gallium/state_trackers/vega/arc.h new file mode 100644 index 00000000000..3205cd5021d --- /dev/null +++ b/src/gallium/state_trackers/vega/arc.h @@ -0,0 +1,80 @@ +/************************************************************************** + * + * 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 ARC_H +#define ARC_H + +#include "VG/openvg.h" + +struct polygon; +struct matrix; +struct stroker; +struct path; + +struct arc { + VGPathSegment type; + + VGfloat cx, cy; + + VGfloat a, b; + + VGfloat theta; + VGfloat cos_theta, sin_theta; + + VGfloat eta1; + VGfloat eta2; + + VGfloat x1, y1, x2, y2; + + VGboolean is_valid; +}; + +void arc_init(struct arc *arc, + VGPathSegment type, + VGfloat x1, VGfloat y1, + VGfloat x2, VGfloat y2, + VGfloat rh, VGfloat rv, + VGfloat rot); + +void arc_add_to_polygon(struct arc *arc, + struct polygon *poly, + struct matrix *matrix); + + +void arc_to_path(struct arc *arc, + struct path *p, + struct matrix *matrix); + +void arc_stroke_cb(struct arc *arc, + struct stroker *stroke, + struct matrix *matrix); + +void arc_stroker_emit(struct arc *arc, + struct stroker *stroke, + struct matrix *matrix); + + +#endif diff --git a/src/gallium/state_trackers/vega/asm_fill.h b/src/gallium/state_trackers/vega/asm_fill.h new file mode 100644 index 00000000000..2f394ad6c55 --- /dev/null +++ b/src/gallium/state_trackers/vega/asm_fill.h @@ -0,0 +1,246 @@ +/************************************************************************** + * + * 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 ASM_FILL_H +#define ASM_FILL_H + +static const char solid_fill_asm[] = + "MOV %s, CONST[0]\n"; + + +static const char linear_grad_asm[] = + "MOV TEMP[0].xy, IN[0]\n" + "MOV TEMP[0].z, CONST[1].yyyy\n" + "DP3 TEMP[1], CONST[2], TEMP[0]\n" + "DP3 TEMP[2], CONST[3], TEMP[0]\n" + "DP3 TEMP[3], CONST[4], TEMP[0]\n" + "RCP TEMP[3], TEMP[3]\n" + "MUL TEMP[1], TEMP[1], TEMP[3]\n" + "MUL TEMP[2], TEMP[2], TEMP[3]\n" + "MOV TEMP[4].x, TEMP[1]\n" + "MOV TEMP[4].y, TEMP[2]\n" + "MUL TEMP[0], CONST[0].yyyy, TEMP[4].yyyy\n" + "MAD TEMP[1], CONST[0].xxxx, TEMP[4].xxxx, TEMP[0]\n" + "MUL TEMP[2], TEMP[1], CONST[0].zzzz\n" + "TEX %s, TEMP[2], SAMP[0], 1D\n"; + +static const char radial_grad_asm[] = + "MOV TEMP[0].xy, IN[0]\n" + "MOV TEMP[0].z, CONST[1].yyyy\n" + "DP3 TEMP[1], CONST[2], TEMP[0]\n" + "DP3 TEMP[2], CONST[3], TEMP[0]\n" + "DP3 TEMP[3], CONST[4], TEMP[0]\n" + "RCP TEMP[3], TEMP[3]\n" + "MUL TEMP[1], TEMP[1], TEMP[3]\n" + "MUL TEMP[2], TEMP[2], TEMP[3]\n" + "MOV TEMP[5].x, TEMP[1]\n" + "MOV TEMP[5].y, TEMP[2]\n" + "MUL TEMP[0], CONST[0].yyyy, TEMP[5].yyyy\n" + "MAD TEMP[1], CONST[0].xxxx, TEMP[5].xxxx, TEMP[0]\n" + "ADD TEMP[1], TEMP[1], TEMP[1]\n" + "MUL TEMP[3], TEMP[5].yyyy, TEMP[5].yyyy\n" + "MAD TEMP[4], TEMP[5].xxxx, TEMP[5].xxxx, TEMP[3]\n" + "MOV TEMP[4], -TEMP[4]\n" + "MUL TEMP[2], CONST[0].zzzz, TEMP[4]\n" + "MUL TEMP[0], CONST[1].wwww, TEMP[2]\n" + "MUL TEMP[3], TEMP[1], TEMP[1]\n" + "SUB TEMP[2], TEMP[3], TEMP[0]\n" + "RSQ TEMP[2], |TEMP[2]|\n" + "RCP TEMP[2], TEMP[2]\n" + "SUB TEMP[1], TEMP[2], TEMP[1]\n" + "ADD TEMP[0], CONST[0].zzzz, CONST[0].zzzz\n" + "RCP TEMP[0], TEMP[0]\n" + "MUL TEMP[2], TEMP[1], TEMP[0]\n" + "TEX %s, TEMP[2], SAMP[0], 1D\n"; + +static const char pattern_asm[] = + "MOV TEMP[0].xy, IN[0]\n" + "MOV TEMP[0].z, CONST[1].yyyy\n" + "DP3 TEMP[1], CONST[2], TEMP[0]\n" + "DP3 TEMP[2], CONST[3], TEMP[0]\n" + "DP3 TEMP[3], CONST[4], TEMP[0]\n" + "RCP TEMP[3], TEMP[3]\n" + "MUL TEMP[1], TEMP[1], TEMP[3]\n" + "MUL TEMP[2], TEMP[2], TEMP[3]\n" + "MOV TEMP[4].x, TEMP[1]\n" + "MOV TEMP[4].y, TEMP[2]\n" + "RCP TEMP[0], CONST[1].zwzw\n" + "MOV TEMP[1], TEMP[4]\n" + "MUL TEMP[1].x, TEMP[1], TEMP[0]\n" + "MUL TEMP[1].y, TEMP[1], TEMP[0]\n" + "TEX %s, TEMP[1], SAMP[0], 2D\n"; + + +static const char mask_asm[] = + "TEX TEMP[1], IN[0], SAMP[1], 2D\n" + "MUL TEMP[0].w, TEMP[0].wwww, TEMP[1].wwww\n" + "MOV %s, TEMP[0]\n"; + + +static const char image_normal_asm[] = + "TEX %s, IN[1], SAMP[3], 2D\n"; + +static const char image_multiply_asm[] = + "TEX TEMP[1], IN[1], SAMP[3], 2D\n" + "MUL %s, TEMP[0], TEMP[1]\n"; + +static const char image_stencil_asm[] = + "TEX TEMP[1], IN[1], SAMP[3], 2D\n" + "MUL %s, TEMP[0], TEMP[1]\n"; + + +#define EXTENDED_BLEND_OVER \ + "SUB TEMP[3], CONST[1].yyyy, TEMP[1].wwww\n" \ + "SUB TEMP[4], CONST[1].yyyy, TEMP[0].wwww\n" \ + "MUL TEMP[3], TEMP[0], TEMP[3]\n" \ + "MUL TEMP[4], TEMP[1], TEMP[4]\n" \ + "ADD TEMP[3], TEMP[3], TEMP[4]\n" + +static const char blend_multiply_asm[] = + "TEX TEMP[1], IN[0], SAMP[2], 2D\n" + EXTENDED_BLEND_OVER + "MUL TEMP[4], TEMP[0], TEMP[1]\n" + "ADD TEMP[1], TEMP[4], TEMP[3]\n"/*result.rgb*/ + "MUL TEMP[2], TEMP[0].wwww, TEMP[1].wwww\n" + "ADD TEMP[3], TEMP[0].wwww, TEMP[1].wwww\n" + "SUB TEMP[1].w, TEMP[3], TEMP[2]\n" + "MOV %s, TEMP[1]\n"; +#if 1 +static const char blend_screen_asm[] = + "TEX TEMP[1], IN[0], SAMP[2], 2D\n" + "ADD TEMP[3], TEMP[0], TEMP[1]\n" + "MUL TEMP[2], TEMP[0], TEMP[1]\n" + "SUB %s, TEMP[3], TEMP[2]\n"; +#else +static const char blend_screen_asm[] = + "TEX TEMP[1], IN[0], SAMP[2], 2D\n" + "MOV %s, TEMP[1]\n"; +#endif + +static const char blend_darken_asm[] = + "TEX TEMP[1], IN[0], SAMP[2], 2D\n" + EXTENDED_BLEND_OVER + "MUL TEMP[4], TEMP[0], TEMP[1].wwww\n" + "MUL TEMP[5], TEMP[1], TEMP[0].wwww\n" + "MIN TEMP[4], TEMP[4], TEMP[5]\n" + "ADD TEMP[1], TEMP[3], TEMP[4]\n" + "MUL TEMP[2], TEMP[0].wwww, TEMP[1].wwww\n" + "ADD TEMP[3], TEMP[0].wwww, TEMP[1].wwww\n" + "SUB TEMP[1].w, TEMP[3], TEMP[2]\n" + "MOV %s, TEMP[1]\n"; + +static const char blend_lighten_asm[] = + "TEX TEMP[1], IN[0], SAMP[2], 2D\n" + EXTENDED_BLEND_OVER + "MUL TEMP[4], TEMP[0], TEMP[1].wwww\n" + "MUL TEMP[5], TEMP[1], TEMP[0].wwww\n" + "MAX TEMP[4], TEMP[4], TEMP[5]\n" + "ADD TEMP[1], TEMP[3], TEMP[4]\n" + "MUL TEMP[2], TEMP[0].wwww, TEMP[1].wwww\n" + "ADD TEMP[3], TEMP[0].wwww, TEMP[1].wwww\n" + "SUB TEMP[1].w, TEMP[3], TEMP[2]\n" + "MOV %s, TEMP[1]\n"; + + +static const char premultiply_asm[] = + "MUL TEMP[0].xyz, TEMP[0], TEMP[0].wwww\n"; + +static const char unpremultiply_asm[] = + "TEX TEMP[0], IN[0], SAMP[1], 2D\n"; + + +static const char color_bw_asm[] = + "ADD TEMP[1], CONST[1].yyyy, CONST[1].yyyy\n" + "RCP TEMP[2], TEMP[1]\n" + "ADD TEMP[1], CONST[1].yyyy, TEMP[2]\n" + "ADD TEMP[2].x, TEMP[0].xxxx, TEMP[0].yyyy\n" + "ADD TEMP[2].x, TEMP[0].zzzz, TEMP[0].xxxx\n" + "SGE TEMP[0].xyz, TEMP[2].xxxx, TEMP[1]\n" + "SGE TEMP[0].w, TEMP[0].wwww, TEMP[2].yyyy\n" + "MOV %s, TEMP[0]\n"; + + +struct shader_asm_info { + VGint id; + VGint num_tokens; + const char * txt; + + VGboolean needs_position; + + VGint start_const; + VGint num_consts; + + VGint start_sampler; + VGint num_samplers; + + VGint start_temp; + VGint num_temps; +}; + + +static const struct shader_asm_info shaders_asm[] = { + /* fills */ + {VEGA_SOLID_FILL_SHADER, 40, solid_fill_asm, + VG_FALSE, 0, 1, 0, 0, 0, 0}, + {VEGA_LINEAR_GRADIENT_SHADER, 200, linear_grad_asm, + VG_TRUE, 0, 5, 0, 1, 0, 5}, + {VEGA_RADIAL_GRADIENT_SHADER, 200, radial_grad_asm, + VG_TRUE, 0, 5, 0, 1, 0, 6}, + {VEGA_PATTERN_SHADER, 100, pattern_asm, + VG_TRUE, 1, 4, 0, 1, 0, 5}, + + /* image draw modes */ + {VEGA_IMAGE_NORMAL_SHADER, 200, image_normal_asm, + VG_TRUE, 0, 0, 3, 1, 0, 0}, + {VEGA_IMAGE_MULTIPLY_SHADER, 200, image_multiply_asm, + VG_TRUE, 0, 0, 3, 1, 0, 2}, + {VEGA_IMAGE_STENCIL_SHADER, 200, image_stencil_asm, + VG_TRUE, 0, 0, 3, 1, 0, 2}, + + {VEGA_MASK_SHADER, 100, mask_asm, + VG_TRUE, 0, 0, 1, 1, 0, 2}, + + /* extra blend modes */ + {VEGA_BLEND_MULTIPLY_SHADER, 200, blend_multiply_asm, + VG_TRUE, 1, 1, 2, 1, 0, 5}, + {VEGA_BLEND_SCREEN_SHADER, 200, blend_screen_asm, + VG_TRUE, 0, 0, 2, 1, 0, 4}, + {VEGA_BLEND_DARKEN_SHADER, 200, blend_darken_asm, + VG_TRUE, 1, 1, 2, 1, 0, 6}, + {VEGA_BLEND_LIGHTEN_SHADER, 200, blend_lighten_asm, + VG_TRUE, 1, 1, 2, 1, 0, 6}, + + /* premultiply */ + {VEGA_PREMULTIPLY_SHADER, 100, premultiply_asm, + VG_FALSE, 0, 0, 0, 0, 0, 1}, + {VEGA_UNPREMULTIPLY_SHADER, 100, unpremultiply_asm, + VG_FALSE, 0, 0, 0, 0, 0, 1}, + + /* color transform to black and white */ + {VEGA_BW_SHADER, 150, color_bw_asm, + VG_FALSE, 1, 1, 0, 0, 0, 3}, +}; +#endif diff --git a/src/gallium/state_trackers/vega/asm_filters.h b/src/gallium/state_trackers/vega/asm_filters.h new file mode 100644 index 00000000000..49807b9ab41 --- /dev/null +++ b/src/gallium/state_trackers/vega/asm_filters.h @@ -0,0 +1,117 @@ +/************************************************************************** + * + * 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 ASM_FILTERS_H +#define ASM_FILTERS_H + +static const char color_matrix_asm[] = + "FRAG1.1\n" + "DCL IN[0], GENERIC[0], PERSPECTIVE\n" + "DCL OUT[0], COLOR, CONSTANT\n" + "DCL CONST[0..4], CONSTANT\n" + "DCL TEMP[0..4], CONSTANT\n" + "DCL SAMP[0], CONSTANT\n" + "TEX TEMP[0], IN[0], SAMP[0], 2D\n" + "MOV TEMP[1], TEMP[0].xxxx\n" + "MOV TEMP[2], TEMP[0].yyyy\n" + "MOV TEMP[3], TEMP[0].zzzz\n" + "MOV TEMP[4], TEMP[0].wwww\n" + "MUL TEMP[1], TEMP[1], CONST[0]\n" + "MUL TEMP[2], TEMP[2], CONST[1]\n" + "MUL TEMP[3], TEMP[3], CONST[2]\n" + "MUL TEMP[4], TEMP[4], CONST[3]\n" + "ADD TEMP[0], TEMP[1], CONST[4]\n" + "ADD TEMP[0], TEMP[0], TEMP[2]\n" + "ADD TEMP[0], TEMP[0], TEMP[3]\n" + "ADD TEMP[0], TEMP[0], TEMP[4]\n" + "MOV OUT[0], TEMP[0]\n" + "END\n"; + +static const char convolution_asm[] = + "FRAG1.1\n" + "DCL IN[0], GENERIC[0], PERSPECTIVE\n" + "DCL OUT[0], COLOR, CONSTANT\n" + "DCL TEMP[0..4], CONSTANT\n" + "DCL ADDR[0], CONSTANT\n" + "DCL CONST[0..%d], CONSTANT\n" + "DCL SAMP[0], CONSTANT\n" + "0: MOV TEMP[0], CONST[0].xxxx\n" + "1: MOV TEMP[1], CONST[0].xxxx\n" + "2: BGNLOOP2 :14\n" + "3: SGE TEMP[0].z, TEMP[0].yyyy, CONST[1].xxxx\n" + "4: IF TEMP[0].zzzz :7\n" + "5: BRK\n" + "6: ENDIF\n" + "7: ARL ADDR[0].x, TEMP[0].yyyy\n" + "8: MOV TEMP[3], CONST[ADDR[0]+2]\n" + "9: ADD TEMP[4].xy, IN[0], TEMP[3]\n" + "10: TEX TEMP[2], TEMP[4], SAMP[0], 2D\n" + "11: MOV TEMP[3], CONST[ADDR[0]+%d]\n" + "12: MAD TEMP[1], TEMP[2], TEMP[3], TEMP[1]\n" + "13: ADD TEMP[0].y, TEMP[0].yyyy, CONST[0].yyyy\n" + "14: ENDLOOP2 :2\n" + "15: MAD OUT[0], TEMP[1], CONST[1].yyyy, CONST[1].zzzz\n" + "16: END\n"; + + +static const char lookup_asm[] = + "FRAG1.1\n" + "DCL IN[0], GENERIC[0], PERSPECTIVE\n" + "DCL OUT[0], COLOR, CONSTANT\n" + "DCL TEMP[0..2], CONSTANT\n" + "DCL CONST[0], CONSTANT\n" + "DCL SAMP[0..1], CONSTANT\n" + "TEX TEMP[0], IN[0], SAMP[0], 2D\n" + "MOV TEMP[1], TEMP[0]\n" + /* do red */ + "TEX TEMP[2], TEMP[1].xxxx, SAMP[1], 1D\n" + "MOV TEMP[0].x, TEMP[2].xxxx\n" + /* do blue */ + "TEX TEMP[2], TEMP[1].yyyy, SAMP[1], 1D\n" + "MOV TEMP[0].y, TEMP[2].yyyy\n" + /* do green */ + "TEX TEMP[2], TEMP[1].zzzz, SAMP[1], 1D\n" + "MOV TEMP[0].z, TEMP[2].zzzz\n" + /* do alpha */ + "TEX TEMP[2], TEMP[1].wwww, SAMP[1], 1D\n" + "MOV TEMP[0].w, TEMP[2].wwww\n" + "MOV OUT[0], TEMP[0]\n" + "END\n"; + + +static const char lookup_single_asm[] = + "FRAG1.1\n" + "DCL IN[0], GENERIC[0], PERSPECTIVE\n" + "DCL OUT[0], COLOR, CONSTANT\n" + "DCL TEMP[0..2], CONSTANT\n" + "DCL CONST[0], CONSTANT\n" + "DCL SAMP[0..1], CONSTANT\n" + "TEX TEMP[0], IN[0], SAMP[0], 2D\n" + "TEX TEMP[1], TEMP[0].%s, SAMP[1], 1D\n" + "MOV OUT[0], TEMP[1]\n" + "END\n"; + +#endif diff --git a/src/gallium/state_trackers/vega/asm_util.h b/src/gallium/state_trackers/vega/asm_util.h new file mode 100644 index 00000000000..218e1d166db --- /dev/null +++ b/src/gallium/state_trackers/vega/asm_util.h @@ -0,0 +1,136 @@ +/************************************************************************** + * + * 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 ASM_UTIL_H +#define ASM_UTIL_H + + +static const char pass_through_depth_asm[] = + "FRAG1.1\n" + "DCL IN[0], POSITION, LINEAR\n" + "DCL OUT[0].z, POSITION, CONSTANT\n" + "0: MOV OUT[0].z, IN[0].zzzz\n" + "1: END\n"; + + + +/* μnew = μmask */ +static const char set_mask_asm[] = + "FRAG1.1\n" + "DCL IN[0], GENERIC[0], PERSPECTIVE\n" + "DCL SAMP[0], CONSTANT\n" + "DCL OUT[0], COLOR, CONSTANT\n" + "0: TEX OUT[0], IN[0], SAMP[0], 2D\n"/*umask*/ + "1: END\n"; + +/* μnew = 1 – (1 – μmask)*(1 – μprev) */ +static const char union_mask_asm[] = + "FRAG1.1\n" + "DCL IN[0], GENERIC[0], PERSPECTIVE\n" + "DCL IN[1], POSITION, LINEAR\n" + "DCL CONST[0], CONSTANT\n" + "DCL SAMP[0..1], CONSTANT\n" + "DCL TEMP[0..3], CONSTANT\n" + "DCL OUT[0], COLOR, CONSTANT\n" + "0: TEX TEMP[1], IN[0], SAMP[0], 2D\n"/*umask*/ + "1: TEX TEMP[0], IN[1], SAMP[1], 2D\n"/*uprev*/ + "2: SUB TEMP[2], CONST[0], TEMP[0]\n" + "3: SUB TEMP[3], CONST[0], TEMP[1]\n" + "4: MUL TEMP[0].w, TEMP[2].wwww, TEMP[3].wwww\n" + "5: SUB OUT[0], CONST[0], TEMP[0]\n" + "6: END\n"; + +/* μnew = μmask *μprev */ +static const char intersect_mask_asm[] = + "FRAG1.1\n" + "DCL IN[0], GENERIC[0], PERSPECTIVE\n" + "DCL IN[1], POSITION, LINEAR\n" + "DCL CONST[0], CONSTANT\n" + "DCL SAMP[0..1], CONSTANT\n" + "DCL TEMP[0..1], CONSTANT\n" + "DCL OUT[0], COLOR, CONSTANT\n" + "0: TEX TEMP[0], IN[1], SAMP[1], 2D\n"/*uprev*/ + "1: TEX TEMP[1], IN[0], SAMP[0], 2D\n"/*umask*/ + "2: MUL OUT[0], TEMP[0].wwww, TEMP[1].wwww\n" + "3: END\n"; + +/* μnew = μprev*(1 – μmask) */ +static const char subtract_mask_asm[] = + "FRAG1.1\n" + "DCL IN[0], GENERIC[0], PERSPECTIVE\n" + "DCL IN[1], POSITION, LINEAR\n" + "DCL CONST[0], CONSTANT\n" + "DCL SAMP[0..1], CONSTANT\n" + "DCL TEMP[0..2], CONSTANT\n" + "DCL OUT[0], COLOR, CONSTANT\n" + "0: TEX TEMP[1], IN[0], SAMP[0], 2D\n"/*umask*/ + "1: TEX TEMP[0], IN[1], SAMP[1], 2D\n"/*uprev*/ + "2: SUB TEMP[2], CONST[0], TEMP[1]\n" + "3: MUL OUT[0], TEMP[2].wwww, TEMP[0].wwww\n" + "4: END\n"; + + +static const char vs_plain_asm[] = + "VERT1.1\n" + "DCL IN[0]\n" + "DCL OUT[0], POSITION\n" + "DCL TEMP[0]\n" + "DCL CONST[0..1]\n" + "0: MUL TEMP[0], IN[0], CONST[0]\n" + "1: ADD TEMP[0], TEMP[0], CONST[1]\n" + "2: MOV OUT[0], TEMP[0]\n" + "3: END\n"; + +static const char vs_clear_asm[] = + "VERT1.1\n" + "DCL IN[0]\n" + "DCL IN[1]\n" + "DCL OUT[0], POSITION\n" + "DCL OUT[1], COLOR\n" + "DCL TEMP[0]\n" + "DCL CONST[0..1]\n" + "0: MUL TEMP[0], IN[0], CONST[0]\n" + "1: ADD TEMP[0], TEMP[0], CONST[1]\n" + "2: MOV OUT[0], TEMP[0]\n" + "3: MOV OUT[1], IN[1]\n" + "4: END\n"; + + +static const char vs_texture_asm[] = + "VERT1.1\n" + "DCL IN[0]\n" + "DCL IN[1]\n" + "DCL OUT[0], POSITION\n" + "DCL OUT[1], GENERIC\n" + "DCL TEMP[0]\n" + "DCL CONST[0..1]\n" + "0: MUL TEMP[0], IN[0], CONST[0]\n" + "1: ADD TEMP[0], TEMP[0], CONST[1]\n" + "2: MOV OUT[0], TEMP[0]\n" + "3: MOV OUT[1], IN[1]\n" + "4: END\n"; + +#endif diff --git a/src/gallium/state_trackers/vega/bezier.c b/src/gallium/state_trackers/vega/bezier.c new file mode 100644 index 00000000000..39a7ade0161 --- /dev/null +++ b/src/gallium/state_trackers/vega/bezier.c @@ -0,0 +1,704 @@ +/************************************************************************** + * + * 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 "bezier.h" + +#include "matrix.h" +#include "polygon.h" + +#include "pipe/p_compiler.h" +#include "util/u_debug.h" + +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include <math.h> + +static const float flatness = 0.5; + + +static INLINE void split_left(struct bezier *bez, VGfloat t, struct bezier* left) +{ + left->x1 = bez->x1; + left->y1 = bez->y1; + + left->x2 = bez->x1 + t * (bez->x2 - bez->x1); + left->y2 = bez->y1 + t * (bez->y2 - bez->y1); + + left->x3 = bez->x2 + t * (bez->x3 - bez->x2); + left->y3 = bez->y2 + t * (bez->y3 - bez->y2); + + bez->x3 = bez->x3 + t * (bez->x4 - bez->x3); + bez->y3 = bez->y3 + t * (bez->y4 - bez->y3); + + bez->x2 = left->x3 + t * (bez->x3 - left->x3); + bez->y2 = left->y3 + t * (bez->y3 - left->y3); + + left->x3 = left->x2 + t * (left->x3 - left->x2); + left->y3 = left->y2 + t * (left->y3 - left->y2); + + left->x4 = bez->x1 = left->x3 + t * (bez->x2 - left->x3); + left->y4 = bez->y1 = left->y3 + t * (bez->y2 - left->y3); +} + +static INLINE void split(struct bezier *bez, + struct bezier *first_half, + struct bezier *second_half) +{ + double c = (bez->x2 + bez->x3) * 0.5; + first_half->x2 = (bez->x1 + bez->x2) * 0.5; + second_half->x3 = (bez->x3 + bez->x4) * 0.5; + first_half->x1 = bez->x1; + second_half->x4 = bez->x4; + first_half->x3 = (first_half->x2 + c) * 0.5; + second_half->x2 = (second_half->x3 + c) * 0.5; + first_half->x4 = second_half->x1 = + (first_half->x3 + second_half->x2) * 0.5; + + c = (bez->y2 + bez->y3) / 2; + first_half->y2 = (bez->y1 + bez->y2) * 0.5; + second_half->y3 = (bez->y3 + bez->y4) * 0.5; + first_half->y1 = bez->y1; + second_half->y4 = bez->y4; + first_half->y3 = (first_half->y2 + c) * 0.5; + second_half->y2 = (second_half->y3 + c) * 0.5; + first_half->y4 = second_half->y1 = + (first_half->y3 + second_half->y2) * 0.5; +} + +struct polygon * bezier_to_polygon(struct bezier *bez) +{ + struct polygon *poly = polygon_create(64); + polygon_vertex_append(poly, bez->x1, bez->y1); + bezier_add_to_polygon(bez, poly); + return poly; +} + +void bezier_add_to_polygon(const struct bezier *bez, + struct polygon *poly) +{ + struct bezier beziers[32]; + struct bezier *b; + + beziers[0] = *bez; + b = beziers; + + while (b >= beziers) { + double y4y1 = b->y4 - b->y1; + double x4x1 = b->x4 - b->x1; + double l = ABS(x4x1) + ABS(y4y1); + double d; + if (l > 1.f) { + d = ABS((x4x1)*(b->y1 - b->y2) - (y4y1)*(b->x1 - b->x2)) + + ABS((x4x1)*(b->y1 - b->y3) - (y4y1)*(b->x1 - b->x3)); + } else { + d = ABS(b->x1 - b->x2) + ABS(b->y1 - b->y2) + + ABS(b->x1 - b->x3) + ABS(b->y1 - b->y3); + l = 1.; + } + if (d < flatness*l || b == beziers + 31) { + /* good enough, we pop it off and add the endpoint */ + polygon_vertex_append(poly, b->x4, b->y4); + --b; + } else { + /* split, second half of the bezier goes lower into the stack */ + split(b, b+1, b); + ++b; + } + } +} + +static void add_if_close(struct bezier *bez, VGfloat *length, VGfloat error) +{ + struct bezier left, right; /* bez poly splits */ + VGfloat len = 0.0; /* arc length */ + VGfloat chord; /* chord length */ + + len = len + line_length(bez->x1, bez->y1, bez->x2, bez->y2); + len = len + line_length(bez->x2, bez->y2, bez->x3, bez->y3); + len = len + line_length(bez->x3, bez->y3, bez->x4, bez->y4); + + chord = line_length(bez->x1, bez->y1, bez->x4, bez->y4); + + if ((len-chord) > error) { + split(bez, &left, &right); /* split in two */ + add_if_close(&left, length, error); /* try left side */ + add_if_close(&right, length, error); /* try right side */ + return; + } + + *length = *length + len; + + return; +} + +float bezier_length(struct bezier *bez, float error) +{ + VGfloat length = 0.f; + + add_if_close(bez, &length, error); + return length; +} + +void bezier_init(struct bezier *bez, + float x1, float y1, + float x2, float y2, + float x3, float y3, + float x4, float y4) +{ + bez->x1 = x1; + bez->y1 = y1; + bez->x2 = x2; + bez->y2 = y2; + bez->x3 = x3; + bez->y3 = y3; + bez->x4 = x4; + bez->y4 = y4; +#if 0 + debug_printf("bezier in [%f, %f, %f, %f, %f, %f]\n", + x1, y1, x2, y2, x3, y3, x4, y4); +#endif +} + + +static INLINE void bezier_init2v(struct bezier *bez, + float *pt1, + float *pt2, + float *pt3, + float *pt4) +{ + bez->x1 = pt1[0]; + bez->y1 = pt1[1]; + + bez->x2 = pt2[0]; + bez->y2 = pt2[1]; + + bez->x3 = pt3[0]; + bez->y3 = pt3[1]; + + bez->x4 = pt4[0]; + bez->y4 = pt4[1]; +} + + +void bezier_transform(struct bezier *bez, + struct matrix *matrix) +{ + assert(matrix_is_affine(matrix)); + matrix_map_point(matrix, bez->x1, bez->y1, &bez->x1, &bez->y1); + matrix_map_point(matrix, bez->x2, bez->y2, &bez->x2, &bez->y2); + matrix_map_point(matrix, bez->x3, bez->y3, &bez->x3, &bez->y3); + matrix_map_point(matrix, bez->x4, bez->y4, &bez->x4, &bez->y4); +} + +static INLINE void bezier_point_at(const struct bezier *bez, float t, float *pt) +{ + float a, b, c, d; + float m_t; + m_t = 1. - t; + b = m_t * m_t; + c = t * t; + d = c * t; + a = b * m_t; + b *= 3. * t; + c *= 3. * m_t; + pt[0] = a*bez->x1 + b*bez->x2 + c*bez->x3 + d*bez->x4; + pt[1] = a*bez->y1 + b*bez->y2 + c*bez->y3 + d*bez->y4; +} + +static INLINE void bezier_normal_at(const struct bezier *bez, float t, float *norm) +{ + float m_t = 1. - t; + float a = m_t * m_t; + float b = t * m_t; + float c = t * t; + + norm[0] = (bez->y2-bez->y1) * a + (bez->y3-bez->y2) * b + (bez->y4-bez->y3) * c; + norm[1] = -(bez->x2-bez->x1) * a - (bez->x3-bez->x2) * b - (bez->x4-bez->x3) * c; +} + +enum shift_result { + Ok, + Discard, + Split, + Circle +}; + +static enum shift_result good_offset(const struct bezier *b1, + const struct bezier *b2, + float offset, float threshold) +{ + const float o2 = offset*offset; + const float max_dist_line = threshold*offset*offset; + const float max_dist_normal = threshold*offset; + const float spacing = 0.25; + for (float i = spacing; i < 0.99; i += spacing) { + float p1[2],p2[2], d, l; + float normal[2]; + bezier_point_at(b1, i, p1); + bezier_point_at(b2, i, p2); + d = (p1[0] - p2[0])*(p1[0] - p2[0]) + (p1[1] - p2[1])*(p1[1] - p2[1]); + if (ABS(d - o2) > max_dist_line) + return Split; + + bezier_normal_at(b1, i, normal); + l = ABS(normal[0]) + ABS(normal[1]); + if (l != 0.) { + d = ABS(normal[0]*(p1[1] - p2[1]) - normal[1]*(p1[0] - p2[0]) ) / l; + if (d > max_dist_normal) + return Split; + } + } + return Ok; +} + +static INLINE void shift_line_by_normal(float *l, float offset) +{ + float norm[4]; + float tx, ty; + + line_normal(l, norm); + line_normalize(norm); + + tx = (norm[2] - norm[0]) * offset; + ty = (norm[3] - norm[1]) * offset; + l[0] += tx; l[1] += ty; + l[2] += tx; l[3] += ty; +} + +static INLINE VGboolean is_bezier_line(float (*points)[2], int count) +{ + float dx13 = points[2][0] - points[0][0]; + float dy13 = points[2][1] - points[0][1]; + + float dx12 = points[1][0] - points[0][0]; + float dy12 = points[1][1] - points[0][1]; + + debug_assert(count > 2); + + if (count == 3) { + return floatsEqual(dx12 * dy13, dx13 * dy12); + } else if (count == 4) { + float dx14 = points[3][0] - points[0][0]; + float dy14 = points[3][1] - points[0][1]; + + return (floatsEqual(dx12 * dy13, dx13 * dy12) && + floatsEqual(dx12 * dy14, dx14 * dy12)); + } + + return VG_FALSE; +} + +static INLINE void compute_pt_normal(float *pt1, float *pt2, float *res) +{ + float line[4]; + float normal[4]; + line[0] = 0.f; line[1] = 0.f; + line[2] = pt2[0] - pt1[0]; + line[3] = pt2[1] - pt1[1]; + line_normal(line, normal); + line_normalize(normal); + + res[0] = normal[2]; + res[1] = normal[3]; +} + +static enum shift_result shift(const struct bezier *orig, + struct bezier *shifted, + float offset, float threshold) +{ + int map[4]; + VGboolean p1_p2_equal = (orig->x1 == orig->x2 && orig->y1 == orig->y2); + VGboolean p2_p3_equal = (orig->x2 == orig->x3 && orig->y2 == orig->y3); + VGboolean p3_p4_equal = (orig->x3 == orig->x4 && orig->y3 == orig->y4); + + float points[4][2]; + int np = 0; + float bounds[4]; + float points_shifted[4][2]; + float prev_normal[2]; + + points[np][0] = orig->x1; + points[np][1] = orig->y1; + map[0] = 0; + ++np; + if (!p1_p2_equal) { + points[np][0] = orig->x2; + points[np][1] = orig->y2; + ++np; + } + map[1] = np - 1; + if (!p2_p3_equal) { + points[np][0] = orig->x3; + points[np][1] = orig->y3; + ++np; + } + map[2] = np - 1; + if (!p3_p4_equal) { + points[np][0] = orig->x4; + points[np][1] = orig->y4; + ++np; + } + map[3] = np - 1; + if (np == 1) + return Discard; + + /* We need to specialcase lines of 3 or 4 points due to numerical + instability in intersection code below */ + if (np > 2 && is_bezier_line(points, np)) { + float l[4] = { points[0][0], points[0][1], + points[np-1][0], points[np-1][1] }; + float ctrl1[2], ctrl2[2]; + if (floatsEqual(points[0][0], points[np-1][0]) && + floatsEqual(points[0][1], points[np-1][1])) + return Discard; + + shift_line_by_normal(l, offset); + line_point_at(l, 0.33, ctrl1); + line_point_at(l, 0.66, ctrl2); + bezier_init(shifted, l[0], l[1], + ctrl1[0], ctrl1[1], ctrl2[0], ctrl2[1], + l[2], l[3]); + return Ok; + } + + bezier_bounds(orig, bounds); + if (np == 4 && bounds[2] < .1*offset && bounds[3] < .1*offset) { + float l = (orig->x1 - orig->x2)*(orig->x1 - orig->x2) + + (orig->y1 - orig->y2)*(orig->y1 - orig->y1) * + (orig->x3 - orig->x4)*(orig->x3 - orig->x4) + + (orig->y3 - orig->y4)*(orig->y3 - orig->y4); + float dot = (orig->x1 - orig->x2)*(orig->x3 - orig->x4) + + (orig->y1 - orig->y2)*(orig->y3 - orig->y4); + if (dot < 0 && dot*dot < 0.8*l) + /* the points are close and reverse dirction. Approximate the whole + thing by a semi circle */ + return Circle; + } + + compute_pt_normal(points[0], points[1], prev_normal); + + points_shifted[0][0] = points[0][0] + offset * prev_normal[0]; + points_shifted[0][1] = points[0][1] + offset * prev_normal[1]; + + for (int i = 1; i < np - 1; ++i) { + float normal_sum[2], r; + float next_normal[2]; + compute_pt_normal(points[i], points[i + 1], next_normal); + + normal_sum[0] = prev_normal[0] + next_normal[0]; + normal_sum[1] = prev_normal[1] + next_normal[1]; + + r = 1.0 + prev_normal[0] * next_normal[0] + + prev_normal[1] * next_normal[1]; + + if (floatsEqual(r + 1, 1)) { + points_shifted[i][0] = points[i][0] + offset * prev_normal[0]; + points_shifted[i][1] = points[i][1] + offset * prev_normal[1]; + } else { + float k = offset / r; + points_shifted[i][0] = points[i][0] + k * normal_sum[0]; + points_shifted[i][1] = points[i][1] + k * normal_sum[1]; + } + + prev_normal[0] = next_normal[0]; + prev_normal[1] = next_normal[1]; + } + + points_shifted[np - 1][0] = points[np - 1][0] + offset * prev_normal[0]; + points_shifted[np - 1][1] = points[np - 1][1] + offset * prev_normal[1]; + + bezier_init2v(shifted, + points_shifted[map[0]], points_shifted[map[1]], + points_shifted[map[2]], points_shifted[map[3]]); + + return good_offset(orig, shifted, offset, threshold); +} + +static VGboolean make_circle(const struct bezier *b, float offset, struct bezier *o) +{ + float normals[3][2]; + float dist; + float angles[2]; + float sign = 1.f; + int i; + float circle[3][2]; + + normals[0][0] = b->y2 - b->y1; + normals[0][1] = b->x1 - b->x2; + dist = sqrt(normals[0][0]*normals[0][0] + normals[0][1]*normals[0][1]); + if (floatsEqual(dist + 1, 1.f)) + return VG_FALSE; + normals[0][0] /= dist; + normals[0][1] /= dist; + + normals[2][0] = b->y4 - b->y3; + normals[2][1] = b->x3 - b->x4; + dist = sqrt(normals[2][0]*normals[2][0] + normals[2][1]*normals[2][1]); + if (floatsEqual(dist + 1, 1.f)) + return VG_FALSE; + normals[2][0] /= dist; + normals[2][1] /= dist; + + normals[1][0] = b->x1 - b->x2 - b->x3 + b->x4; + normals[1][1] = b->y1 - b->y2 - b->y3 + b->y4; + dist = -1*sqrt(normals[1][0]*normals[1][0] + normals[1][1]*normals[1][1]); + normals[1][0] /= dist; + normals[1][1] /= dist; + + for (i = 0; i < 2; ++i) { + float cos_a = normals[i][0]*normals[i+1][0] + normals[i][1]*normals[i+1][1]; + if (cos_a > 1.) + cos_a = 1.; + if (cos_a < -1.) + cos_a = -1; + angles[i] = acos(cos_a)/M_PI; + } + + if (angles[0] + angles[1] > 1.) { + /* more than 180 degrees */ + normals[1][0] = -normals[1][0]; + normals[1][1] = -normals[1][1]; + angles[0] = 1. - angles[0]; + angles[1] = 1. - angles[1]; + sign = -1.; + } + + circle[0][0] = b->x1 + normals[0][0]*offset; + circle[0][1] = b->y1 + normals[0][1]*offset; + + circle[1][0] = 0.5*(b->x1 + b->x4) + normals[1][0]*offset; + circle[1][1] = 0.5*(b->y1 + b->y4) + normals[1][1]*offset; + + circle[2][0] = b->x4 + normals[2][0]*offset; + circle[2][1] = b->y4 + normals[2][1]*offset; + + for (i = 0; i < 2; ++i) { + float kappa = 2.*KAPPA * sign * offset * angles[i]; + + o->x1 = circle[i][0]; + o->y1 = circle[i][1]; + o->x2 = circle[i][0] - normals[i][1]*kappa; + o->y2 = circle[i][1] + normals[i][0]*kappa; + o->x3 = circle[i+1][0] + normals[i+1][1]*kappa; + o->y3 = circle[i+1][1] - normals[i+1][0]*kappa; + o->x4 = circle[i+1][0]; + o->y4 = circle[i+1][1]; + + ++o; + } + return VG_TRUE; +} + +int bezier_translate_by_normal(struct bezier *bez, + struct bezier *curves, + int max_curves, + float normal_len, + float threshold) +{ + struct bezier beziers[10]; + struct bezier *b, *o; + + /* fixme: this should really be floatsEqual */ + if (bez->x1 == bez->x2 && bez->x1 == bez->x3 && bez->x1 == bez->x4 && + bez->y1 == bez->y2 && bez->y1 == bez->y3 && bez->y1 == bez->y4) + return 0; + + --max_curves; +redo: + beziers[0] = *bez; + b = beziers; + o = curves; + + while (b >= beziers) { + int stack_segments = b - beziers + 1; + enum shift_result res; + if ((stack_segments == 10) || (o - curves == max_curves - stack_segments)) { + threshold *= 1.5; + if (threshold > 2.) + goto give_up; + goto redo; + } + res = shift(b, o, normal_len, threshold); + if (res == Discard) { + --b; + } else if (res == Ok) { + ++o; + --b; + continue; + } else if (res == Circle && max_curves - (o - curves) >= 2) { + /* add semi circle */ + if (make_circle(b, normal_len, o)) + o += 2; + --b; + } else { + split(b, b+1, b); + ++b; + } + } + +give_up: + while (b >= beziers) { + enum shift_result res = shift(b, o, normal_len, threshold); + + /* if res isn't Ok or Split then *o is undefined */ + if (res == Ok || res == Split) + ++o; + + --b; + } + + debug_assert(o - curves <= max_curves); + return o - curves; +} + +void bezier_bounds(const struct bezier *bez, + float *bounds/*x/y/width/height*/) +{ + float xmin = bez->x1; + float xmax = bez->x1; + float ymin = bez->y1; + float ymax = bez->y1; + + if (bez->x2 < xmin) + xmin = bez->x2; + else if (bez->x2 > xmax) + xmax = bez->x2; + if (bez->x3 < xmin) + xmin = bez->x3; + else if (bez->x3 > xmax) + xmax = bez->x3; + if (bez->x4 < xmin) + xmin = bez->x4; + else if (bez->x4 > xmax) + xmax = bez->x4; + + if (bez->y2 < ymin) + ymin = bez->y2; + else if (bez->y2 > ymax) + ymax = bez->y2; + if (bez->y3 < ymin) + ymin = bez->y3; + else if (bez->y3 > ymax) + ymax = bez->y3; + if (bez->y4 < ymin) + ymin = bez->y4; + else if (bez->y4 > ymax) + ymax = bez->y4; + + bounds[0] = xmin; /* x */ + bounds[1] = ymin; /* y */ + bounds[2] = xmax - xmin; /* width */ + bounds[3] = ymax - ymin; /* height */ +} + +void bezier_start_tangent(const struct bezier *bez, + float *tangent) +{ + tangent[0] = bez->x1; + tangent[1] = bez->y1; + tangent[2] = bez->x2; + tangent[3] = bez->y2; + + if (null_line(tangent)) { + tangent[0] = bez->x1; + tangent[1] = bez->y1; + tangent[2] = bez->x3; + tangent[3] = bez->y3; + } + if (null_line(tangent)) { + tangent[0] = bez->x1; + tangent[1] = bez->y1; + tangent[2] = bez->x4; + tangent[3] = bez->y4; + } +} + + +static INLINE VGfloat bezier_t_at_length(struct bezier *bez, + VGfloat at_length, + VGfloat error) +{ + VGfloat len = bezier_length(bez, error); + VGfloat t = 1.0; + VGfloat last_bigger = 1.; + + if (at_length > len || floatsEqual(at_length, len)) + return t; + + if (floatIsZero(at_length)) + return 0.f; + + t *= 0.5; + while (1) { + struct bezier right = *bez; + struct bezier left; + VGfloat tmp_len; + split_left(&right, t, &left); + tmp_len = bezier_length(&left, error); + if (ABS(tmp_len - at_length) < error) + break; + + if (tmp_len < at_length) { + t += (last_bigger - t)*.5; + } else { + last_bigger = t; + t -= t*.5; + } + } + return t; +} + +void bezier_point_at_length(struct bezier *bez, + float length, + float *point, + float *normal) +{ + /* ~0.000001 seems to be required to pass G2080x tests */ + VGfloat t = bezier_t_at_length(bez, length, 0.000001); + bezier_point_at(bez, t, point); + bezier_normal_at(bez, t, normal); + vector_unit(normal); +} + +void bezier_point_at_t(struct bezier *bez, float t, + float *point, float *normal) +{ + bezier_point_at(bez, t, point); + bezier_normal_at(bez, t, normal); + vector_unit(normal); +} + +void bezier_exact_bounds(const struct bezier *bez, + float *bounds/*x/y/width/height*/) +{ + struct polygon *poly = polygon_create(64); + polygon_vertex_append(poly, bez->x1, bez->y1); + bezier_add_to_polygon(bez, poly); + polygon_bounding_rect(poly, bounds); + polygon_destroy(poly); +} + diff --git a/src/gallium/state_trackers/vega/bezier.h b/src/gallium/state_trackers/vega/bezier.h new file mode 100644 index 00000000000..e06666051ca --- /dev/null +++ b/src/gallium/state_trackers/vega/bezier.h @@ -0,0 +1,81 @@ +/************************************************************************** + * + * 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 BEZIER_H +#define BEZIER_H + +struct polygon; +struct matrix; + +struct bezier { + float x1, y1; + float x2, y2; + float x3, y3; + float x4, y4; +}; + + +#define BEZIER_DEFAULT_ERROR 0.01 + +/* kappa as being l of a circle with r = 1, we can emulate any + * circle of radius r by using the formula + * l = r . kappa + * More at: + * http://www.whizkidtech.redprince.net/bezier/circle/ */ +#define KAPPA 0.5522847498 + +void bezier_init(struct bezier *bez, + float x1, float y1, + float x2, float y2, + float x3, float y3, + float x4, float y4); + +struct polygon *bezier_to_polygon(struct bezier *bez); +void bezier_add_to_polygon(const struct bezier *bez, + struct polygon *poly); +float bezier_length(struct bezier *bez, float error); +void bezier_transform(struct bezier *bez, + struct matrix *mat); + +int bezier_translate_by_normal(struct bezier *b, + struct bezier *curves, + int max_curves, + float normal_len, + float threshold); +void bezier_bounds(const struct bezier *bez, + float *bounds/*x/y/width/height*/); +void bezier_exact_bounds(const struct bezier *bez, + float *bounds/*x/y/width/height*/); + +void bezier_start_tangent(const struct bezier *bez, + float *tangent); + +void bezier_point_at_length(struct bezier *bez, float length, + float *point, float *normal); +void bezier_point_at_t(struct bezier *bez, float t, + float *point, float *normal); + +#endif diff --git a/src/gallium/state_trackers/vega/image.c b/src/gallium/state_trackers/vega/image.c new file mode 100644 index 00000000000..9a722980d52 --- /dev/null +++ b/src/gallium/state_trackers/vega/image.c @@ -0,0 +1,654 @@ +/************************************************************************** + * + * 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 "image.h" + +#include "vg_translate.h" +#include "vg_context.h" +#include "matrix.h" +#include "renderer.h" +#include "util_array.h" +#include "api_consts.h" +#include "shaders_cache.h" +#include "shader.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "pipe/p_inlines.h" +#include "util/u_blit.h" +#include "util/u_tile.h" +#include "util/u_memory.h" +#include "util/u_math.h" + +static enum pipe_format vg_format_to_pipe(VGImageFormat format) +{ + switch(format) { + case VG_sRGB_565: + return PIPE_FORMAT_R5G6B5_UNORM; + case VG_sRGBA_5551: + return PIPE_FORMAT_A1R5G5B5_UNORM; + case VG_sRGBA_4444: + return PIPE_FORMAT_A4R4G4B4_UNORM; + case VG_sL_8: + case VG_lL_8: + return PIPE_FORMAT_L8_UNORM; + case VG_BW_1: + return PIPE_FORMAT_A8R8G8B8_UNORM; + case VG_A_8: + return PIPE_FORMAT_A8_UNORM; +#ifdef OPENVG_VERSION_1_1 + case VG_A_1: + case VG_A_4: + return PIPE_FORMAT_A8_UNORM; +#endif + default: + return PIPE_FORMAT_A8R8G8B8_UNORM; + } +} + +static INLINE void vg_sync_size(VGfloat *src_loc, VGfloat *dst_loc) +{ + src_loc[2] = MIN2(src_loc[2], dst_loc[2]); + src_loc[3] = MIN2(src_loc[3], dst_loc[3]); + dst_loc[2] = src_loc[2]; + dst_loc[3] = src_loc[3]; +} + + +static void vg_copy_texture(struct vg_context *ctx, + struct pipe_texture *dst, VGint dx, VGint dy, + struct pipe_texture *src, VGint sx, VGint sy, + VGint width, VGint height) +{ + VGfloat dst_loc[4], src_loc[4]; + VGfloat dst_bounds[4], src_bounds[4]; + VGfloat src_shift[4], dst_shift[4], shift[4]; + + dst_loc[0] = dx; + dst_loc[1] = dy; + dst_loc[2] = width; + dst_loc[3] = height; + dst_bounds[0] = 0.f; + dst_bounds[1] = 0.f; + dst_bounds[2] = dst->width[0]; + dst_bounds[3] = dst->height[0]; + + src_loc[0] = sx; + src_loc[1] = sy; + src_loc[2] = width; + src_loc[3] = height; + src_bounds[0] = 0.f; + src_bounds[1] = 0.f; + src_bounds[2] = src->width[0]; + src_bounds[3] = src->height[0]; + + vg_bound_rect(src_loc, src_bounds, src_shift); + vg_bound_rect(dst_loc, dst_bounds, dst_shift); + shift[0] = src_shift[0] - dst_shift[0]; + shift[1] = src_shift[1] - dst_shift[1]; + + if (shift[0] < 0) + vg_shift_rectx(src_loc, src_bounds, -shift[0]); + else + vg_shift_rectx(dst_loc, dst_bounds, shift[0]); + + if (shift[1] < 0) + vg_shift_recty(src_loc, src_bounds, -shift[1]); + else + vg_shift_recty(dst_loc, dst_bounds, shift[1]); + + vg_sync_size(src_loc, dst_loc); + + if (src_loc[2] >= 0 && src_loc[3] >= 0 && + dst_loc[2] >= 0 && dst_loc[3] >= 0) { + renderer_copy_texture(ctx->renderer, + src, + src_loc[0], + src_loc[1] + src_loc[3], + src_loc[0] + src_loc[2], + src_loc[1], + dst, + dst_loc[0], + dst_loc[1] + dst_loc[3], + dst_loc[0] + dst_loc[2], + dst_loc[1]); + } + +} + +void vg_copy_surface(struct vg_context *ctx, + struct pipe_surface *dst, VGint dx, VGint dy, + struct pipe_surface *src, VGint sx, VGint sy, + VGint width, VGint height) +{ + VGfloat dst_loc[4], src_loc[4]; + VGfloat dst_bounds[4], src_bounds[4]; + VGfloat src_shift[4], dst_shift[4], shift[4]; + + dst_loc[0] = dx; + dst_loc[1] = dy; + dst_loc[2] = width; + dst_loc[3] = height; + dst_bounds[0] = 0.f; + dst_bounds[1] = 0.f; + dst_bounds[2] = dst->width; + dst_bounds[3] = dst->height; + + src_loc[0] = sx; + src_loc[1] = sy; + src_loc[2] = width; + src_loc[3] = height; + src_bounds[0] = 0.f; + src_bounds[1] = 0.f; + src_bounds[2] = src->width; + src_bounds[3] = src->height; + + vg_bound_rect(src_loc, src_bounds, src_shift); + vg_bound_rect(dst_loc, dst_bounds, dst_shift); + shift[0] = src_shift[0] - dst_shift[0]; + shift[1] = src_shift[1] - dst_shift[1]; + + if (shift[0] < 0) + vg_shift_rectx(src_loc, src_bounds, -shift[0]); + else + vg_shift_rectx(dst_loc, dst_bounds, shift[0]); + + if (shift[1] < 0) + vg_shift_recty(src_loc, src_bounds, -shift[1]); + else + vg_shift_recty(dst_loc, dst_bounds, shift[1]); + + vg_sync_size(src_loc, dst_loc); + + if (src_loc[2] > 0 && src_loc[3] > 0 && + dst_loc[2] > 0 && dst_loc[3] > 0) { + if (src == dst) + renderer_copy_surface(ctx->renderer, + src, + src_loc[0], + src->height - (src_loc[1] + src_loc[3]), + src_loc[0] + src_loc[2], + src->height - src_loc[1], + dst, + dst_loc[0], + dst->height - (dst_loc[1] + dst_loc[3]), + dst_loc[0] + dst_loc[2], + dst->height - dst_loc[1], + 0, 0); + else + renderer_copy_surface(ctx->renderer, + src, + src_loc[0], + src->height - src_loc[1], + src_loc[0] + src_loc[2], + src->height - (src_loc[1] + src_loc[3]), + dst, + dst_loc[0], + dst->height - (dst_loc[1] + dst_loc[3]), + dst_loc[0] + dst_loc[2], + dst->height - dst_loc[1], + 0, 0); + } + +} + +static struct pipe_texture *image_texture(struct vg_image *img) +{ + struct pipe_texture *tex = img->texture; + return tex; +} + + +static void image_cleari(struct vg_image *img, VGint clear_colori, + VGint x, VGint y, VGint width, VGint height) +{ + VGint *clearbuf; + VGint i; + VGfloat dwidth, dheight; + + clearbuf = malloc(sizeof(VGint)*width*height); + for (i = 0; i < width*height; ++i) + clearbuf[i] = clear_colori; + + dwidth = MIN2(width, img->width); + dheight = MIN2(height, img->height); + + image_sub_data(img, clearbuf, width * sizeof(VGint), + VG_sRGBA_8888, + x, y, dwidth, dheight); + free(clearbuf); +} + +struct vg_image * image_create(VGImageFormat format, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_image *image = CALLOC_STRUCT(vg_image); + enum pipe_format pformat = vg_format_to_pipe(format); + struct pipe_texture pt, *newtex; + struct pipe_screen *screen = ctx->pipe->screen; + + vg_init_object(&image->base, ctx, VG_OBJECT_IMAGE); + + image->format = format; + image->width = width; + image->height = height; + + image->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + image->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + image->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + image->sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST; + image->sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST; + image->sampler.normalized_coords = 1; + + assert(screen->is_format_supported(screen, pformat, PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_SAMPLER, 0)); + + memset(&pt, 0, sizeof(pt)); + pt.target = PIPE_TEXTURE_2D; + pt.format = pformat; + pf_get_block(pformat, &pt.block); + pt.last_level = 0; + pt.width[0] = width; + pt.height[0] = height; + pt.depth[0] = 1; + pt.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; + + newtex = screen->texture_create(screen, &pt); + + debug_assert(newtex); + + image->texture = newtex; + + vg_context_add_object(ctx, VG_OBJECT_IMAGE, image); + + image_cleari(image, 0, 0, 0, image->width, image->height); + return image; +} + +void image_destroy(struct vg_image *img) +{ + struct vg_context *ctx = vg_current_context(); + vg_context_remove_object(ctx, VG_OBJECT_IMAGE, img); + + + if (img->parent) { + /* remove img from the parent child array */ + int idx; + struct vg_image **array = + (struct vg_image **)img->parent->children_array->data; + + for (idx = 0; idx < img->parent->children_array->num_elements; ++idx) { + struct vg_image *child = array[idx]; + if (child == img) { + break; + } + } + debug_assert(idx < img->parent->children_array->num_elements); + array_remove_element(img->parent->children_array, idx); + } + + if (img->children_array && img->children_array->num_elements) { + /* reparent the children */ + VGint i; + struct vg_image *parent = img->parent; + struct vg_image **children = + (struct vg_image **)img->children_array->data; + if (!parent) { + VGint min_x = children[0]->x; + parent = children[0]; + + for (i = 1; i < img->children_array->num_elements; ++i) { + struct vg_image *child = children[i]; + if (child->x < min_x) { + parent = child; + } + } + } + + for (i = 0; i < img->children_array->num_elements; ++i) { + struct vg_image *child = children[i]; + if (child != parent) { + child->parent = parent; + if (!parent->children_array) { + parent->children_array = array_create( + sizeof(struct vg_image*)); + } + array_append_data(parent->children_array, + &child, 1); + } else + child->parent = NULL; + } + array_destroy(img->children_array); + } + + pipe_texture_reference(&img->texture, NULL); + free(img); +} + +void image_clear(struct vg_image *img, + VGint x, VGint y, VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + VGfloat *clear_colorf = ctx->state.vg.clear_color; + VGubyte r, g, b ,a; + VGint clear_colori; + /* FIXME: this is very nasty */ + r = float_to_ubyte(clear_colorf[0]); + g = float_to_ubyte(clear_colorf[1]); + b = float_to_ubyte(clear_colorf[2]); + a = float_to_ubyte(clear_colorf[3]); + clear_colori = r << 24 | g << 16 | b << 8 | a; + image_cleari(img, clear_colori, x, y, width, height); +} + +void image_sub_data(struct vg_image *image, + const void * data, + VGint dataStride, + VGImageFormat dataFormat, + VGint x, VGint y, + VGint width, VGint height) +{ + const VGint yStep = 1; + VGubyte *src = (VGubyte *)data; + VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4]; + VGfloat *df = (VGfloat*)temp; + VGint i; + struct vg_context *ctx = vg_current_context(); + struct pipe_screen *screen = ctx->pipe->screen; + struct pipe_texture *texture = image_texture(image); + VGint xoffset = 0, yoffset = 0; + + if (x < 0) { + xoffset -= x; + width += x; + x = 0; + } + if (y < 0) { + yoffset -= y; + height += y; + y = 0; + } + + if (width <= 0 || height <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + if (x > image->width || y > image->width) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + if (x + width > image->width) { + width = image->width - x; + } + + if (y + height > image->height) { + height = image->height - y; + } + + { /* upload color_data */ + struct pipe_transfer *transfer = screen->get_tex_transfer( + screen, texture, 0, 0, 0, + PIPE_TRANSFER_WRITE, 0, 0, texture->width[0], texture->height[0]); + src += (dataStride * yoffset); + for (i = 0; i < height; i++) { + _vega_unpack_float_span_rgba(ctx, width, xoffset, src, dataFormat, temp); + pipe_put_tile_rgba(transfer, x+image->x, y+image->y, width, 1, df); + y += yStep; + src += dataStride; + } + screen->tex_transfer_destroy(transfer); + } +} + +void image_get_sub_data(struct vg_image * image, + void * data, + VGint dataStride, + VGImageFormat dataFormat, + VGint sx, VGint sy, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_context *pipe = ctx->pipe; + struct pipe_screen *screen = pipe->screen; + VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4]; + VGfloat *df = (VGfloat*)temp; + VGint y = 0, yStep = 1; + VGint i; + VGubyte *dst = (VGubyte *)data; + + { + struct pipe_transfer *transfer = + screen->get_tex_transfer(screen, + image->texture, 0, 0, 0, + PIPE_TRANSFER_READ, + 0, 0, + image->x + image->width, + image->y + image->height); + /* Do a row at a time to flip image data vertically */ + for (i = 0; i < height; i++) { +#if 0 + debug_printf("%d-%d == %d\n", sy, height, y); +#endif + pipe_get_tile_rgba(transfer, sx+image->x, y, width, 1, df); + y += yStep; + _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, dst); + dst += dataStride; + } + + screen->tex_transfer_destroy(transfer); + } +} + +struct vg_image * image_child_image(struct vg_image *parent, + VGint x, VGint y, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_image *image = CALLOC_STRUCT(vg_image); + + vg_init_object(&image->base, ctx, VG_OBJECT_IMAGE); + + image->x = parent->x + x; + image->y = parent->y + y; + image->width = width; + image->height = height; + image->parent = parent; + image->texture = 0; + pipe_texture_reference(&image->texture, + parent->texture); + + image->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + image->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + image->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + image->sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST; + image->sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST; + image->sampler.normalized_coords = 1; + + if (!parent->children_array) + parent->children_array = array_create( + sizeof(struct vg_image*)); + + array_append_data(parent->children_array, + &image, 1); + + vg_context_add_object(ctx, VG_OBJECT_IMAGE, image); + + return image; +} + +void image_copy(struct vg_image *dst, VGint dx, VGint dy, + struct vg_image *src, VGint sx, VGint sy, + VGint width, VGint height, + VGboolean dither) +{ + struct vg_context *ctx = vg_current_context(); + + if (width <= 0 || height <= 0) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + /* make sure rendering has completed */ + ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL); + vg_copy_texture(ctx, dst->texture, dst->x + dx, dst->y + dy, + src->texture, src->x + sx, src->y + sy, width, height); +} + +void image_draw(struct vg_image *img) +{ + struct vg_context *ctx = vg_current_context(); + VGfloat x1, y1; + VGfloat x2, y2; + VGfloat x3, y3; + VGfloat x4, y4; + struct matrix *matrix; + + x1 = 0; + y1 = 0; + x2 = img->width; + y2 = 0; + x3 = img->width; + y3 = img->height; + x4 = 0; + y4 = img->height; + + matrix = &ctx->state.vg.image_user_to_surface_matrix; + + matrix_map_point(matrix, x1, y1, &x1, &y1); + matrix_map_point(matrix, x2, y2, &x2, &y2); + matrix_map_point(matrix, x3, y3, &x3, &y3); + matrix_map_point(matrix, x4, y4, &x4, &y4); + + shader_set_drawing_image(ctx->shader, VG_TRUE); + shader_set_paint(ctx->shader, ctx->state.vg.fill_paint); + shader_set_image(ctx->shader, img); + shader_bind(ctx->shader); + + renderer_texture_quad(ctx->renderer, image_texture(img), + img->x, img->y, img->x + img->width, img->y + img->height, + x1, y1, x2, y2, x3, y3, x4, y4); +} + +void image_set_pixels(VGint dx, VGint dy, + struct vg_image *src, VGint sx, VGint sy, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_context *pipe = ctx->pipe; + struct pipe_screen *screen = pipe->screen; + struct pipe_surface *surf; + struct st_renderbuffer *strb = ctx->draw_buffer->strb; + + /* make sure rendering has completed */ + pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); + + surf = screen->get_tex_surface(screen, image_texture(src), 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_READ); + + vg_copy_surface(ctx, strb->surface, dx, dy, + surf, sx+src->x, sy+src->y, width, height); + + screen->tex_surface_destroy(surf); +} + +void image_get_pixels(struct vg_image *dst, VGint dx, VGint dy, + VGint sx, VGint sy, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_context *pipe = ctx->pipe; + struct pipe_screen *screen = pipe->screen; + struct pipe_surface *surf; + struct st_renderbuffer *strb = ctx->draw_buffer->strb; + + /* flip the y coordinates */ + /*dy = dst->height - dy - height;*/ + + /* make sure rendering has completed */ + pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); + + surf = screen->get_tex_surface(screen, image_texture(dst), 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_WRITE | + PIPE_BUFFER_USAGE_GPU_READ); + vg_copy_surface(ctx, surf, dst->x + dx, dst->y + dy, + strb->surface, sx, sy, width, height); + + pipe_surface_reference(&surf, NULL); +} + + +VGboolean vg_image_overlaps(struct vg_image *dst, + struct vg_image *src) +{ + if (dst == src || dst->parent == src || + dst == src->parent) + return VG_TRUE; + if (dst->parent && dst->parent == src->parent) { + VGfloat left1 = dst->x; + VGfloat left2 = src->x; + VGfloat right1 = dst->x + dst->width; + VGfloat right2 = src->x + src->width; + VGfloat bottom1 = dst->y; + VGfloat bottom2 = src->y; + VGfloat top1 = dst->y + dst->height; + VGfloat top2 = src->y + src->height; + + return !(left2 > right1 || right2 < left1 || + top2 > bottom1 || bottom2 < top1); + } + return VG_FALSE; +} + +VGint image_bind_samplers(struct vg_image *img, struct pipe_sampler_state **samplers, + struct pipe_texture **textures) +{ + img->sampler.min_img_filter = image_sampler_filter(img->base.ctx); + img->sampler.mag_img_filter = image_sampler_filter(img->base.ctx); + samplers[3] = &img->sampler; + textures[3] = img->texture; + return 1; +} + +VGint image_sampler_filter(struct vg_context *ctx) +{ + switch(ctx->state.vg.image_quality) { + case VG_IMAGE_QUALITY_NONANTIALIASED: + return PIPE_TEX_FILTER_NEAREST; + break; + case VG_IMAGE_QUALITY_FASTER: + return PIPE_TEX_FILTER_NEAREST; + break; + case VG_IMAGE_QUALITY_BETTER: + /*return PIPE_TEX_FILTER_ANISO;*/ + return PIPE_TEX_FILTER_LINEAR; + break; + default: + debug_printf("Unknown image quality"); + } + return PIPE_TEX_FILTER_NEAREST; +} diff --git a/src/gallium/state_trackers/vega/image.h b/src/gallium/state_trackers/vega/image.h new file mode 100644 index 00000000000..78e17cffa64 --- /dev/null +++ b/src/gallium/state_trackers/vega/image.h @@ -0,0 +1,104 @@ +/************************************************************************** + * + * 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 IMAGES_H +#define IMAGES_H + +#include "vg_context.h" +#include "pipe/p_state.h" + +struct pipe_texture; +struct array; +struct vg_context; +struct pipe_surface; + +struct vg_image { + struct vg_object base; + VGImageFormat format; + VGint x, y; + VGint width, height; + + struct vg_image *parent; + + struct pipe_texture *texture; + struct pipe_sampler_state sampler; + + struct array *children_array; +}; + +struct vg_image *image_create(VGImageFormat format, + VGint width, VGint height); +void image_destroy(struct vg_image *img); + +void image_clear(struct vg_image *img, + VGint x, VGint y, VGint width, VGint height); + +void image_sub_data(struct vg_image *image, + const void * data, + VGint dataStride, + VGImageFormat dataFormat, + VGint x, VGint y, + VGint width, VGint height); + +void image_get_sub_data(struct vg_image * image, + void * data, + VGint dataStride, + VGImageFormat dataFormat, + VGint x, VGint y, + VGint width, VGint height); + +struct vg_image *image_child_image(struct vg_image *parent, + VGint x, VGint y, + VGint width, VGint height); + +void image_copy(struct vg_image *dst, VGint dx, VGint dy, + struct vg_image *src, VGint sx, VGint sy, + VGint width, VGint height, + VGboolean dither); + +void image_draw(struct vg_image *img); + +void image_set_pixels(VGint dx, VGint dy, + struct vg_image *src, VGint sx, VGint sy, + VGint width, VGint height); +void image_get_pixels(struct vg_image *dst, VGint dx, VGint dy, + VGint sx, VGint sy, + VGint width, VGint height); + +VGint image_bind_samplers(struct vg_image *dst, struct pipe_sampler_state **samplers, + struct pipe_texture **textures); + +VGboolean vg_image_overlaps(struct vg_image *dst, + struct vg_image *src); + +VGint image_sampler_filter(struct vg_context *ctx); + +void vg_copy_surface(struct vg_context *ctx, + struct pipe_surface *dst, VGint dx, VGint dy, + struct pipe_surface *src, VGint sx, VGint sy, + VGint width, VGint height); + +#endif diff --git a/src/gallium/state_trackers/vega/mask.c b/src/gallium/state_trackers/vega/mask.c new file mode 100644 index 00000000000..24650a37d50 --- /dev/null +++ b/src/gallium/state_trackers/vega/mask.c @@ -0,0 +1,690 @@ +/************************************************************************** + * + * 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 "mask.h" + +#include "path.h" +#include "image.h" +#include "shaders_cache.h" +#include "renderer.h" +#include "asm_util.h" +#include "st_inlines.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "pipe/p_inlines.h" +#include "util/u_memory.h" + +struct vg_mask_layer { + struct vg_object base; + + VGint width; + VGint height; + + struct pipe_texture *texture; +}; + +static INLINE struct pipe_surface * +alpha_mask_surface(struct vg_context *ctx, int usage) +{ + struct pipe_screen *screen = ctx->pipe->screen; + struct st_framebuffer *stfb = ctx->draw_buffer; + return screen->get_tex_surface(screen, + stfb->alpha_mask, + 0, 0, 0, + usage); +} + +static INLINE VGboolean +intersect_rectangles(VGint dwidth, VGint dheight, + VGint swidth, VGint sheight, + VGint tx, VGint ty, + VGint twidth, VGint theight, + VGint *offsets, + VGint *location) +{ + if (tx + twidth <= 0 || tx >= dwidth) + return VG_FALSE; + if (ty + theight <= 0 || ty >= dheight) + return VG_FALSE; + + offsets[0] = 0; + offsets[1] = 0; + location[0] = tx; + location[1] = ty; + + if (tx < 0) { + offsets[0] -= tx; + location[0] = 0; + + location[2] = MIN2(tx + swidth, MIN2(dwidth, tx + twidth)); + offsets[2] = location[2]; + } else { + offsets[2] = MIN2(twidth, MIN2(dwidth - tx, swidth )); + location[2] = offsets[2]; + } + + if (ty < 0) { + offsets[1] -= ty; + location[1] = 0; + + location[3] = MIN2(ty + sheight, MIN2(dheight, ty + theight)); + offsets[3] = location[3]; + } else { + offsets[3] = MIN2(theight, MIN2(dheight - ty, sheight)); + location[3] = offsets[3]; + } + + return VG_TRUE; +} + +#if DEBUG_MASKS +static void read_alpha_mask(void * data, VGint dataStride, + VGImageFormat dataFormat, + VGint sx, VGint sy, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_context *pipe = ctx->pipe; + struct pipe_screen *screen = pipe->screen; + + struct st_framebuffer *stfb = ctx->draw_buffer; + struct st_renderbuffer *strb = stfb->alpha_mask; + struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; + + VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4]; + VGfloat *df = (VGfloat*)temp; + VGint y = (fb->height - sy) - 1, yStep = -1; + VGint i; + VGubyte *dst = (VGubyte *)data; + VGint xoffset = 0, yoffset = 0; + + /* make sure rendering has completed */ + pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); + if (sx < 0) { + xoffset = -sx; + xoffset *= _vega_size_for_format(dataFormat); + width += sx; + sx = 0; + } + if (sy < 0) { + yoffset = -sy; + height += sy; + sy = 0; + y = (fb->height - sy) - 1; + yoffset *= dataStride; + } + + { + struct pipe_surface *surf; + + surf = screen->get_tex_surface(screen, strb->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_READ); + + /* Do a row at a time to flip image data vertically */ + for (i = 0; i < height; i++) { +#if 0 + debug_printf("%d-%d == %d\n", sy, height, y); +#endif + pipe_get_tile_rgba(surf, sx, y, width, 1, df); + y += yStep; + _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, + dst + yoffset + xoffset); + dst += dataStride; + } + + pipe_surface_reference(&surf, NULL); + } +} + +void save_alpha_to_file(const char *filename) +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; + VGint *data; + int i, j; + + data = malloc(sizeof(int) * fb->width * fb->height); + read_alpha_mask(data, fb->width * sizeof(int), + VG_sRGBA_8888, + 0, 0, fb->width, fb->height); + fprintf(stderr, "/*---------- start */\n"); + fprintf(stderr, "const int image_width = %d;\n", + fb->width); + fprintf(stderr, "const int image_height = %d;\n", + fb->height); + fprintf(stderr, "const int image_data = {\n"); + for (i = 0; i < fb->height; ++i) { + for (j = 0; j < fb->width; ++j) { + int rgba = data[i * fb->height + j]; + int argb = 0; + argb = (rgba >> 8); + argb |= ((rgba & 0xff) << 24); + fprintf(stderr, "0x%x, ", argb); + } + fprintf(stderr, "\n"); + } + fprintf(stderr, "};\n"); + fprintf(stderr, "/*---------- end */\n"); +} +#endif + +static void setup_mask_framebuffer(struct pipe_surface *surf, + VGint surf_width, VGint surf_height) +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_framebuffer_state fb; + + memset(&fb, 0, sizeof(fb)); + fb.width = surf_width; + fb.height = surf_height; + fb.nr_cbufs = 1; + fb.cbufs[0] = surf; + { + VGint i; + for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) + fb.cbufs[i] = 0; + } + cso_set_framebuffer(ctx->cso_context, &fb); +} + + +/* setup shader constants */ +static void setup_mask_operation(VGMaskOperation operation) +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_constant_buffer *cbuf = &ctx->mask.cbuf; + const VGint param_bytes = 4 * sizeof(VGfloat); + const VGfloat ones[4] = {1.f, 1.f, 1.f, 1.f}; + void *shader = 0; + + /* We always need to get a new buffer, to keep the drivers simple and + * avoid gratuitous rendering synchronization. + */ + pipe_buffer_reference(&cbuf->buffer, NULL); + + cbuf->buffer = pipe_buffer_create(ctx->pipe->screen, 1, + PIPE_BUFFER_USAGE_CONSTANT, + param_bytes); + if (cbuf->buffer) { + st_no_flush_pipe_buffer_write(ctx, cbuf->buffer, + 0, param_bytes, ones); + } + + ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf); + switch (operation) { + case VG_UNION_MASK: { + if (!ctx->mask.union_fs) { + ctx->mask.union_fs = shader_create_from_text(ctx->pipe, + union_mask_asm, + 200, + PIPE_SHADER_FRAGMENT); + } + shader = ctx->mask.union_fs->driver; + } + break; + case VG_INTERSECT_MASK: { + if (!ctx->mask.intersect_fs) { + ctx->mask.intersect_fs = shader_create_from_text(ctx->pipe, + intersect_mask_asm, + 200, + PIPE_SHADER_FRAGMENT); + } + shader = ctx->mask.intersect_fs->driver; + } + break; + case VG_SUBTRACT_MASK: { + if (!ctx->mask.subtract_fs) { + ctx->mask.subtract_fs = shader_create_from_text(ctx->pipe, + subtract_mask_asm, + 200, + PIPE_SHADER_FRAGMENT); + } + shader = ctx->mask.subtract_fs->driver; + } + break; + case VG_SET_MASK: { + if (!ctx->mask.set_fs) { + ctx->mask.set_fs = shader_create_from_text(ctx->pipe, + set_mask_asm, + 200, + PIPE_SHADER_FRAGMENT); + } + shader = ctx->mask.set_fs->driver; + } + break; + default: + assert(0); + break; + } + cso_set_fragment_shader_handle(ctx->cso_context, shader); +} + +static void setup_mask_samplers(struct pipe_texture *umask) +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; + struct pipe_texture *textures[PIPE_MAX_SAMPLERS]; + struct st_framebuffer *fb_buffers = ctx->draw_buffer; + struct pipe_texture *uprev = NULL; + struct pipe_sampler_state sampler; + + uprev = fb_buffers->blend_texture; + sampler = ctx->mask.sampler; + sampler.normalized_coords = 1; + + samplers[0] = NULL; + samplers[1] = NULL; + samplers[2] = NULL; + textures[0] = NULL; + textures[1] = NULL; + textures[2] = NULL; + + samplers[0] = &sampler; + samplers[1] = &ctx->mask.sampler; + + textures[0] = umask; + textures[1] = uprev; + + cso_set_samplers(ctx->cso_context, 2, + (const struct pipe_sampler_state **)samplers); + cso_set_sampler_textures(ctx->cso_context, 2, textures); +} + + +/* setup shader constants */ +static void setup_mask_fill(const VGfloat color[4]) +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_constant_buffer *cbuf = &ctx->mask.cbuf; + const VGint param_bytes = 4 * sizeof(VGfloat); + + /* We always need to get a new buffer, to keep the drivers simple and + * avoid gratuitous rendering synchronization. + */ + pipe_buffer_reference(&cbuf->buffer, NULL); + + cbuf->buffer = pipe_buffer_create(ctx->pipe->screen, 1, + PIPE_BUFFER_USAGE_CONSTANT, + param_bytes); + if (cbuf->buffer) { + st_no_flush_pipe_buffer_write(ctx, cbuf->buffer, 0, param_bytes, color); + } + + ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf); + cso_set_fragment_shader_handle(ctx->cso_context, + shaders_cache_fill(ctx->sc, + VEGA_SOLID_FILL_SHADER)); +} + +static void setup_mask_viewport() +{ + struct vg_context *ctx = vg_current_context(); + vg_set_viewport(ctx, VEGA_Y0_TOP); +} + +static void setup_mask_blend() +{ + struct vg_context *ctx = vg_current_context(); + + struct pipe_blend_state blend; + + memset(&blend, 0, sizeof(struct pipe_blend_state)); + blend.blend_enable = 1; + blend.colormask |= PIPE_MASK_R; + blend.colormask |= PIPE_MASK_G; + blend.colormask |= PIPE_MASK_B; + blend.colormask |= PIPE_MASK_A; + blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + + cso_set_blend(ctx->cso_context, &blend); +} + + +static void surface_fill(struct pipe_surface *surf, + int surf_width, int surf_height, + int x, int y, int width, int height, + const VGfloat color[4]) +{ + struct vg_context *ctx = vg_current_context(); + + if (x < 0) { + width += x; + x = 0; + } + if (y < 0) { + height += y; + y = 0; + } + + cso_save_framebuffer(ctx->cso_context); + cso_save_blend(ctx->cso_context); + cso_save_fragment_shader(ctx->cso_context); + cso_save_viewport(ctx->cso_context); + + setup_mask_blend(); + setup_mask_fill(color); + setup_mask_framebuffer(surf, surf_width, surf_height); + setup_mask_viewport(); + + renderer_draw_quad(ctx->renderer, x, y, + x + width, y + height, 0.0f/*depth should be disabled*/); + + + /* make sure rendering has completed */ + ctx->pipe->flush(ctx->pipe, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, + NULL); + +#if DEBUG_MASKS + save_alpha_to_file(0); +#endif + + cso_restore_blend(ctx->cso_context); + cso_restore_framebuffer(ctx->cso_context); + cso_restore_fragment_shader(ctx->cso_context); + cso_restore_viewport(ctx->cso_context); +} + + +static void mask_using_texture(struct pipe_texture *texture, + VGMaskOperation operation, + VGint x, VGint y, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct pipe_surface *surface = + alpha_mask_surface(ctx, PIPE_BUFFER_USAGE_GPU_WRITE); + VGint offsets[4], loc[4]; + + if (!surface) + return; + if (!intersect_rectangles(surface->width, surface->height, + texture->width[0], texture->height[0], + x, y, width, height, + offsets, loc)) + return; +#if 0 + debug_printf("Offset = [%d, %d, %d, %d]\n", offsets[0], + offsets[1], offsets[2], offsets[3]); + debug_printf("Locati = [%d, %d, %d, %d]\n", loc[0], + loc[1], loc[2], loc[3]); +#endif + + /* prepare our blend surface */ + vg_prepare_blend_surface_from_mask(ctx); + + cso_save_samplers(ctx->cso_context); + cso_save_sampler_textures(ctx->cso_context); + cso_save_framebuffer(ctx->cso_context); + cso_save_blend(ctx->cso_context); + cso_save_fragment_shader(ctx->cso_context); + cso_save_viewport(ctx->cso_context); + + setup_mask_samplers(texture); + setup_mask_blend(); + setup_mask_operation(operation); + setup_mask_framebuffer(surface, surface->width, surface->height); + setup_mask_viewport(); + + /* render the quad to propagate the rendering from stencil */ + renderer_draw_texture(ctx->renderer, texture, + offsets[0], offsets[1], + offsets[0] + offsets[2], offsets[1] + offsets[3], + loc[0], loc[1], loc[0] + loc[2], loc[1] + loc[3]); + + /* make sure rendering has completed */ + ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL); + cso_restore_blend(ctx->cso_context); + cso_restore_framebuffer(ctx->cso_context); + cso_restore_fragment_shader(ctx->cso_context); + cso_restore_samplers(ctx->cso_context); + cso_restore_sampler_textures(ctx->cso_context); + cso_restore_viewport(ctx->cso_context); + + pipe_surface_reference(&surface, NULL); +} + + +#ifdef OPENVG_VERSION_1_1 + +struct vg_mask_layer * mask_layer_create(VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_mask_layer *mask = 0; + + mask = CALLOC_STRUCT(vg_mask_layer); + vg_init_object(&mask->base, ctx, VG_OBJECT_MASK); + mask->width = width; + mask->height = height; + + { + struct pipe_texture pt; + struct pipe_screen *screen = ctx->pipe->screen; + + memset(&pt, 0, sizeof(pt)); + pt.target = PIPE_TEXTURE_2D; + pt.format = PIPE_FORMAT_A8R8G8B8_UNORM; + pf_get_block(PIPE_FORMAT_A8R8G8B8_UNORM, &pt.block); + pt.last_level = 0; + pt.width[0] = width; + pt.height[0] = height; + pt.depth[0] = 1; + pt.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; + pt.compressed = 0; + + mask->texture = screen->texture_create(screen, &pt); + } + + vg_context_add_object(ctx, VG_OBJECT_MASK, mask); + + return mask; +} + +void mask_layer_destroy(struct vg_mask_layer *layer) +{ + struct vg_context *ctx = vg_current_context(); + + vg_context_remove_object(ctx, VG_OBJECT_MASK, layer); + pipe_texture_release(&layer->texture); + free(layer); +} + +void mask_layer_fill(struct vg_mask_layer *layer, + VGint x, VGint y, + VGint width, VGint height, + VGfloat value) +{ + struct vg_context *ctx = vg_current_context(); + VGfloat alpha_color[4] = {0, 0, 0, 0}; + struct pipe_surface *surface; + + alpha_color[3] = value; + + surface = ctx->pipe->screen->get_tex_surface( + ctx->pipe->screen, layer->texture, + 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_WRITE); + + surface_fill(surface, + layer->width, layer->height, + x, y, width, height, alpha_color); + + ctx->pipe->screen->tex_surface_release(ctx->pipe->screen, &surface); +} + +void mask_copy(struct vg_mask_layer *layer, + VGint sx, VGint sy, + VGint dx, VGint dy, + VGint width, VGint height) +{ + struct vg_context *ctx = vg_current_context(); + struct st_framebuffer *fb_buffers = ctx->draw_buffer; + + renderer_copy_texture(ctx->renderer, + layer->texture, + sx, sy, + sx + width, sy + height, + fb_buffers->alpha_mask, + dx, dy, + dx + width, dy + height); +} + +static void mask_layer_render_to(struct vg_mask_layer *layer, + struct path *path, + VGbitfield paint_modes) +{ + struct vg_context *ctx = vg_current_context(); + const VGfloat fill_color[4] = {1.f, 1.f, 1.f, 1.f}; + struct pipe_screen *screen = ctx->pipe->screen; + struct pipe_surface *surface; + + surface = screen->get_tex_surface(screen, layer->texture, 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_WRITE); + + cso_save_framebuffer(ctx->cso_context); + cso_save_fragment_shader(ctx->cso_context); + cso_save_viewport(ctx->cso_context); + + setup_mask_blend(); + setup_mask_fill(fill_color); + setup_mask_framebuffer(surface, layer->width, layer->height); + setup_mask_viewport(); + + if (paint_modes & VG_FILL_PATH) { + struct matrix *mat = &ctx->state.vg.path_user_to_surface_matrix; + path_fill(path, mat); + } + + if (paint_modes & VG_STROKE_PATH){ + path_stroke(path); + } + + + /* make sure rendering has completed */ + ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL); + + cso_restore_framebuffer(ctx->cso_context); + cso_restore_fragment_shader(ctx->cso_context); + cso_restore_viewport(ctx->cso_context); + ctx->state.dirty |= BLEND_DIRTY; + + screen->tex_surface_release(ctx->pipe->screen, &surface); +} + +void mask_render_to(struct path *path, + VGbitfield paint_modes, + VGMaskOperation operation) +{ + struct vg_context *ctx = vg_current_context(); + struct st_framebuffer *fb_buffers = ctx->draw_buffer; + struct vg_mask_layer *temp_layer; + VGint width, height; + + width = fb_buffers->alpha_mask->width[0]; + height = fb_buffers->alpha_mask->width[0]; + + temp_layer = mask_layer_create(width, height); + + mask_layer_render_to(temp_layer, path, paint_modes); + + mask_using_layer(temp_layer, 0, 0, width, height, + operation); + + mask_layer_destroy(temp_layer); +} + +void mask_using_layer(struct vg_mask_layer *layer, + VGMaskOperation operation, + VGint x, VGint y, + VGint width, VGint height) +{ + mask_using_texture(layer->texture, operation, + x, y, width, height); +} + +VGint mask_layer_width(struct vg_mask_layer *layer) +{ + return layer->width; +} + +VGint mask_layer_height(struct vg_mask_layer *layer) +{ + return layer->height; +} + + +#endif + +void mask_using_image(struct vg_image *image, + VGMaskOperation operation, + VGint x, VGint y, + VGint width, VGint height) +{ + mask_using_texture(image->texture, operation, + x, y, width, height); +} + +void mask_fill(VGint x, VGint y, VGint width, VGint height, + VGfloat value) +{ + struct vg_context *ctx = vg_current_context(); + VGfloat alpha_color[4] = {.0f, .0f, .0f, value}; + struct pipe_surface *surf = alpha_mask_surface( + ctx, PIPE_BUFFER_USAGE_GPU_WRITE); + +#if DEBUG_MASKS + debug_printf("mask_fill(%d, %d, %d, %d) with rgba(%f, %f, %f, %f)\n", + x, y, width, height, + alpha_color[0], alpha_color[1], + alpha_color[2], alpha_color[3]); + debug_printf("XXX %f === %f \n", + alpha_color[3], value); +#endif + + surface_fill(surf, surf->width, surf->height, + x, y, width, height, alpha_color); + + pipe_surface_reference(&surf, NULL); +} + +VGint mask_bind_samplers(struct pipe_sampler_state **samplers, + struct pipe_texture **textures) +{ + struct vg_context *ctx = vg_current_context(); + + if (ctx->state.vg.masking) { + struct st_framebuffer *fb_buffers = ctx->draw_buffer; + + samplers[1] = &ctx->mask.sampler; + textures[1] = fb_buffers->alpha_mask; + return 1; + } else + return 0; +} diff --git a/src/gallium/state_trackers/vega/mask.h b/src/gallium/state_trackers/vega/mask.h new file mode 100644 index 00000000000..5eaaede0e3a --- /dev/null +++ b/src/gallium/state_trackers/vega/mask.h @@ -0,0 +1,68 @@ +/************************************************************************** + * + * 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 MASK_H +#define MASK_H + +#include "vg_context.h" + +struct path; +struct vg_image; +struct pipe_texture; + +struct vg_mask_layer *mask_layer_create(VGint width, VGint height); +void mask_layer_destroy(struct vg_mask_layer *layer); +void mask_layer_fill(struct vg_mask_layer *layer, + VGint x, VGint y, + VGint width, VGint height, + VGfloat value); +VGint mask_layer_width(struct vg_mask_layer *layer); +VGint mask_layer_height(struct vg_mask_layer *layer); +void mask_copy(struct vg_mask_layer *layer, + VGint sx, VGint sy, + VGint dx, VGint dy, + VGint width, VGint height); + +void mask_render_to(struct path *path, + VGbitfield paint_modes, + VGMaskOperation operation); + +void mask_using_layer(struct vg_mask_layer *layer, + VGMaskOperation operation, + VGint x, VGint y, + VGint width, VGint height); +void mask_using_image(struct vg_image *image, + VGMaskOperation operation, + VGint x, VGint y, + VGint width, VGint height); +void mask_fill(VGint x, VGint y, + VGint width, VGint height, + VGfloat value); + +VGint mask_bind_samplers(struct pipe_sampler_state **samplers, + struct pipe_texture **textures); + +#endif diff --git a/src/gallium/state_trackers/vega/matrix.h b/src/gallium/state_trackers/vega/matrix.h new file mode 100644 index 00000000000..4c207f912a8 --- /dev/null +++ b/src/gallium/state_trackers/vega/matrix.h @@ -0,0 +1,462 @@ +/************************************************************************** + * + * 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 MATRIX_H +#define MATRIX_H + +#include "VG/openvg.h" + +#include "pipe/p_compiler.h" +#include "util/u_math.h" + +#include <stdio.h> +#include <math.h> + +#define floatsEqual(x, y) (fabs(x - y) <= 0.00001f * MIN2(fabs(x), fabs(y))) +#define floatIsZero(x) (floatsEqual((x) + 1, 1)) +#define ABS(x) (fabsf(x)) + +#define DEGREES_TO_RADIANS(d) (0.0174532925199 * (d)) +#define FLT_TO_INT(flt) float_to_int_floor(((VGuint*)&(flt))[0]) + +static INLINE VGint float_to_int_floor(VGuint bits) +{ + int sign = (bits >> 31) ? -1 : 1; + int exp = ((bits >> 23) & 255) - 127; + int mant = bits & 0x007fffff; + int sh = 23 - exp; + + /* abs(value) >= 2^31 -> clamp. */ + + if (exp >= 31) + return (VGint)((sign < 0) ? 0x80000000u : 0x7fffffffu); + + /* abs(value) < 1 -> return -1 or 0. */ + + if (exp < 0) + return (sign < 0 && (exp > -127 || mant != 0)) ? -1 : 0; + + /* abs(value) >= 2^23 -> shift left. */ + + mant |= 0x00800000; + if (sh <= 0) + return sign * (mant << -sh); + + /* Negative -> add a rounding term. */ + + if (sign < 0) + mant += (1 << sh) - 1; + + /* Shift right to obtain the result. */ + + return sign * (mant >> sh); +} + + +struct matrix { + VGfloat m[9]; +}; + +static INLINE void matrix_init(struct matrix *mat, + const VGfloat *val) +{ + memcpy(mat->m, val, sizeof(VGfloat) * 9); +} + +static INLINE void matrix_inits(struct matrix *mat, + VGfloat m11, VGfloat m12, VGfloat m13, + VGfloat m21, VGfloat m22, VGfloat m23, + VGfloat m31, VGfloat m32, VGfloat m33) +{ + mat->m[0] = m11; mat->m[1] = m12; mat->m[2] = m13; + mat->m[3] = m21; mat->m[4] = m22; mat->m[5] = m23; + mat->m[6] = m31; mat->m[7] = m32; mat->m[8] = m33; +} + +static INLINE void matrix_load_identity(struct matrix *matrix) +{ + static const VGfloat identity[9] = {1.f, 0.f, 0.f, + 0.f, 1.f, 0.f, + 0.f, 0.f, 1.f}; + memcpy(matrix->m, identity, sizeof(identity)); +} + +static INLINE VGboolean matrix_is_identity(struct matrix *matrix) +{ + return floatsEqual(matrix->m[0], 1) && floatIsZero(matrix->m[1]) && + floatIsZero(matrix->m[2]) && + floatIsZero(matrix->m[3]) && floatsEqual(matrix->m[4], 1) && + floatIsZero(matrix->m[5]) && + floatIsZero(matrix->m[6]) && floatIsZero(matrix->m[7]) && + floatIsZero(matrix->m[8]); +} + +static INLINE VGboolean matrix_is_affine(struct matrix *matrix) +{ + return floatIsZero(matrix->m[2]) && floatIsZero(matrix->m[5]) + && floatsEqual(matrix->m[8], 1); +} + + +static INLINE void matrix_make_affine(struct matrix *matrix) +{ + matrix->m[2] = 0.f; + matrix->m[5] = 0.f; + matrix->m[8] = 1.f; +} + +static INLINE void matrix_mult(struct matrix *dst, + struct matrix *src) +{ + VGfloat m11 = dst->m[0]*src->m[0] + dst->m[3]*src->m[1] + dst->m[6]*src->m[2]; + VGfloat m12 = dst->m[0]*src->m[3] + dst->m[3]*src->m[4] + dst->m[6]*src->m[5]; + VGfloat m13 = dst->m[0]*src->m[6] + dst->m[3]*src->m[7] + dst->m[6]*src->m[8]; + + VGfloat m21 = dst->m[1]*src->m[0] + dst->m[4]*src->m[1] + dst->m[7]*src->m[2]; + VGfloat m22 = dst->m[1]*src->m[3] + dst->m[4]*src->m[4] + dst->m[7]*src->m[5]; + VGfloat m23 = dst->m[1]*src->m[6] + dst->m[4]*src->m[7] + dst->m[7]*src->m[8]; + + VGfloat m31 = dst->m[2]*src->m[0] + dst->m[5]*src->m[1] + dst->m[8]*src->m[2]; + VGfloat m32 = dst->m[2]*src->m[3] + dst->m[5]*src->m[4] + dst->m[8]*src->m[5]; + VGfloat m33 = dst->m[2]*src->m[6] + dst->m[5]*src->m[7] + dst->m[8]*src->m[8]; + + dst->m[0] = m11; dst->m[1] = m21; dst->m[2] = m31; + dst->m[3] = m12; dst->m[4] = m22; dst->m[5] = m32; + dst->m[6] = m13; dst->m[7] = m23; dst->m[8] = m33; +} + + +static INLINE void matrix_map_point(struct matrix *mat, + VGfloat x, VGfloat y, + VGfloat *out_x, VGfloat *out_y) +{ + /* to be able to do matrix_map_point(m, x, y, &x, &y) use + * temporaries */ + VGfloat tmp_x = x, tmp_y = y; + + *out_x = mat->m[0]*tmp_x + mat->m[3]*tmp_y + mat->m[6]; + *out_y = mat->m[1]*tmp_x + mat->m[4]*tmp_y + mat->m[7]; + if (!matrix_is_affine(mat)) { + VGfloat w = 1/(mat->m[2]*tmp_x + mat->m[5]*tmp_y + mat->m[8]); + *out_x *= w; + *out_y *= w; + } +} + +static INLINE void matrix_translate(struct matrix *dst, + VGfloat tx, VGfloat ty) +{ + if (!matrix_is_affine(dst)) { + struct matrix trans_matrix; + matrix_load_identity(&trans_matrix); + trans_matrix.m[6] = tx; + trans_matrix.m[7] = ty; + matrix_mult(dst, &trans_matrix); + } else { + dst->m[6] += tx*dst->m[0] + ty*dst->m[3]; + dst->m[7] += ty*dst->m[4] + tx*dst->m[1]; + } +} + +static INLINE void matrix_scale(struct matrix *dst, + VGfloat sx, VGfloat sy) +{ + if (!matrix_is_affine(dst)) { + struct matrix scale_matrix; + matrix_load_identity(&scale_matrix); + scale_matrix.m[0] = sx; + scale_matrix.m[4] = sy; + matrix_mult(dst, &scale_matrix); + } else { + dst->m[0] *= sx; dst->m[1] *= sx; + dst->m[3] *= sy; dst->m[4] *= sy; + } +} + +static INLINE void matrix_shear(struct matrix *dst, + VGfloat shx, VGfloat shy) +{ + struct matrix shear_matrix; + matrix_load_identity(&shear_matrix); + shear_matrix.m[1] = shy; + shear_matrix.m[3] = shx; + matrix_mult(dst, &shear_matrix); +} + +static INLINE void matrix_rotate(struct matrix *dst, + VGfloat angle) +{ + struct matrix mat; + float sin_val = 0; + float cos_val = 0; + + + if (floatsEqual(angle, 90) || floatsEqual(angle, -270)) + sin_val = 1.f; + else if (floatsEqual(angle, 270) || floatsEqual(angle, -90)) + sin_val = -1.f; + else if (floatsEqual(angle, 180)) + cos_val = -1.f; + else { + float radians = DEGREES_TO_RADIANS(angle); + sin_val = sin(radians); + cos_val = cos(radians); + } + + if (!matrix_is_affine(dst)) { + matrix_load_identity(&mat); + mat.m[0] = cos_val; mat.m[1] = sin_val; + mat.m[3] = -sin_val; mat.m[4] = cos_val; + + matrix_mult(dst, &mat); + } else { + VGfloat m11 = cos_val*dst->m[0] + sin_val*dst->m[3]; + VGfloat m12 = cos_val*dst->m[1] + sin_val*dst->m[4]; + VGfloat m21 = -sin_val*dst->m[0] + cos_val*dst->m[3]; + VGfloat m22 = -sin_val*dst->m[1] + cos_val*dst->m[4]; + dst->m[0] = m11; dst->m[1] = m12; + dst->m[3] = m21; dst->m[4] = m22; + } +} + + +static INLINE VGfloat matrix_determinant(struct matrix *mat) +{ + return mat->m[0]*(mat->m[8]*mat->m[4]-mat->m[7]*mat->m[5]) - + mat->m[3]*(mat->m[8]*mat->m[1]-mat->m[7]*mat->m[2])+ + mat->m[6]*(mat->m[5]*mat->m[1]-mat->m[4]*mat->m[2]); +} + + +static INLINE void matrix_adjoint(struct matrix *mat) +{ + VGfloat h[9]; + h[0] = mat->m[4]*mat->m[8] - mat->m[5]*mat->m[7]; + h[3] = mat->m[5]*mat->m[6] - mat->m[3]*mat->m[8]; + h[6] = mat->m[3]*mat->m[7] - mat->m[4]*mat->m[6]; + h[1] = mat->m[2]*mat->m[7] - mat->m[1]*mat->m[8]; + h[4] = mat->m[0]*mat->m[8] - mat->m[2]*mat->m[6]; + h[7] = mat->m[1]*mat->m[6] - mat->m[0]*mat->m[7]; + h[2] = mat->m[1]*mat->m[5] - mat->m[2]*mat->m[4]; + h[5] = mat->m[2]*mat->m[3] - mat->m[0]*mat->m[5]; + h[8] = mat->m[0]*mat->m[4] - mat->m[1]*mat->m[3]; + + + memcpy(mat->m, h, sizeof(VGfloat) * 9); +} + +static INLINE void matrix_divs(struct matrix *mat, + VGfloat s) +{ + mat->m[0] /= s; + mat->m[1] /= s; + mat->m[2] /= s; + mat->m[3] /= s; + mat->m[4] /= s; + mat->m[5] /= s; + mat->m[6] /= s; + mat->m[7] /= s; + mat->m[8] /= s; +} + +static INLINE VGboolean matrix_invert(struct matrix *mat) +{ + VGfloat det = matrix_determinant(mat); + + if (floatIsZero(det)) + return VG_FALSE; + + matrix_adjoint(mat); + matrix_divs(mat, det); + return VG_TRUE; +} + +static INLINE VGboolean matrix_is_invertible(struct matrix *mat) +{ + return !floatIsZero(matrix_determinant(mat)); +} + + +static INLINE VGboolean matrix_square_to_quad(VGfloat dx0, VGfloat dy0, + VGfloat dx1, VGfloat dy1, + VGfloat dx3, VGfloat dy3, + VGfloat dx2, VGfloat dy2, + struct matrix *mat) +{ + VGfloat ax = dx0 - dx1 + dx2 - dx3; + VGfloat ay = dy0 - dy1 + dy2 - dy3; + + if (floatIsZero(ax) && floatIsZero(ay)) { + /* affine case */ + matrix_inits(mat, + dx1 - dx0, dy1 - dy0, 0, + dx2 - dx1, dy2 - dy1, 0, + dx0, dy0, 1); + } else { + VGfloat a, b, c, d, e, f, g, h; + VGfloat ax1 = dx1 - dx2; + VGfloat ax2 = dx3 - dx2; + VGfloat ay1 = dy1 - dy2; + VGfloat ay2 = dy3 - dy2; + + /* determinants */ + VGfloat gtop = ax * ay2 - ax2 * ay; + VGfloat htop = ax1 * ay - ax * ay1; + VGfloat bottom = ax1 * ay2 - ax2 * ay1; + + if (!bottom) + return VG_FALSE; + + g = gtop / bottom; + h = htop / bottom; + + a = dx1 - dx0 + g * dx1; + b = dx3 - dx0 + h * dx3; + c = dx0; + d = dy1 - dy0 + g * dy1; + e = dy3 - dy0 + h * dy3; + f = dy0; + + matrix_inits(mat, + a, d, g, + b, e, h, + c, f, 1.f); + } + + return VG_TRUE; +} + +static INLINE VGboolean matrix_quad_to_square(VGfloat sx0, VGfloat sy0, + VGfloat sx1, VGfloat sy1, + VGfloat sx2, VGfloat sy2, + VGfloat sx3, VGfloat sy3, + struct matrix *mat) +{ + if (!matrix_square_to_quad(sx0, sy0, sx1, sy1, + sx2, sy2, sx3, sy3, + mat)) + return VG_FALSE; + + return matrix_invert(mat); +} + + +static INLINE VGboolean matrix_quad_to_quad(VGfloat dx0, VGfloat dy0, + VGfloat dx1, VGfloat dy1, + VGfloat dx2, VGfloat dy2, + VGfloat dx3, VGfloat dy3, + VGfloat sx0, VGfloat sy0, + VGfloat sx1, VGfloat sy1, + VGfloat sx2, VGfloat sy2, + VGfloat sx3, VGfloat sy3, + struct matrix *mat) +{ + struct matrix sqr_to_qd; + + if (!matrix_square_to_quad(dx0, dy0, dx1, dy1, + dx2, dy2, dx3, dy3, + mat)) + return VG_FALSE; + + if (!matrix_quad_to_square(sx0, sy0, sx1, sy1, + sx2, sy2, sx3, sy3, + &sqr_to_qd)) + return VG_FALSE; + + matrix_mult(mat, &sqr_to_qd); + + return VG_TRUE; +} + + +static INLINE VGboolean null_line(const VGfloat *l) +{ + return floatsEqual(l[0], l[2]) && floatsEqual(l[1], l[3]); +} + +static INLINE void line_normal(float *l, float *norm) +{ + norm[0] = l[0]; + norm[1] = l[1]; + + norm[2] = l[0] + (l[3] - l[1]); + norm[3] = l[1] - (l[2] - l[0]); +} + +static INLINE void line_normalize(float *l) +{ + float x = l[2] - l[0]; + float y = l[3] - l[1]; + float len = sqrt(x*x + y*y); + l[2] = l[0] + x/len; + l[3] = l[1] + y/len; +} + +static INLINE VGfloat line_length(VGfloat x1, VGfloat y1, + VGfloat x2, VGfloat y2) +{ + VGfloat x = x2 - x1; + VGfloat y = y2 - y1; + return sqrt(x*x + y*y); +} + +static INLINE VGfloat line_lengthv(const VGfloat *l) +{ + VGfloat x = l[2] - l[0]; + VGfloat y = l[3] - l[1]; + return sqrt(x*x + y*y); +} + + +static INLINE void line_point_at(float *l, float t, float *pt) +{ + float dx = l[2] - l[0]; + float dy = l[3] - l[1]; + + pt[0] = l[0] + dx * t; + pt[1] = l[1] + dy * t; +} + +static INLINE void vector_unit(float *vec) +{ + float len = sqrt(vec[0] * vec[0] + vec[1] * vec[1]); + vec[0] /= len; + vec[1] /= len; +} + +static INLINE void line_normal_vector(float *line, float *vec) +{ + VGfloat normal[4]; + + line_normal(line, normal); + + vec[0] = normal[2] - normal[0]; + vec[1] = normal[3] - normal[1]; + + vector_unit(vec); +} + +#endif diff --git a/src/gallium/state_trackers/vega/paint.c b/src/gallium/state_trackers/vega/paint.c new file mode 100644 index 00000000000..04a6ba9cdcd --- /dev/null +++ b/src/gallium/state_trackers/vega/paint.c @@ -0,0 +1,699 @@ +/************************************************************************** + * + * 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 "paint.h" + +#include "shaders_cache.h" +#include "matrix.h" +#include "image.h" +#include "st_inlines.h" + +#include "pipe/p_compiler.h" +#include "pipe/p_inlines.h" + +#include "util/u_memory.h" +#include "util/u_math.h" + +#include "cso_cache/cso_context.h" + +struct vg_paint { + struct vg_object base; + + VGPaintType type; + + struct { + VGfloat color[4]; + VGint colori[4]; + } solid; + + struct { + VGColorRampSpreadMode spread; + VGuint color_data[1024]; + struct { + VGfloat coords[4]; + VGint coordsi[4]; + } linear; + struct { + VGfloat vals[5]; + VGint valsi[5]; + } radial; + struct pipe_texture *texture; + struct pipe_sampler_state sampler; + + VGfloat *ramp_stops; + VGint *ramp_stopsi; + VGint num_stops; + + VGboolean color_ramps_premultiplied; + } gradient; + + struct { + struct pipe_texture *texture; + VGTilingMode tiling_mode; + struct pipe_sampler_state sampler; + } pattern; + + struct pipe_constant_buffer cbuf; + struct pipe_shader_state fs_state; + void *fs; +}; + +static INLINE VGuint mix_pixels(VGuint p1, VGuint a, VGuint p2, VGuint b) +{ + VGuint t = (p1 & 0xff00ff) * a + (p2 & 0xff00ff) * b; + t >>= 8; t &= 0xff00ff; + + p1 = ((p1 >> 8) & 0xff00ff) * a + ((p2 >> 8) & 0xff00ff) * b; + p1 &= 0xff00ff00; p1 |= t; + + return p1; +} + +static INLINE VGuint float4_to_argb(const VGfloat *clr) +{ + return float_to_ubyte(clr[3]) << 24 | + float_to_ubyte(clr[0]) << 16 | + float_to_ubyte(clr[1]) << 8 | + float_to_ubyte(clr[2]) << 0; +} + +static INLINE void create_gradient_data(const VGfloat *ramp_stops, + VGint num, + VGuint *data, + VGint size) +{ + VGint i; + VGint pos = 0; + VGfloat fpos = 0, incr = 1.f / size; + VGuint last_color; + + while (fpos < ramp_stops[0]) { + data[pos] = float4_to_argb(ramp_stops + 1); + fpos += incr; + ++pos; + } + + for (i = 0; i < num - 1; ++i) { + VGint rcur = 5 * i; + VGint rnext = 5 * (i + 1); + VGfloat delta = 1.f/(ramp_stops[rnext] - ramp_stops[rcur]); + while (fpos < ramp_stops[rnext] && pos < size) { + VGint dist = 256 * ((fpos - ramp_stops[rcur]) * delta); + VGint idist = 256 - dist; + VGuint current_color = float4_to_argb(ramp_stops + rcur + 1); + VGuint next_color = float4_to_argb(ramp_stops + rnext + 1); + data[pos] = mix_pixels(current_color, idist, + next_color, dist); + fpos += incr; + ++pos; + } + } + + last_color = float4_to_argb(ramp_stops + ((num - 1) * 5 + 1)); + while (pos < size) { + data[pos] = last_color; + ++pos; + } + data[size-1] = last_color; +} + +static INLINE struct pipe_texture *create_gradient_texture(struct vg_paint *p) +{ + struct pipe_context *pipe = p->base.ctx->pipe; + struct pipe_screen *screen = pipe->screen; + struct pipe_texture *tex = 0; + struct pipe_texture templ; + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_1D; + templ.format = PIPE_FORMAT_A8R8G8B8_UNORM; + templ.last_level = 0; + templ.width[0] = 1024; + templ.height[0] = 1; + templ.depth[0] = 1; + pf_get_block(PIPE_FORMAT_A8R8G8B8_UNORM, &templ.block); + templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; + + tex = screen->texture_create(screen, &templ); + + { /* upload color_data */ + struct pipe_transfer *transfer = + st_no_flush_get_tex_transfer(p->base.ctx, tex, 0, 0, 0, + PIPE_TRANSFER_WRITE, 0, 0, 1024, 1); + void *map = screen->transfer_map(screen, transfer); + memcpy(map, p->gradient.color_data, sizeof(VGint)*1024); + screen->transfer_unmap(screen, transfer); + screen->tex_transfer_destroy(transfer); + } + + return tex; +} + +struct vg_paint * paint_create(struct vg_context *ctx) +{ + struct vg_paint *paint = CALLOC_STRUCT(vg_paint); + const VGfloat default_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; + const VGfloat def_ling[] = {0.0f, 0.0f, 1.0f, 0.0f}; + const VGfloat def_radg[] = {0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + vg_init_object(&paint->base, ctx, VG_OBJECT_PAINT); + vg_context_add_object(ctx, VG_OBJECT_PAINT, paint); + + paint->type = VG_PAINT_TYPE_COLOR; + memcpy(paint->solid.color, default_color, + 4 * sizeof(VGfloat)); + paint->gradient.spread = VG_COLOR_RAMP_SPREAD_PAD; + memcpy(paint->gradient.linear.coords, def_ling, + 4 * sizeof(VGfloat)); + memcpy(paint->gradient.radial.vals, def_radg, + 5 * sizeof(VGfloat)); + + paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + paint->gradient.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + paint->gradient.sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST; + paint->gradient.sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST; + paint->gradient.sampler.normalized_coords = 1; + + memcpy(&paint->pattern.sampler, + &paint->gradient.sampler, + sizeof(struct pipe_sampler_state)); + + return paint; +} + +void paint_destroy(struct vg_paint *paint) +{ + struct vg_context *ctx = paint->base.ctx; + if (paint->pattern.texture) + pipe_texture_reference(&paint->pattern.texture, NULL); + if (ctx) + vg_context_remove_object(ctx, VG_OBJECT_PAINT, paint); + + free(paint->gradient.ramp_stopsi); + free(paint->gradient.ramp_stops); + free(paint); +} + +void paint_set_color(struct vg_paint *paint, + const VGfloat *color) +{ + paint->solid.color[0] = color[0]; + paint->solid.color[1] = color[1]; + paint->solid.color[2] = color[2]; + paint->solid.color[3] = color[3]; + + paint->solid.colori[0] = FLT_TO_INT(color[0]); + paint->solid.colori[1] = FLT_TO_INT(color[1]); + paint->solid.colori[2] = FLT_TO_INT(color[2]); + paint->solid.colori[3] = FLT_TO_INT(color[3]); +} + +static INLINE void paint_color_buffer(struct vg_paint *paint, void *buffer) +{ + VGfloat *map = (VGfloat*)buffer; + memcpy(buffer, paint->solid.color, 4 * sizeof(VGfloat)); + map[4] = 0.f; + map[5] = 1.f; + map[6] = 2.f; + map[7] = 4.f; +} + +static INLINE void paint_linear_gradient_buffer(struct vg_paint *paint, void *buffer) +{ + struct vg_context *ctx = paint->base.ctx; + VGfloat *map = (VGfloat*)buffer; + + map[0] = paint->gradient.linear.coords[2] - paint->gradient.linear.coords[0]; + map[1] = paint->gradient.linear.coords[3] - paint->gradient.linear.coords[1]; + map[2] = 1.f / (map[0] * map[0] + map[1] * map[1]); + map[3] = 1.f; + + map[4] = 0.f; + map[5] = 1.f; + map[6] = 2.f; + map[7] = 4.f; + { + struct matrix mat; + struct matrix inv; + matrix_load_identity(&mat); + matrix_translate(&mat, -paint->gradient.linear.coords[0], -paint->gradient.linear.coords[1]); + memcpy(&inv, &ctx->state.vg.fill_paint_to_user_matrix, + sizeof(struct matrix)); + matrix_invert(&inv); + matrix_mult(&inv, &mat); + memcpy(&mat, &inv, + sizeof(struct matrix)); + + map[8] = mat.m[0]; map[9] = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f; + map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f; + map[16] = mat.m[2]; map[17] = mat.m[5]; map[18] = mat.m[8]; map[19] = 0.f; + } +#if 0 + debug_printf("Coords (%f, %f, %f, %f)\n", + map[0], map[1], map[2], map[3]); +#endif +} + + +static INLINE void paint_radial_gradient_buffer(struct vg_paint *paint, void *buffer) +{ + VGfloat *radialCoords = paint->gradient.radial.vals; + struct vg_context *ctx = paint->base.ctx; + + VGfloat *map = (VGfloat*)buffer; + + map[0] = radialCoords[0] - radialCoords[2]; + map[1] = radialCoords[1] - radialCoords[3]; + map[2] = -map[0] * map[0] - map[1] * map[1] + + radialCoords[4] * radialCoords[4]; + map[3] = 1.f; + + map[4] = 0.f; + map[5] = 1.f; + map[6] = 2.f; + map[7] = 4.f; + + { + struct matrix mat; + struct matrix inv; + matrix_load_identity(&mat); + matrix_translate(&mat, -radialCoords[2], -radialCoords[3]); + memcpy(&inv, &ctx->state.vg.fill_paint_to_user_matrix, + sizeof(struct matrix)); + matrix_invert(&inv); + matrix_mult(&inv, &mat); + memcpy(&mat, &inv, + sizeof(struct matrix)); + + map[8] = mat.m[0]; map[9] = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f; + map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f; + map[16] = mat.m[2]; map[17] = mat.m[5]; map[18] = mat.m[8]; map[19] = 0.f; + } + +#if 0 + debug_printf("Coords (%f, %f, %f, %f)\n", + map[0], map[1], map[2], map[3]); +#endif +} + + +static INLINE void paint_pattern_buffer(struct vg_paint *paint, void *buffer) +{ + struct vg_context *ctx = paint->base.ctx; + + VGfloat *map = (VGfloat *)buffer; + memcpy(map, paint->solid.color, 4 * sizeof(VGfloat)); + + map[4] = 0.f; + map[5] = 1.f; + map[6] = paint->pattern.texture->width[0]; + map[7] = paint->pattern.texture->height[0]; + { + struct matrix mat; + memcpy(&mat, &ctx->state.vg.fill_paint_to_user_matrix, + sizeof(struct matrix)); + matrix_invert(&mat); + { + struct matrix pm; + memcpy(&pm, &ctx->state.vg.path_user_to_surface_matrix, + sizeof(struct matrix)); + matrix_invert(&pm); + matrix_mult(&pm, &mat); + memcpy(&mat, &pm, sizeof(struct matrix)); + } + + map[8] = mat.m[0]; map[9] = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f; + map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f; + map[16] = mat.m[2]; map[17] = mat.m[5]; map[18] = mat.m[8]; map[19] = 0.f; + } +} + +void paint_set_type(struct vg_paint *paint, VGPaintType type) +{ + paint->type = type; +} + +void paint_set_ramp_stops(struct vg_paint *paint, const VGfloat *stops, + int num) +{ + const VGfloat default_stops[] = {0.0f, 0.0f, 0.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 1.0f}; + VGint i; + const VGint num_stops = num / 5; + VGfloat last_coord; + + paint->gradient.num_stops = num; + if (num) { + free(paint->gradient.ramp_stops); + paint->gradient.ramp_stops = malloc(sizeof(VGfloat)*num); + memcpy(paint->gradient.ramp_stops, stops, sizeof(VGfloat)*num); + } else + return; + + /* stops must be in increasing order. the last stop is 1.0. if the + * first one is bigger than 1 then the whole sequence is invalid*/ + if (stops[0] > 1) { + stops = default_stops; + num = 10; + } + last_coord = stops[0]; + for (i = 1; i < num_stops; ++i) { + VGint idx = 5 * i; + VGfloat coord = stops[idx]; + if (!floatsEqual(last_coord, coord) && coord < last_coord) { + stops = default_stops; + num = 10; + break; + } + last_coord = coord; + } + + create_gradient_data(stops, num / 5, paint->gradient.color_data, + 1024); + + if (paint->gradient.texture) { + pipe_texture_reference(&paint->gradient.texture, NULL); + paint->gradient.texture = 0; + } + + paint->gradient.texture = create_gradient_texture(paint); +} + +void paint_set_colori(struct vg_paint *p, + VGuint rgba) +{ + p->solid.color[0] = ((rgba >> 24) & 0xff) / 255.f; + p->solid.color[1] = ((rgba >> 16) & 0xff) / 255.f; + p->solid.color[2] = ((rgba >> 8) & 0xff) / 255.f; + p->solid.color[3] = ((rgba >> 0) & 0xff) / 255.f; +} + +VGuint paint_colori(struct vg_paint *p) +{ +#define F2B(f) (float_to_ubyte(f)) + + return ((F2B(p->solid.color[0]) << 24) | + (F2B(p->solid.color[1]) << 16) | + (F2B(p->solid.color[2]) << 8) | + (F2B(p->solid.color[3]) << 0)); +#undef F2B +} + +void paint_set_linear_gradient(struct vg_paint *paint, + const VGfloat *coords) +{ + memcpy(paint->gradient.linear.coords, coords, sizeof(VGfloat) * 4); +} + +void paint_set_spread_mode(struct vg_paint *paint, + VGint mode) +{ + paint->gradient.spread = mode; + switch(mode) { + case VG_COLOR_RAMP_SPREAD_PAD: + paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + break; + case VG_COLOR_RAMP_SPREAD_REPEAT: + paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_REPEAT; + break; + case VG_COLOR_RAMP_SPREAD_REFLECT: + paint->gradient.sampler.wrap_s = PIPE_TEX_WRAP_MIRROR_REPEAT; + break; + } +} + +VGColorRampSpreadMode paint_spread_mode(struct vg_paint *paint) +{ + return paint->gradient.spread; +} + +void paint_set_radial_gradient(struct vg_paint *paint, + const VGfloat *values) +{ + memcpy(paint->gradient.radial.vals, values, sizeof(VGfloat) * 5); +} + +void paint_set_pattern(struct vg_paint *paint, + struct vg_image *img) +{ + if (paint->pattern.texture) + pipe_texture_reference(&paint->pattern.texture, NULL); + + paint->pattern.texture = 0; + pipe_texture_reference(&paint->pattern.texture, + img->texture); +} + +void paint_set_pattern_tiling(struct vg_paint *paint, + VGTilingMode mode) +{ + paint->pattern.tiling_mode = mode; + + switch(mode) { + case VG_TILE_FILL: + paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_BORDER; + paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_BORDER; + break; + case VG_TILE_PAD: + paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + break; + case VG_TILE_REPEAT: + paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_REPEAT; + paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_REPEAT; + break; + case VG_TILE_REFLECT: + paint->pattern.sampler.wrap_s = PIPE_TEX_WRAP_MIRROR_REPEAT; + paint->pattern.sampler.wrap_t = PIPE_TEX_WRAP_MIRROR_REPEAT; + break; + default: + debug_assert("!Unknown tiling mode"); + } +} + +void paint_get_color(struct vg_paint *paint, + VGfloat *color) +{ + color[0] = paint->solid.color[0]; + color[1] = paint->solid.color[1]; + color[2] = paint->solid.color[2]; + color[3] = paint->solid.color[3]; +} + +void paint_ramp_stops(struct vg_paint *paint, VGfloat *stops, + int num) +{ + memcpy(stops, paint->gradient.ramp_stops, sizeof(VGfloat)*num); +} + +void paint_linear_gradient(struct vg_paint *paint, + VGfloat *coords) +{ + memcpy(coords, paint->gradient.linear.coords, sizeof(VGfloat)*4); +} + +void paint_radial_gradient(struct vg_paint *paint, + VGfloat *coords) +{ + memcpy(coords, paint->gradient.radial.vals, sizeof(VGfloat)*5); +} + +int paint_num_ramp_stops(struct vg_paint *paint) +{ + return paint->gradient.num_stops; +} + +VGPaintType paint_type(struct vg_paint *paint) +{ + return paint->type; +} + +void paint_set_coloriv(struct vg_paint *paint, + const VGint *color) +{ + paint->solid.color[0] = color[0]; + paint->solid.color[1] = color[1]; + paint->solid.color[2] = color[2]; + paint->solid.color[3] = color[3]; + + paint->solid.colori[0] = color[0]; + paint->solid.colori[1] = color[1]; + paint->solid.colori[2] = color[2]; + paint->solid.colori[3] = color[3]; +} + +void paint_get_coloriv(struct vg_paint *paint, + VGint *color) +{ + color[0] = paint->solid.colori[0]; + color[1] = paint->solid.colori[1]; + color[2] = paint->solid.colori[2]; + color[3] = paint->solid.colori[3]; +} + +void paint_set_color_ramp_premultiplied(struct vg_paint *paint, + VGboolean set) +{ + paint->gradient.color_ramps_premultiplied = set; +} + +VGboolean paint_color_ramp_premultiplied(struct vg_paint *paint) +{ + return paint->gradient.color_ramps_premultiplied; +} + +void paint_set_ramp_stopsi(struct vg_paint *paint, const VGint *stops, + int num) +{ + if (num) { + free(paint->gradient.ramp_stopsi); + paint->gradient.ramp_stopsi = malloc(sizeof(VGint)*num); + memcpy(paint->gradient.ramp_stopsi, stops, sizeof(VGint)*num); + } +} + +void paint_ramp_stopsi(struct vg_paint *paint, VGint *stops, + int num) +{ + memcpy(stops, paint->gradient.ramp_stopsi, sizeof(VGint)*num); +} + +void paint_set_linear_gradienti(struct vg_paint *paint, + const VGint *coords) +{ + memcpy(paint->gradient.linear.coordsi, coords, sizeof(VGint) * 4); +} + +void paint_linear_gradienti(struct vg_paint *paint, + VGint *coords) +{ + memcpy(coords, paint->gradient.linear.coordsi, sizeof(VGint)*4); +} + +void paint_set_radial_gradienti(struct vg_paint *paint, + const VGint *values) +{ + memcpy(paint->gradient.radial.valsi, values, sizeof(VGint) * 5); +} + +void paint_radial_gradienti(struct vg_paint *paint, + VGint *coords) +{ + memcpy(coords, paint->gradient.radial.valsi, sizeof(VGint)*5); +} + +VGTilingMode paint_pattern_tiling(struct vg_paint *paint) +{ + return paint->pattern.tiling_mode; +} + +VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers, + struct pipe_texture **textures) +{ + struct vg_context *ctx = vg_current_context(); + + switch(paint->type) { + case VG_PAINT_TYPE_LINEAR_GRADIENT: + case VG_PAINT_TYPE_RADIAL_GRADIENT: { + if (paint->gradient.texture) { + paint->gradient.sampler.min_img_filter = image_sampler_filter(ctx); + paint->gradient.sampler.mag_img_filter = image_sampler_filter(ctx); + samplers[0] = &paint->gradient.sampler; + textures[0] = paint->gradient.texture; + return 1; + } + } + break; + case VG_PAINT_TYPE_PATTERN: { + memcpy(paint->pattern.sampler.border_color, + ctx->state.vg.tile_fill_color, + sizeof(VGfloat) * 4); + paint->pattern.sampler.min_img_filter = image_sampler_filter(ctx); + paint->pattern.sampler.mag_img_filter = image_sampler_filter(ctx); + samplers[0] = &paint->pattern.sampler; + textures[0] = paint->pattern.texture; + return 1; + } + break; + default: + samplers[0] = &paint->pattern.sampler; /* dummy */ + textures[0] = 0; + return 0; + break; + } + return 0; +} + +void paint_resolve_type(struct vg_paint *paint) +{ + if (paint->type == VG_PAINT_TYPE_PATTERN && + !paint->pattern.texture) { + paint->type = VG_PAINT_TYPE_COLOR; + } +} + +VGint paint_constant_buffer_size(struct vg_paint *paint) +{ + switch(paint->type) { + case VG_PAINT_TYPE_COLOR: + return 8 * sizeof(VGfloat);/*4 color + 4 constants (0.f,1.f,2.f,4.f)*/ + break; + case VG_PAINT_TYPE_LINEAR_GRADIENT: + return 20 * sizeof(VGfloat); + break; + case VG_PAINT_TYPE_RADIAL_GRADIENT: + return 20 * sizeof(VGfloat); + break; + case VG_PAINT_TYPE_PATTERN: + return 20 * sizeof(VGfloat); + break; + default: + debug_printf("Uknown paint type: %d\n", paint->type); + } + + return 0; +} + +void paint_fill_constant_buffer(struct vg_paint *paint, + void *buffer) +{ + switch(paint->type) { + case VG_PAINT_TYPE_COLOR: + paint_color_buffer(paint, buffer); + break; + case VG_PAINT_TYPE_LINEAR_GRADIENT: + paint_linear_gradient_buffer(paint, buffer); + break; + case VG_PAINT_TYPE_RADIAL_GRADIENT: + paint_radial_gradient_buffer(paint, buffer); + break; + case VG_PAINT_TYPE_PATTERN: + paint_pattern_buffer(paint, buffer); + break; + + default: + abort(); + } +} diff --git a/src/gallium/state_trackers/vega/paint.h b/src/gallium/state_trackers/vega/paint.h new file mode 100644 index 00000000000..999b5c167ca --- /dev/null +++ b/src/gallium/state_trackers/vega/paint.h @@ -0,0 +1,118 @@ +/************************************************************************** + * + * 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 PAINT_H +#define PAINT_H + +#include "vg_context.h" + +#include "VG/openvg.h" +#include "pipe/p_state.h" + +struct vg_paint; +struct vg_image; +struct pipe_sampler_state; +struct pipe_texture; + +struct vg_paint *paint_create(struct vg_context *ctx); +void paint_destroy(struct vg_paint *paint); + +void paint_set_color(struct vg_paint *paint, + const VGfloat *color); +void paint_get_color(struct vg_paint *paint, + VGfloat *color); + +void paint_set_coloriv(struct vg_paint *paint, + const VGint *color); +void paint_get_coloriv(struct vg_paint *paint, + VGint *color); + +void paint_set_colori(struct vg_paint *paint, + VGuint rgba); + +VGuint paint_colori(struct vg_paint *paint); + +void paint_set_type(struct vg_paint *paint, VGPaintType type); +VGPaintType paint_type(struct vg_paint *paint); +void paint_resolve_type(struct vg_paint *paint); + +void paint_set_linear_gradient(struct vg_paint *paint, + const VGfloat *coords); +void paint_linear_gradient(struct vg_paint *paint, + VGfloat *coords); +void paint_set_linear_gradienti(struct vg_paint *paint, + const VGint *coords); +void paint_linear_gradienti(struct vg_paint *paint, + VGint *coords); + + +void paint_set_radial_gradient(struct vg_paint *paint, + const VGfloat *values); +void paint_radial_gradient(struct vg_paint *paint, + VGfloat *coords); +void paint_set_radial_gradienti(struct vg_paint *paint, + const VGint *values); +void paint_radial_gradienti(struct vg_paint *paint, + VGint *coords); + + +void paint_set_ramp_stops(struct vg_paint *paint, const VGfloat *stops, + int num); +void paint_ramp_stops(struct vg_paint *paint, VGfloat *stops, + int num); + +void paint_set_ramp_stopsi(struct vg_paint *paint, const VGint *stops, + int num); +void paint_ramp_stopsi(struct vg_paint *paint, VGint *stops, + int num); + +int paint_num_ramp_stops(struct vg_paint *paint); + +void paint_set_spread_mode(struct vg_paint *paint, + VGint mode); +VGColorRampSpreadMode paint_spread_mode(struct vg_paint *paint); + + +void paint_set_pattern(struct vg_paint *paint, + struct vg_image *img); +void paint_set_pattern_tiling(struct vg_paint *paint, + VGTilingMode mode); +VGTilingMode paint_pattern_tiling(struct vg_paint *paint); + +void paint_set_color_ramp_premultiplied(struct vg_paint *paint, + VGboolean set); +VGboolean paint_color_ramp_premultiplied(struct vg_paint *paint); + + +VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers, + struct pipe_texture **textures); + +VGint paint_constant_buffer_size(struct vg_paint *paint); +void paint_fill_constant_buffer(struct vg_paint *paint, + void *buffer); + + +#endif diff --git a/src/gallium/state_trackers/vega/path.c b/src/gallium/state_trackers/vega/path.c new file mode 100644 index 00000000000..d04f9d9ae64 --- /dev/null +++ b/src/gallium/state_trackers/vega/path.c @@ -0,0 +1,2034 @@ +/************************************************************************** + * + * 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 "path.h" + +#include "stroker.h" +#include "polygon.h" +#include "bezier.h" +#include "matrix.h" +#include "vg_context.h" +#include "util_array.h" +#include "arc.h" +#include "path_utils.h" +#include "paint.h" +#include "shader.h" + +#include "util/u_memory.h" + +#include <assert.h> + +#define DEBUG_PATH 0 + +struct path { + struct vg_object base; + VGbitfield caps; + VGboolean dirty; + VGboolean dirty_stroke; + + VGPathDatatype datatype; + + VGfloat scale; + VGfloat bias; + + VGint num_segments; + + struct array * segments; + struct array * control_points; + + struct { + struct polygon_array polygon_array; + struct matrix matrix; + } fill_polys; + + struct { + struct path *path; + struct matrix matrix; + VGfloat stroke_width; + VGfloat miter_limit; + VGCapStyle cap_style; + VGJoinStyle join_style; + } stroked; +}; + + +static INLINE void data_at(void **data, + struct path *p, + VGint start, VGint count, + VGfloat *out) +{ + VGPathDatatype dt = p->datatype; + VGint i; + VGint end = start + count; + VGfloat *itr = out; + + switch(dt) { + case VG_PATH_DATATYPE_S_8: { + VGbyte **bdata = (VGbyte **)data; + for (i = start; i < end; ++i) { + *itr = (*bdata)[i]; + ++itr; + } + *bdata += count; + } + break; + case VG_PATH_DATATYPE_S_16: { + VGshort **bdata = (VGshort **)data; + for (i = start; i < end; ++i) { + *itr = (*bdata)[i]; + ++itr; + } + *bdata += count; + } + break; + case VG_PATH_DATATYPE_S_32: { + VGint **bdata = (VGint **)data; + for (i = start; i < end; ++i) { + *itr = (*bdata)[i]; + ++itr; + } + *bdata += count; + } + break; + case VG_PATH_DATATYPE_F: { + VGfloat **fdata = (VGfloat **)data; + for (i = start; i < end; ++i) { + *itr = (*fdata)[i]; + ++itr; + } + *fdata += count; + } + break; + default: + debug_assert(!"Unknown path datatype!"); + } +} + + +void vg_float_to_datatype(VGPathDatatype datatype, + VGubyte *common_data, + const VGfloat *data, + VGint num_coords) +{ + VGint i; + switch(datatype) { + case VG_PATH_DATATYPE_S_8: { + for (i = 0; i < num_coords; ++i) { + common_data[i] = (VGubyte)data[i]; + } + } + break; + case VG_PATH_DATATYPE_S_16: { + VGshort *buf = (VGshort*)common_data; + for (i = 0; i < num_coords; ++i) { + buf[i] = (VGshort)data[i]; + } + } + break; + case VG_PATH_DATATYPE_S_32: { + VGint *buf = (VGint*)common_data; + for (i = 0; i < num_coords; ++i) { + buf[i] = (VGint)data[i]; + } + } + break; + case VG_PATH_DATATYPE_F: { + memcpy(common_data, data, sizeof(VGfloat) * num_coords); + } + break; + default: + debug_assert(!"Unknown path datatype!"); + } +} + +static void coords_adjust_by_scale_bias(struct path *p, + void *pdata, VGint num_coords, + VGfloat scale, VGfloat bias, + VGPathDatatype datatype) +{ + VGfloat data[8]; + void *coords = (VGfloat *)pdata; + VGubyte *common_data = (VGubyte *)pdata; + VGint size_dst = size_for_datatype(datatype); + VGint i; + + for (i = 0; i < num_coords; ++i) { + data_at(&coords, p, 0, 1, data); + data[0] = data[0] * scale + bias; + vg_float_to_datatype(datatype, common_data, data, 1); + common_data += size_dst; + } +} + +struct path * path_create(VGPathDatatype dt, VGfloat scale, VGfloat bias, + VGint segmentCapacityHint, + VGint coordCapacityHint, + VGbitfield capabilities) +{ + struct path *path = CALLOC_STRUCT(path); + + vg_init_object(&path->base, vg_current_context(), VG_OBJECT_PATH); + path->caps = capabilities & VG_PATH_CAPABILITY_ALL; + vg_context_add_object(vg_current_context(), VG_OBJECT_PATH, path); + + path->datatype = dt; + path->scale = scale; + path->bias = bias; + + path->segments = array_create(size_for_datatype(VG_PATH_DATATYPE_S_8)); + path->control_points = array_create(size_for_datatype(dt)); + + path->dirty = VG_TRUE; + path->dirty_stroke = VG_TRUE; + + return path; +} + +void path_destroy(struct path *p) +{ + vg_context_remove_object(vg_current_context(), VG_OBJECT_PATH, p); + + array_destroy(p->segments); + array_destroy(p->control_points); + array_destroy(p->fill_polys.polygon_array.array); + + if (p->stroked.path) + path_destroy(p->stroked.path); + + free(p); +} + +VGbitfield path_capabilities(struct path *p) +{ + return p->caps; +} + +void path_set_capabilities(struct path *p, VGbitfield bf) +{ + p->caps = (bf & VG_PATH_CAPABILITY_ALL); +} + +void path_append_data(struct path *p, + VGint numSegments, + const VGubyte * pathSegments, + const void * pathData) +{ + VGint old_segments = p->num_segments; + VGint num_new_coords = num_elements_for_segments(pathSegments, numSegments); + array_append_data(p->segments, pathSegments, numSegments); + array_append_data(p->control_points, pathData, num_new_coords); + + p->num_segments += numSegments; + if (!floatsEqual(p->scale, 1.f) || !floatsEqual(p->bias, 0.f)) { + VGubyte *coords = (VGubyte*)p->control_points->data; + coords_adjust_by_scale_bias(p, + coords + old_segments * p->control_points->datatype_size, + num_new_coords, + p->scale, p->bias, p->datatype); + } + p->dirty = VG_TRUE; + p->dirty_stroke = VG_TRUE; +} + +VGint path_num_segments(struct path *p) +{ + return p->num_segments; +} + +static INLINE void map_if_relative(VGfloat ox, VGfloat oy, + VGboolean relative, + VGfloat *x, VGfloat *y) +{ + if (relative) { + if (x) + *x += ox; + if (y) + *y += oy; + } +} + +static INLINE void close_polygon(struct polygon *current, + VGfloat sx, VGfloat sy, + VGfloat ox, VGfloat oy, + struct matrix *matrix) +{ + if (!floatsEqual(sx, ox) || + !floatsEqual(sy, oy)) { + VGfloat x0 = sx; + VGfloat y0 = sy; + matrix_map_point(matrix, x0, y0, &x0, &y0); + polygon_vertex_append(current, x0, y0); + } +} + +static void convert_path(struct path *p, + VGPathDatatype to, + void *dst, + VGint num_coords) +{ + VGfloat data[8]; + void *coords = (VGfloat *)p->control_points->data; + VGubyte *common_data = (VGubyte *)dst; + VGint size_dst = size_for_datatype(to); + VGint i; + + for (i = 0; i < num_coords; ++i) { + data_at(&coords, p, 0, 1, data); + vg_float_to_datatype(to, common_data, data, 1); + common_data += size_dst; + } +} + + +static void polygon_array_calculate_bounds( struct polygon_array *polyarray ) +{ + struct array *polys = polyarray->array; + VGfloat min_x, max_x; + VGfloat min_y, max_y; + VGfloat bounds[4]; + unsigned i; + + assert(polys); + assert(polys->num_elements); + polygon_bounding_rect((((struct polygon**)polys->data)[0]), bounds); + min_x = bounds[0]; + min_y = bounds[1]; + max_x = bounds[0] + bounds[2]; + max_y = bounds[1] + bounds[3]; + for (i = 1; i < polys->num_elements; ++i) { + struct polygon *p = (((struct polygon**)polys->data)[i]); + polygon_bounding_rect(p, bounds); + min_x = MIN2(min_x, bounds[0]); + min_y = MIN2(min_y, bounds[1]); + max_x = MAX2(max_x, bounds[0] + bounds[2]); + max_y = MAX2(max_y, bounds[1] + bounds[3]); + } + + polyarray->min_x = min_x; + polyarray->min_y = min_y; + polyarray->max_x = max_x; + polyarray->max_y = max_y; +} + + +static struct polygon_array * path_get_fill_polygons(struct path *p, struct matrix *matrix) +{ + VGint i; + struct polygon *current = 0; + VGfloat sx, sy, px, py, ox, oy; + VGfloat x0, y0, x1, y1, x2, y2, x3, y3; + VGfloat data[8]; + void *coords = (VGfloat *)p->control_points->data; + struct array *array; + + if (p->fill_polys.polygon_array.array) + { + if (memcmp( &p->fill_polys.matrix, + matrix, + sizeof *matrix ) == 0 && p->dirty == VG_FALSE) + { + return &p->fill_polys.polygon_array; + } + else { + array_destroy( p->fill_polys.polygon_array.array ); + p->fill_polys.polygon_array.array = NULL; + } + } + + array = array_create(sizeof(struct array*)); + + sx = sy = px = py = ox = oy = 0.f; + + current = polygon_create(32); + + for (i = 0; i < p->num_segments; ++i) { + VGubyte segment = ((VGubyte*)(p->segments->data))[i]; + VGint command = SEGMENT_COMMAND(segment); + VGboolean relative = SEGMENT_ABS_REL(segment); + + switch(command) { + case VG_CLOSE_PATH: + close_polygon(current, sx, sy, ox, oy, matrix); + ox = sx; + oy = sy; + break; + case VG_MOVE_TO: + if (current && polygon_vertex_count(current) > 0) { + /* add polygon */ + close_polygon(current, sx, sy, ox, oy, matrix); + array_append_data(array, ¤t, 1); + current = polygon_create(32); + } + data_at(&coords, p, 0, 2, data); + x0 = data[0]; + y0 = data[1]; + map_if_relative(ox, oy, relative, &x0, &y0); + sx = x0; + sy = y0; + ox = x0; + oy = y0; + px = x0; + py = y0; + matrix_map_point(matrix, x0, y0, &x0, &y0); + polygon_vertex_append(current, x0, y0); + break; + case VG_LINE_TO: + data_at(&coords, p, 0, 2, data); + x0 = data[0]; + y0 = data[1]; + map_if_relative(ox, oy, relative, &x0, &y0); + ox = x0; + oy = y0; + px = x0; + py = y0; + matrix_map_point(matrix, x0, y0, &x0, &y0); + polygon_vertex_append(current, x0, y0); + break; + case VG_HLINE_TO: + data_at(&coords, p, 0, 1, data); + x0 = data[0]; + y0 = oy; + map_if_relative(ox, oy, relative, &x0, 0); + ox = x0; + px = x0; + py = y0; + matrix_map_point(matrix, x0, y0, &x0, &y0); + polygon_vertex_append(current, x0, y0); + break; + case VG_VLINE_TO: + data_at(&coords, p, 0, 1, data); + x0 = ox; + y0 = data[0]; + map_if_relative(ox, oy, relative, 0, &y0); + oy = y0; + px = x0; + py = y0; + matrix_map_point(matrix, x0, y0, &x0, &y0); + polygon_vertex_append(current, x0, y0); + break; + case VG_CUBIC_TO: { + struct bezier bezier; + data_at(&coords, p, 0, 6, data); + x0 = ox; + y0 = oy; + x1 = data[0]; + y1 = data[1]; + x2 = data[2]; + y2 = data[3]; + x3 = data[4]; + y3 = data[5]; + map_if_relative(ox, oy, relative, &x1, &y1); + map_if_relative(ox, oy, relative, &x2, &y2); + map_if_relative(ox, oy, relative, &x3, &y3); + ox = x3; + oy = y3; + px = x2; + py = y2; + assert(matrix_is_affine(matrix)); + matrix_map_point(matrix, x0, y0, &x0, &y0); + matrix_map_point(matrix, x1, y1, &x1, &y1); + matrix_map_point(matrix, x2, y2, &x2, &y2); + matrix_map_point(matrix, x3, y3, &x3, &y3); + bezier_init(&bezier, x0, y0, x1, y1, + x2, y2, x3, y3); + bezier_add_to_polygon(&bezier, current); + } + break; + case VG_QUAD_TO: { + struct bezier bezier; + data_at(&coords, p, 0, 4, data); + x0 = ox; + y0 = oy; + x1 = data[0]; + y1 = data[1]; + x3 = data[2]; + y3 = data[3]; + map_if_relative(ox, oy, relative, &x1, &y1); + map_if_relative(ox, oy, relative, &x3, &y3); + px = x1; + py = y1; + { /* form a cubic out of it */ + x2 = (x3 + 2*x1) / 3.f; + y2 = (y3 + 2*y1) / 3.f; + x1 = (x0 + 2*x1) / 3.f; + y1 = (y0 + 2*y1) / 3.f; + } + ox = x3; + oy = y3; + assert(matrix_is_affine(matrix)); + matrix_map_point(matrix, x0, y0, &x0, &y0); + matrix_map_point(matrix, x1, y1, &x1, &y1); + matrix_map_point(matrix, x2, y2, &x2, &y2); + matrix_map_point(matrix, x3, y3, &x3, &y3); + bezier_init(&bezier, x0, y0, x1, y1, + x2, y2, x3, y3); + bezier_add_to_polygon(&bezier, current); + } + break; + case VG_SQUAD_TO: { + struct bezier bezier; + data_at(&coords, p, 0, 2, data); + x0 = ox; + y0 = oy; + x1 = 2*ox-px; + y1 = 2*oy-py; + x3 = data[0]; + y3 = data[1]; + map_if_relative(ox, oy, relative, &x3, &y3); + px = x1; + py = y1; + { /* form a cubic out of it */ + x2 = (x3 + 2*x1) / 3.f; + y2 = (y3 + 2*y1) / 3.f; + x1 = (x0 + 2*x1) / 3.f; + y1 = (y0 + 2*y1) / 3.f; + } + ox = x3; + oy = y3; + assert(matrix_is_affine(matrix)); + matrix_map_point(matrix, x0, y0, &x0, &y0); + matrix_map_point(matrix, x1, y1, &x1, &y1); + matrix_map_point(matrix, x2, y2, &x2, &y2); + matrix_map_point(matrix, x3, y3, &x3, &y3); + bezier_init(&bezier, x0, y0, x1, y1, + x2, y2, x3, y3); + bezier_add_to_polygon(&bezier, current); + } + break; + case VG_SCUBIC_TO: { + struct bezier bezier; + data_at(&coords, p, 0, 4, data); + x0 = ox; + y0 = oy; + x1 = 2*ox-px; + y1 = 2*oy-py; + x2 = data[0]; + y2 = data[1]; + x3 = data[2]; + y3 = data[3]; + map_if_relative(ox, oy, relative, &x2, &y2); + map_if_relative(ox, oy, relative, &x3, &y3); + ox = x3; + oy = y3; + px = x2; + py = y2; + assert(matrix_is_affine(matrix)); + matrix_map_point(matrix, x0, y0, &x0, &y0); + matrix_map_point(matrix, x1, y1, &x1, &y1); + matrix_map_point(matrix, x2, y2, &x2, &y2); + matrix_map_point(matrix, x3, y3, &x3, &y3); + bezier_init(&bezier, x0, y0, x1, y1, + x2, y2, x3, y3); + bezier_add_to_polygon(&bezier, current); + } + break; + case VG_SCCWARC_TO: + case VG_SCWARC_TO: + case VG_LCCWARC_TO: + case VG_LCWARC_TO: { + VGfloat rh, rv, rot; + struct arc arc; + + data_at(&coords, p, 0, 5, data); + x0 = ox; + y0 = oy; + rh = data[0]; + rv = data[1]; + rot = data[2]; + x1 = data[3]; + y1 = data[4]; + map_if_relative(ox, oy, relative, &x1, &y1); +#if 0 + debug_printf("------- ARC (%f, %f), (%f, %f) %f, %f, %f\n", + x0, y0, x1, y1, rh, rv, rot); +#endif + arc_init(&arc, command, x0, y0, x1, y1, + rh, rv, rot); + arc_add_to_polygon(&arc, current, + matrix); + ox = x1; + oy = y1; + px = x1; + py = y1; + } + break; + default: + abort(); + assert(!"Unknown segment!"); + } + } + if (current) { + if (polygon_vertex_count(current) > 0) { + close_polygon(current, sx, sy, ox, oy, matrix); + array_append_data(array, ¤t, 1); + } else + polygon_destroy(current); + } + + p->fill_polys.polygon_array.array = array; + p->fill_polys.matrix = *matrix; + + polygon_array_calculate_bounds( &p->fill_polys.polygon_array ); + + p->dirty = VG_FALSE; + + return &p->fill_polys.polygon_array; +} + +VGbyte path_datatype_size(struct path *p) +{ + return size_for_datatype(p->datatype); +} + +VGPathDatatype path_datatype(struct path *p) +{ + return p->datatype; +} + +VGfloat path_scale(struct path *p) +{ + return p->scale; +} + +VGfloat path_bias(struct path *p) +{ + return p->bias; +} + +VGint path_num_coords(struct path *p) +{ + return num_elements_for_segments((VGubyte*)p->segments->data, + p->num_segments); +} + +void path_modify_coords(struct path *p, + VGint startIndex, + VGint numSegments, + const void * pathData) +{ + VGubyte *segments = (VGubyte*)(p->segments->data); + VGint count = num_elements_for_segments(&segments[startIndex], numSegments); + VGint start_cp = num_elements_for_segments(segments, startIndex); + + array_change_data(p->control_points, pathData, start_cp, count); + coords_adjust_by_scale_bias(p, + ((VGubyte*)p->control_points->data) + + (startIndex * p->control_points->datatype_size), + path_num_coords(p), + p->scale, p->bias, p->datatype); + p->dirty = VG_TRUE; + p->dirty_stroke = VG_TRUE; +} + +void path_for_each_segment(struct path *path, + path_for_each_cb cb, + void *user_data) +{ + VGint i; + struct path_for_each_data p; + VGfloat data[8]; + void *coords = (VGfloat *)path->control_points->data; + + p.coords = data; + p.sx = p.sy = p.px = p.py = p.ox = p.oy = 0.f; + p.user_data = user_data; + + for (i = 0; i < path->num_segments; ++i) { + VGint command; + VGboolean relative; + + p.segment = ((VGubyte*)(path->segments->data))[i]; + command = SEGMENT_COMMAND(p.segment); + relative = SEGMENT_ABS_REL(p.segment); + + switch(command) { + case VG_CLOSE_PATH: + cb(path, &p); + break; + case VG_MOVE_TO: + data_at(&coords, path, 0, 2, data); + map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]); + cb(path, &p); + p.sx = data[0]; + p.sy = data[1]; + p.ox = data[0]; + p.oy = data[1]; + p.px = data[0]; + p.py = data[1]; + break; + case VG_LINE_TO: + data_at(&coords, path, 0, 2, data); + map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]); + cb(path, &p); + p.ox = data[0]; + p.oy = data[1]; + p.px = data[0]; + p.py = data[1]; + break; + case VG_HLINE_TO: + data_at(&coords, path, 0, 1, data); + map_if_relative(p.ox, p.oy, relative, &data[0], 0); + p.segment = VG_LINE_TO; + data[1] = p.oy; + cb(path, &p); + p.ox = data[0]; + p.oy = data[1]; + p.px = data[0]; + p.py = data[1]; + break; + case VG_VLINE_TO: + data_at(&coords, path, 0, 1, data); + map_if_relative(p.ox, p.oy, relative, 0, &data[0]); + p.segment = VG_LINE_TO; + data[1] = data[0]; + data[0] = p.ox; + cb(path, &p); + p.ox = data[0]; + p.oy = data[1]; + p.px = data[0]; + p.py = data[1]; + break; + case VG_CUBIC_TO: { + data_at(&coords, path, 0, 6, data); + map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]); + map_if_relative(p.ox, p.oy, relative, &data[2], &data[3]); + map_if_relative(p.ox, p.oy, relative, &data[4], &data[5]); + cb(path, &p); + p.px = data[2]; + p.py = data[3]; + p.ox = data[4]; + p.oy = data[5]; + } + break; + case VG_QUAD_TO: { + data_at(&coords, path, 0, 4, data); + map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]); + map_if_relative(p.ox, p.oy, relative, &data[2], &data[3]); + cb(path, &p); + p.px = data[0]; + p.py = data[1]; + p.ox = data[2]; + p.oy = data[3]; + } + break; + case VG_SQUAD_TO: { + data_at(&coords, path, 0, 2, data); + map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]); + cb(path, &p); + p.px = 2*p.ox-p.px; + p.py = 2*p.oy-p.py; + p.ox = data[2]; + p.oy = data[3]; + } + break; + case VG_SCUBIC_TO: { + data_at(&coords, path, 0, 4, data); + map_if_relative(p.ox, p.oy, relative, &data[0], &data[1]); + map_if_relative(p.ox, p.oy, relative, &data[2], &data[3]); + cb(path, &p); + p.px = data[0]; + p.py = data[1]; + p.ox = data[2]; + p.oy = data[3]; + } + break; + case VG_SCCWARC_TO: + case VG_SCWARC_TO: + case VG_LCCWARC_TO: + case VG_LCWARC_TO: { + data_at(&coords, path, 0, 5, data); + map_if_relative(p.ox, p.oy, relative, &data[3], &data[4]); +#if 0 + debug_printf("------- ARC (%f, %f), (%f, %f) %f, %f, %f\n", + p.ox, p.oy, data[3], data[4], data[0], data[1], data[2]); +#endif + cb(path, &p); + p.ox = data[3]; + p.oy = data[4]; + p.px = data[3]; + p.py = data[4]; + } + break; + default: + abort(); + assert(!"Unknown segment!"); + } + } +} + +struct transform_data { + struct array *segments; + struct array *coords; + + struct matrix *matrix; + + VGPathDatatype datatype; +}; + +static VGboolean transform_cb(struct path *p, + struct path_for_each_data *pd) +{ + struct transform_data *td = (struct transform_data *)pd->user_data; + VGint num_coords = num_elements_for_segments(&pd->segment, 1); + VGubyte segment = SEGMENT_COMMAND(pd->segment);/* abs bit is 0 */ + VGfloat data[8]; + VGubyte common_data[sizeof(VGfloat)*8]; + + memcpy(data, pd->coords, sizeof(VGfloat) * num_coords); + + switch(segment) { + case VG_CLOSE_PATH: + break; + case VG_MOVE_TO: + matrix_map_point(td->matrix, + data[0], data[1], &data[0], &data[1]); + break; + case VG_LINE_TO: + matrix_map_point(td->matrix, + data[0], data[1], &data[0], &data[1]); + break; + case VG_HLINE_TO: + case VG_VLINE_TO: + assert(0); + break; + case VG_QUAD_TO: + matrix_map_point(td->matrix, + data[0], data[1], &data[0], &data[1]); + matrix_map_point(td->matrix, + data[2], data[3], &data[2], &data[3]); + break; + case VG_CUBIC_TO: + matrix_map_point(td->matrix, + data[0], data[1], &data[0], &data[1]); + matrix_map_point(td->matrix, + data[2], data[3], &data[2], &data[3]); + matrix_map_point(td->matrix, + data[4], data[5], &data[4], &data[5]); + break; + case VG_SQUAD_TO: + matrix_map_point(td->matrix, + data[0], data[1], &data[0], &data[1]); + break; + case VG_SCUBIC_TO: + matrix_map_point(td->matrix, + data[0], data[1], &data[0], &data[1]); + matrix_map_point(td->matrix, + data[2], data[3], &data[2], &data[3]); + break; + case VG_SCCWARC_TO: + case VG_SCWARC_TO: + case VG_LCCWARC_TO: + case VG_LCWARC_TO: { + struct arc arc; + struct path *path = path_create(td->datatype, + 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL); + arc_init(&arc, segment, + pd->ox, pd->oy, data[3], data[4], + data[0], data[1], data[2]); + + arc_to_path(&arc, path, td->matrix); + + num_coords = path_num_coords(path); + + array_append_data(td->segments, path->segments->data, + path->num_segments); + array_append_data(td->coords, path->control_points->data, + num_coords); + path_destroy(path); + + return VG_TRUE; + } + break; + default: + break; + } + + vg_float_to_datatype(td->datatype, common_data, data, num_coords); + + array_append_data(td->segments, &segment, 1); + array_append_data(td->coords, common_data, num_coords); + return VG_TRUE; +} + +void path_transform(struct path *dst, struct path *src) +{ + struct transform_data data; + struct vg_context *ctx = dst->base.ctx; + + data.segments = dst->segments; + data.coords = dst->control_points; + data.matrix = &ctx->state.vg.path_user_to_surface_matrix; + data.datatype = dst->datatype; + + path_for_each_segment(src, transform_cb, (void*)&data); + + dst->num_segments = dst->segments->num_elements; + dst->dirty = VG_TRUE; + dst->dirty_stroke = VG_TRUE; +} + +void path_append_path(struct path *dst, + struct path *src) +{ + VGint num_coords = path_num_coords(src); + void *dst_data = malloc(size_for_datatype(dst->datatype) * num_coords); + array_append_data(dst->segments, + src->segments->data, + src->num_segments); + convert_path(src, dst->datatype, + dst_data, num_coords); + array_append_data(dst->control_points, + dst_data, + num_coords); + free(dst_data); + + dst->num_segments += src->num_segments; + dst->dirty = VG_TRUE; + dst->dirty_stroke = VG_TRUE; +} + +static INLINE VGboolean is_segment_arc(VGubyte segment) +{ + VGubyte scommand = SEGMENT_COMMAND(segment); + return (scommand == VG_SCCWARC_TO || + scommand == VG_SCWARC_TO || + scommand == VG_LCCWARC_TO || + scommand == VG_LCWARC_TO); +} + +struct path_iter_data { + struct path *path; + VGubyte segment; + void *coords; + VGfloat px, py, ox, oy, sx, sy; +}; +static INLINE VGubyte normalize_coords(struct path_iter_data *pd, + VGint *num_coords, + VGfloat *data) +{ + VGint command = SEGMENT_COMMAND(pd->segment); + VGboolean relative = SEGMENT_ABS_REL(pd->segment); + + switch(command) { + case VG_CLOSE_PATH: + *num_coords = 0; + pd->ox = pd->sx; + pd->oy = pd->sy; + return VG_CLOSE_PATH; + break; + case VG_MOVE_TO: + data_at(&pd->coords, pd->path, 0, 2, data); + map_if_relative(pd->ox, pd->oy, relative, &data[0], &data[1]); + pd->sx = data[0]; + pd->sy = data[1]; + pd->ox = data[0]; + pd->oy = data[1]; + pd->px = data[0]; + pd->py = data[1]; + *num_coords = 2; + return VG_MOVE_TO_ABS; + break; + case VG_LINE_TO: + data_at(&pd->coords, pd->path, 0, 2, data); + map_if_relative(pd->ox, pd->oy, relative, &data[0], &data[1]); + pd->ox = data[0]; + pd->oy = data[1]; + pd->px = data[0]; + pd->py = data[1]; + *num_coords = 2; + return VG_LINE_TO_ABS; + break; + case VG_HLINE_TO: + data_at(&pd->coords, pd->path, 0, 1, data); + map_if_relative(pd->ox, pd->oy, relative, &data[0], 0); + data[1] = pd->oy; + pd->ox = data[0]; + pd->oy = data[1]; + pd->px = data[0]; + pd->py = data[1]; + *num_coords = 2; + return VG_LINE_TO_ABS; + break; + case VG_VLINE_TO: + data_at(&pd->coords, pd->path, 0, 1, data); + map_if_relative(pd->ox, pd->oy, relative, 0, &data[0]); + data[1] = data[0]; + data[0] = pd->ox; + pd->ox = data[0]; + pd->oy = data[1]; + pd->px = data[0]; + pd->py = data[1]; + *num_coords = 2; + return VG_LINE_TO_ABS; + break; + case VG_CUBIC_TO: { + data_at(&pd->coords, pd->path, 0, 6, data); + map_if_relative(pd->ox, pd->oy, relative, &data[0], &data[1]); + map_if_relative(pd->ox, pd->oy, relative, &data[2], &data[3]); + map_if_relative(pd->ox, pd->oy, relative, &data[4], &data[5]); + pd->px = data[2]; + pd->py = data[3]; + pd->ox = data[4]; + pd->oy = data[5]; + *num_coords = 6; + return VG_CUBIC_TO_ABS; + } + break; + case VG_QUAD_TO: { + VGfloat x0, y0, x1, y1, x2, y2, x3, y3; + data_at(&pd->coords, pd->path, 0, 4, data); + x0 = pd->ox; + y0 = pd->oy; + x1 = data[0]; + y1 = data[1]; + x3 = data[2]; + y3 = data[3]; + map_if_relative(pd->ox, pd->oy, relative, &x1, &y1); + map_if_relative(pd->ox, pd->oy, relative, &x3, &y3); + pd->px = x1; + pd->py = y1; + { /* form a cubic out of it */ + x2 = (x3 + 2*x1) / 3.f; + y2 = (y3 + 2*y1) / 3.f; + x1 = (x0 + 2*x1) / 3.f; + y1 = (y0 + 2*y1) / 3.f; + } + pd->ox = x3; + pd->oy = y3; + data[0] = x1; + data[1] = y1; + data[2] = x2; + data[3] = y2; + data[4] = x3; + data[5] = y3; + *num_coords = 6; + return VG_CUBIC_TO_ABS; + } + break; + case VG_SQUAD_TO: { + VGfloat x0, y0, x1, y1, x2, y2, x3, y3; + data_at(&pd->coords, pd->path, 0, 2, data); + x0 = pd->ox; + y0 = pd->oy; + x1 = 2 * pd->ox - pd->px; + y1 = 2 * pd->oy - pd->py; + x3 = data[0]; + y3 = data[1]; + map_if_relative(pd->ox, pd->oy, relative, &x3, &y3); + pd->px = x1; + pd->py = y1; + { /* form a cubic out of it */ + x2 = (x3 + 2*x1) / 3.f; + y2 = (y3 + 2*y1) / 3.f; + x1 = (x0 + 2*x1) / 3.f; + y1 = (y0 + 2*y1) / 3.f; + } + pd->ox = x3; + pd->oy = y3; + data[0] = x1; + data[1] = y1; + data[2] = x2; + data[3] = y2; + data[4] = x3; + data[5] = y3; + *num_coords = 6; + return VG_CUBIC_TO_ABS; + } + break; + case VG_SCUBIC_TO: { + VGfloat x0, y0, x1, y1, x2, y2, x3, y3; + data_at(&pd->coords, pd->path, 0, 4, data); + x0 = pd->ox; + y0 = pd->oy; + x1 = 2*pd->ox-pd->px; + y1 = 2*pd->oy-pd->py; + x2 = data[0]; + y2 = data[1]; + x3 = data[2]; + y3 = data[3]; + map_if_relative(pd->ox, pd->oy, relative, &x2, &y2); + map_if_relative(pd->ox, pd->oy, relative, &x3, &y3); + pd->ox = x3; + pd->oy = y3; + pd->px = x2; + pd->py = y2; + data[0] = x1; + data[1] = y1; + data[2] = x2; + data[3] = y2; + data[4] = x3; + data[5] = y3; + *num_coords = 6; + return VG_CUBIC_TO_ABS; + } + break; + case VG_SCCWARC_TO: + case VG_SCWARC_TO: + case VG_LCCWARC_TO: + case VG_LCWARC_TO: { + data_at(&pd->coords, pd->path, 0, 5, data); + map_if_relative(pd->ox, pd->oy, relative, &data[3], &data[4]); + pd->ox = data[3]; + pd->oy = data[4]; + pd->px = data[3]; + pd->py = data[4]; + *num_coords = 5; + return command | VG_ABSOLUTE; + } + break; + default: + abort(); + assert(!"Unknown segment!"); + } +} + +static void linearly_interpolate(VGfloat *result, + const VGfloat *start, + const VGfloat *end, + VGfloat amount, + VGint number) +{ + VGint i; + for (i = 0; i < number; ++i) { + result[i] = start[i] + (end[i] - start[i]) * amount; + } +} + +VGboolean path_interpolate(struct path *dst, + struct path *start, struct path *end, + VGfloat amount) +{ + /* temporary path that we can discard if it will turn + * out that start is not compatible with end */ + struct path *res_path = path_create(dst->datatype, + 1.0, 0.0, + 0, 0, dst->caps); + VGint i; + VGfloat start_coords[8]; + VGfloat end_coords[8]; + VGfloat results[8]; + VGubyte common_data[sizeof(VGfloat)*8]; + struct path_iter_data start_iter, end_iter; + + memset(&start_iter, 0, sizeof(struct path_iter_data)); + memset(&end_iter, 0, sizeof(struct path_iter_data)); + + start_iter.path = start; + start_iter.coords = start->control_points->data; + end_iter.path = end; + end_iter.coords = end->control_points->data; + + for (i = 0; i < start->num_segments; ++i) { + VGubyte segment; + VGubyte ssegment, esegment; + VGint snum_coords, enum_coords; + start_iter.segment = ((VGubyte*)(start->segments->data))[i]; + end_iter.segment = ((VGubyte*)(end->segments->data))[i]; + + ssegment = normalize_coords(&start_iter, &snum_coords, + start_coords); + esegment = normalize_coords(&end_iter, &enum_coords, + end_coords); + + if (is_segment_arc(ssegment)) { + if (!is_segment_arc(esegment)) { + path_destroy(res_path); + return VG_FALSE; + } + if (amount > 0.5) + segment = esegment; + else + segment = ssegment; + } else if (is_segment_arc(esegment)) { + path_destroy(res_path); + return VG_FALSE; + } + else if (ssegment != esegment) { + path_destroy(res_path); + return VG_FALSE; + } + else + segment = ssegment; + + linearly_interpolate(results, start_coords, end_coords, + amount, snum_coords); + vg_float_to_datatype(dst->datatype, common_data, results, snum_coords); + path_append_data(res_path, 1, &segment, common_data); + } + + path_append_path(dst, res_path); + path_destroy(res_path); + + dst->dirty = VG_TRUE; + dst->dirty_stroke = VG_TRUE; + + return VG_TRUE; +} + +void path_clear(struct path *p, VGbitfield capabilities) +{ + path_set_capabilities(p, capabilities); + array_destroy(p->segments); + array_destroy(p->control_points); + p->segments = array_create(size_for_datatype(VG_PATH_DATATYPE_S_8)); + p->control_points = array_create(size_for_datatype(p->datatype)); + p->num_segments = 0; + p->dirty = VG_TRUE; + p->dirty_stroke = VG_TRUE; +} + +struct path * path_create_stroke(struct path *p, + struct matrix *matrix) +{ + VGint i; + VGfloat sx, sy, px, py, ox, oy; + VGfloat x0, y0, x1, y1, x2, y2, x3, y3; + VGfloat data[8]; + void *coords = (VGfloat *)p->control_points->data; + int dashed = (p->base.ctx->state.vg.stroke.dash_pattern_num ? 1 : 0); + struct dash_stroker stroker; + struct vg_state *vg_state = &p->base.ctx->state.vg; + + if (p->stroked.path) + { + /* ### compare the dash patterns to see if we can cache them. + * for now we simply always bail out if the path is dashed. + */ + if (memcmp( &p->stroked.matrix, + matrix, + sizeof *matrix ) == 0 && + !dashed && !p->dirty_stroke && + floatsEqual(p->stroked.stroke_width, vg_state->stroke.line_width.f) && + floatsEqual(p->stroked.miter_limit, vg_state->stroke.miter_limit.f) && + p->stroked.cap_style == vg_state->stroke.cap_style && + p->stroked.join_style == vg_state->stroke.join_style) + { + return p->stroked.path; + } + else { + path_destroy( p->stroked.path ); + p->stroked.path = NULL; + } + } + + + sx = sy = px = py = ox = oy = 0.f; + + if (dashed) + dash_stroker_init((struct stroker *)&stroker, vg_state); + else + stroker_init((struct stroker *)&stroker, vg_state); + + stroker_begin((struct stroker *)&stroker); + + for (i = 0; i < p->num_segments; ++i) { + VGubyte segment = ((VGubyte*)(p->segments->data))[i]; + VGint command = SEGMENT_COMMAND(segment); + VGboolean relative = SEGMENT_ABS_REL(segment); + + switch(command) { + case VG_CLOSE_PATH: { + VGfloat x0 = sx; + VGfloat y0 = sy; + matrix_map_point(matrix, x0, y0, &x0, &y0); + stroker_line_to((struct stroker *)&stroker, x0, y0); + } + break; + case VG_MOVE_TO: + data_at(&coords, p, 0, 2, data); + x0 = data[0]; + y0 = data[1]; + map_if_relative(ox, oy, relative, &x0, &y0); + sx = x0; + sy = y0; + ox = x0; + oy = y0; + px = x0; + py = y0; + matrix_map_point(matrix, x0, y0, &x0, &y0); + stroker_move_to((struct stroker *)&stroker, x0, y0); + break; + case VG_LINE_TO: + data_at(&coords, p, 0, 2, data); + x0 = data[0]; + y0 = data[1]; + map_if_relative(ox, oy, relative, &x0, &y0); + ox = x0; + oy = y0; + px = x0; + py = y0; + matrix_map_point(matrix, x0, y0, &x0, &y0); + stroker_line_to((struct stroker *)&stroker, x0, y0); + break; + case VG_HLINE_TO: + data_at(&coords, p, 0, 1, data); + x0 = data[0]; + y0 = oy; + map_if_relative(ox, oy, relative, &x0, 0); + ox = x0; + px = x0; + py = y0; + matrix_map_point(matrix, x0, y0, &x0, &y0); + stroker_line_to((struct stroker *)&stroker, x0, y0); + break; + case VG_VLINE_TO: + data_at(&coords, p, 0, 1, data); + x0 = ox; + y0 = data[0]; + map_if_relative(ox, oy, relative, 0, &y0); + oy = y0; + px = x0; + py = y0; + matrix_map_point(matrix, x0, y0, &x0, &y0); + stroker_line_to((struct stroker *)&stroker, x0, y0); + break; + case VG_CUBIC_TO: { + data_at(&coords, p, 0, 6, data); + x0 = ox; + y0 = oy; + x1 = data[0]; + y1 = data[1]; + x2 = data[2]; + y2 = data[3]; + x3 = data[4]; + y3 = data[5]; + map_if_relative(ox, oy, relative, &x1, &y1); + map_if_relative(ox, oy, relative, &x2, &y2); + map_if_relative(ox, oy, relative, &x3, &y3); + if (floatsEqual(x1, ox) && floatsEqual(y1, oy) && + floatsEqual(x1, x2) && floatsEqual(y1, y2) && + floatsEqual(x2, x3) && floatsEqual(y2, y3)) { + /*ignore the empty segment */ + continue; + } else if (floatsEqual(x3, ox) && floatsEqual(y3, oy)) { + /* if dup vertex, emit a line */ + ox = x3; + oy = y3; + matrix_map_point(matrix, x3, y3, &x3, &y3); + stroker_line_to((struct stroker *)&stroker, x3, y3); + continue; + } + ox = x3; + oy = y3; + px = x2; + py = y2; + assert(matrix_is_affine(matrix)); + matrix_map_point(matrix, x0, y0, &x0, &y0); + matrix_map_point(matrix, x1, y1, &x1, &y1); + matrix_map_point(matrix, x2, y2, &x2, &y2); + matrix_map_point(matrix, x3, y3, &x3, &y3); + stroker_curve_to((struct stroker *)&stroker, x1, y1, x2, y2, x3, y3); + } + break; + case VG_QUAD_TO: { + data_at(&coords, p, 0, 4, data); + x0 = ox; + y0 = oy; + x1 = data[0]; + y1 = data[1]; + x3 = data[2]; + y3 = data[3]; + map_if_relative(ox, oy, relative, &x1, &y1); + map_if_relative(ox, oy, relative, &x3, &y3); + px = x1; + py = y1; + { /* form a cubic out of it */ + x2 = (x3 + 2*x1) / 3.f; + y2 = (y3 + 2*y1) / 3.f; + x1 = (x0 + 2*x1) / 3.f; + y1 = (y0 + 2*y1) / 3.f; + } + if (floatsEqual(x1, ox) && floatsEqual(y1, oy) && + floatsEqual(x1, x2) && floatsEqual(y1, y2) && + floatsEqual(x2, x3) && floatsEqual(y2, y3)) { + /*ignore the empty segment */ + continue; + } else if (floatsEqual(x3, ox) && floatsEqual(y3, oy)) { + /* if dup vertex, emit a line */ + ox = x3; + oy = y3; + matrix_map_point(matrix, x3, y3, &x3, &y3); + stroker_line_to((struct stroker *)&stroker, x3, y3); + continue; + } + ox = x3; + oy = y3; + assert(matrix_is_affine(matrix)); + matrix_map_point(matrix, x0, y0, &x0, &y0); + matrix_map_point(matrix, x1, y1, &x1, &y1); + matrix_map_point(matrix, x2, y2, &x2, &y2); + matrix_map_point(matrix, x3, y3, &x3, &y3); + stroker_curve_to((struct stroker *)&stroker, x1, y1, x2, y2, x3, y3); + } + break; + case VG_SQUAD_TO: { + data_at(&coords, p, 0, 2, data); + x0 = ox; + y0 = oy; + x1 = 2*ox-px; + y1 = 2*oy-py; + x3 = data[0]; + y3 = data[1]; + map_if_relative(ox, oy, relative, &x3, &y3); + px = x1; + py = y1; + { /* form a cubic out of it */ + x2 = (x3 + 2*x1) / 3.f; + y2 = (y3 + 2*y1) / 3.f; + x1 = (x0 + 2*x1) / 3.f; + y1 = (y0 + 2*y1) / 3.f; + } + if (floatsEqual(x1, ox) && floatsEqual(y1, oy) && + floatsEqual(x1, x2) && floatsEqual(y1, y2) && + floatsEqual(x2, x3) && floatsEqual(y2, y3)) { + /*ignore the empty segment */ + continue; + } else if (floatsEqual(x3, ox) && floatsEqual(y3, oy)) { + /* if dup vertex, emit a line */ + ox = x3; + oy = y3; + matrix_map_point(matrix, x3, y3, &x3, &y3); + stroker_line_to((struct stroker *)&stroker, x3, y3); + continue; + } + ox = x3; + oy = y3; + assert(matrix_is_affine(matrix)); + matrix_map_point(matrix, x0, y0, &x0, &y0); + matrix_map_point(matrix, x1, y1, &x1, &y1); + matrix_map_point(matrix, x2, y2, &x2, &y2); + matrix_map_point(matrix, x3, y3, &x3, &y3); + stroker_curve_to((struct stroker *)&stroker, x1, y1, x2, y2, x3, y3); + } + break; + case VG_SCUBIC_TO: { + data_at(&coords, p, 0, 4, data); + x0 = ox; + y0 = oy; + x1 = 2*ox-px; + y1 = 2*oy-py; + x2 = data[0]; + y2 = data[1]; + x3 = data[2]; + y3 = data[3]; + map_if_relative(ox, oy, relative, &x2, &y2); + map_if_relative(ox, oy, relative, &x3, &y3); + if (floatsEqual(x1, ox) && floatsEqual(y1, oy) && + floatsEqual(x1, x2) && floatsEqual(y1, y2) && + floatsEqual(x2, x3) && floatsEqual(y2, y3)) { + /*ignore the empty segment */ + continue; + } else if (floatsEqual(x3, ox) && floatsEqual(y3, oy)) { + /* if dup vertex, emit a line */ + ox = x3; + oy = y3; + matrix_map_point(matrix, x3, y3, &x3, &y3); + stroker_line_to((struct stroker *)&stroker, x3, y3); + continue; + } + ox = x3; + oy = y3; + px = x2; + py = y2; + assert(matrix_is_affine(matrix)); + matrix_map_point(matrix, x0, y0, &x0, &y0); + matrix_map_point(matrix, x1, y1, &x1, &y1); + matrix_map_point(matrix, x2, y2, &x2, &y2); + matrix_map_point(matrix, x3, y3, &x3, &y3); + stroker_curve_to((struct stroker *)&stroker, x1, y1, x2, y2, x3, y3); + } + break; + case VG_SCCWARC_TO: + case VG_SCWARC_TO: + case VG_LCCWARC_TO: + case VG_LCWARC_TO: { + VGfloat rh, rv, rot; + struct arc arc; + + data_at(&coords, p, 0, 5, data); + x0 = ox; + y0 = oy; + rh = data[0]; + rv = data[1]; + rot = data[2]; + x1 = data[3]; + y1 = data[4]; + map_if_relative(ox, oy, relative, &x1, &y1); + if (floatsEqual(x1, ox) && floatsEqual(y1, oy)) { + /* if dup vertex, emit a line */ + ox = x1; + oy = y1; + matrix_map_point(matrix, x1, y1, &x1, &y1); + stroker_line_to((struct stroker *)&stroker, x1, y1); + continue; + } + arc_init(&arc, command, x0, y0, x1, y1, + rh, rv, rot); + arc_stroke_cb(&arc, (struct stroker *)&stroker, + matrix); + ox = x1; + oy = y1; + px = x1; + py = y1; + } + break; + default: + abort(); + assert(!"Unknown segment!"); + } + } + + stroker_end((struct stroker *)&stroker); + + if (dashed) + dash_stroker_cleanup((struct dash_stroker *)&stroker); + else + stroker_cleanup((struct stroker *)&stroker); + + p->stroked.path = stroker.base.path; + p->stroked.matrix = *matrix; + p->dirty_stroke = VG_FALSE; + p->stroked.stroke_width = vg_state->stroke.line_width.f; + p->stroked.miter_limit = vg_state->stroke.miter_limit.f; + p->stroked.cap_style = vg_state->stroke.cap_style; + p->stroked.join_style = vg_state->stroke.join_style; + + return stroker.base.path; +} + +void path_render(struct path *p, VGbitfield paintModes) +{ + struct vg_context *ctx = vg_current_context(); + struct matrix *mat = &ctx->state.vg.path_user_to_surface_matrix; + + vg_validate_state(ctx); + + shader_set_drawing_image(ctx->shader, VG_FALSE); + shader_set_image(ctx->shader, 0); +#if 0 + fprintf(stderr, "Matrix(11=%f 12=%f 13=%f 21=%f 22=%f 23=%f 31=%f 32=%f 33=%f)\n", + mat->m[0], mat->m[1], mat->m[2], + mat->m[3], mat->m[4], mat->m[5], + mat->m[6], mat->m[7], mat->m[8]); +#endif + if (paintModes & VG_FILL_PATH) { + /* First the fill */ + shader_set_paint(ctx->shader, ctx->state.vg.fill_paint); + shader_bind(ctx->shader); + path_fill(p, mat); + } + + if (paintModes & VG_STROKE_PATH){ + /* 8.7.5: "line width less than or equal to 0 prevents stroking from + * taking place."*/ + if (ctx->state.vg.stroke.line_width.f <= 0) + return; + shader_set_paint(ctx->shader, ctx->state.vg.stroke_paint); + shader_bind(ctx->shader); + path_stroke(p); + } +} + +void path_fill(struct path *p, struct matrix *mat) +{ + struct vg_context *ctx = vg_current_context(); + { + struct polygon_array *polygon_array = path_get_fill_polygons(p, mat); + struct array *polys = polygon_array->array; + + if (!polygon_array || !polys || !polys->num_elements) { + return; + } + polygon_array_fill(polygon_array, ctx); + } +} + +void path_stroke(struct path *p) +{ + struct vg_context *ctx = vg_current_context(); + struct matrix *mat = &ctx->state.vg.path_user_to_surface_matrix; + VGFillRule old_fill = ctx->state.vg.fill_rule; + struct matrix identity; + struct path *stroke; + + matrix_load_identity(&identity); + stroke = path_create_stroke(p, &identity); + if (stroke && !path_is_empty(stroke)) { + ctx->state.vg.fill_rule = VG_NON_ZERO; + + path_fill(stroke, mat); + + ctx->state.vg.fill_rule = old_fill; + } +} + +void path_move_to(struct path *p, float x, float y) +{ + VGubyte segment = VG_MOVE_TO_ABS; + VGubyte common_data[sizeof(VGfloat) * 2]; + VGfloat data[2] = {x, y}; + + vg_float_to_datatype(p->datatype, common_data, data, 2); + path_append_data(p, 1, &segment, common_data); +} + +void path_line_to(struct path *p, float x, float y) +{ + VGubyte segment = VG_LINE_TO_ABS; + VGubyte common_data[sizeof(VGfloat) * 2]; + VGfloat data[2] = {x, y}; + + vg_float_to_datatype(p->datatype, common_data, data, 2); + + path_append_data(p, 1, &segment, common_data); +} + +void path_cubic_to(struct path *p, float px1, float py1, + float px2, float py2, + float x, float y) +{ + VGubyte segment = VG_CUBIC_TO_ABS; + VGubyte common_data[sizeof(VGfloat) * 6]; + VGfloat data[6]; + + data[0] = px1; data[1] = py1; + data[2] = px2; data[3] = py2; + data[4] = x; data[5] = y; + + vg_float_to_datatype(p->datatype, common_data, data, 6); + + path_append_data(p, 1, &segment, common_data); +} + +static INLINE void line_bounds(VGfloat *line /*x1,y1,x2,y2*/, + VGfloat *bounds) +{ + bounds[0] = MIN2(line[0], line[2]); + bounds[1] = MIN2(line[1], line[3]); + bounds[2] = MAX2(line[0], line[2]) - bounds[0]; + bounds[3] = MAX2(line[1], line[3]) - bounds[1]; +} + +static INLINE void unite_bounds(VGfloat *bounds, + VGfloat *el) +{ + VGfloat cx1, cy1, cx2, cy2; + VGfloat nx1, ny1, nx2, ny2; + + cx1 = bounds[0]; + cy1 = bounds[1]; + cx2 = bounds[0] + bounds[2]; + cy2 = bounds[1] + bounds[3]; + + nx1 = el[0]; + ny1 = el[1]; + nx2 = el[0] + el[2]; + ny2 = el[1] + el[3]; + + bounds[0] = MIN2(cx1, nx1); + bounds[1] = MIN2(cy1, ny1); + bounds[2] = MAX2(cx2, nx2) - bounds[0]; + bounds[3] = MAX2(cy2, ny2) - bounds[1]; +} + +static INLINE void set_bounds(VGfloat *bounds, + VGfloat *element_bounds, + VGboolean *initialized) +{ + if (!(*initialized)) { + memcpy(bounds, element_bounds, 4 * sizeof(VGfloat)); + *initialized = VG_TRUE; + } else + unite_bounds(bounds, element_bounds); +} + +void path_bounding_rect(struct path *p, float *x, float *y, + float *w, float *h) +{ + VGint i; + VGfloat coords[8]; + struct path_iter_data iter; + VGint num_coords; + VGfloat bounds[4]; + VGfloat element_bounds[4]; + VGfloat ox, oy; + VGboolean bounds_inited = VG_FALSE; + + memset(&iter, 0, sizeof(struct path_iter_data)); + memset(&bounds, 0, sizeof(bounds)); + + if (!p->num_segments) { + bounds[2] = -1; + bounds[3] = -1; + } + + + iter.path = p; + iter.coords = p->control_points->data; + + for (i = 0; i < p->num_segments; ++i) { + VGubyte segment; + iter.segment = ((VGubyte*)(p->segments->data))[i]; + + ox = iter.ox; + oy = iter.oy; + + segment = normalize_coords(&iter, &num_coords, coords); + + switch(segment) { + case VG_CLOSE_PATH: + case VG_MOVE_TO_ABS: + break; + case VG_LINE_TO_ABS: { + VGfloat line[4] = {ox, oy, coords[0], coords[1]}; + line_bounds(line, element_bounds); + set_bounds(bounds, element_bounds, &bounds_inited); + } + break; + case VG_CUBIC_TO_ABS: { + struct bezier bezier; + bezier_init(&bezier, ox, oy, + coords[0], coords[1], + coords[2], coords[3], + coords[4], coords[5]); + bezier_exact_bounds(&bezier, element_bounds); + set_bounds(bounds, element_bounds, &bounds_inited); + } + break; + case VG_SCCWARC_TO: + case VG_SCWARC_TO: + case VG_LCCWARC_TO: + case VG_LCWARC_TO: { + struct arc arc; + struct matrix identity; + struct path *path = path_create(VG_PATH_DATATYPE_F, + 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL); + + matrix_load_identity(&identity); + arc_init(&arc, segment, + ox, oy, coords[3], coords[4], + coords[0], coords[1], coords[2]); + + arc_to_path(&arc, path, &identity); + + path_bounding_rect(path, element_bounds + 0, element_bounds + 1, + element_bounds + 2, element_bounds + 3); + set_bounds(bounds, element_bounds, &bounds_inited); + } + break; + default: + assert(0); + } + } + + *x = bounds[0]; + *y = bounds[1]; + *w = bounds[2]; + *h = bounds[3]; +} + +float path_length(struct path *p, int start_segment, int num_segments) +{ + VGint i; + VGfloat coords[8]; + struct path_iter_data iter; + VGint num_coords; + VGfloat length = 0; + VGfloat ox, oy; + VGboolean in_range = VG_FALSE; + + memset(&iter, 0, sizeof(struct path_iter_data)); + + iter.path = p; + iter.coords = p->control_points->data; + + for (i = 0; i < (start_segment + num_segments); ++i) { + VGubyte segment; + + iter.segment = ((VGubyte*)(p->segments->data))[i]; + + ox = iter.ox; + oy = iter.oy; + + segment = normalize_coords(&iter, &num_coords, coords); + + in_range = (i >= start_segment) && i <= (start_segment + num_segments); + if (!in_range) + continue; + + switch(segment) { + case VG_MOVE_TO_ABS: + break; + case VG_CLOSE_PATH: { + VGfloat line[4] = {ox, oy, iter.sx, iter.sy}; + length += line_lengthv(line); + } + break; + case VG_LINE_TO_ABS: { + VGfloat line[4] = {ox, oy, coords[0], coords[1]}; + length += line_lengthv(line); + } + break; + case VG_CUBIC_TO_ABS: { + struct bezier bezier; + bezier_init(&bezier, ox, oy, + coords[0], coords[1], + coords[2], coords[3], + coords[4], coords[5]); + length += bezier_length(&bezier, BEZIER_DEFAULT_ERROR); + } + break; + case VG_SCCWARC_TO: + case VG_SCWARC_TO: + case VG_LCCWARC_TO: + case VG_LCWARC_TO: { + struct arc arc; + struct matrix identity; + struct path *path = path_create(VG_PATH_DATATYPE_F, + 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL); + + matrix_load_identity(&identity); + arc_init(&arc, segment, + ox, oy, coords[3], coords[4], + coords[0], coords[1], coords[2]); + + arc_to_path(&arc, path, &identity); + + length += path_length(path, 0, path_num_segments(path)); + } + break; + default: + assert(0); + } + } + + return length; +} + +static INLINE VGboolean point_on_current_segment(VGfloat distance, + VGfloat length, + VGfloat segment_length) +{ + return + (((floatIsZero(distance) || distance < 0) && floatIsZero(length)) || + ((distance > length || floatsEqual(distance, length)) && + (floatsEqual(distance, length + segment_length) || + distance < (length + segment_length)))); +} + +static VGboolean path_point_segment(struct path_iter_data iter, + struct path_iter_data prev_iter, + VGfloat coords[8], + VGfloat distance, + VGfloat length, VGfloat *current_length, + VGfloat *point, VGfloat *normal) +{ + switch (iter.segment) { + case VG_MOVE_TO_ABS: + break; + case VG_CLOSE_PATH: { + VGfloat line[4] = {prev_iter.ox, prev_iter.oy, iter.sx, iter.sy}; + VGboolean on_current_segment = VG_FALSE; + *current_length = line_lengthv(line); + on_current_segment = point_on_current_segment(distance, + length, + *current_length); + if (on_current_segment) { + VGfloat at = (distance - length) / line_lengthv(line); + line_normal_vector(line, normal); + line_point_at(line, at, point); + return VG_TRUE; + } + } + break; + case VG_LINE_TO_ABS: { + VGfloat line[4] = {prev_iter.ox, prev_iter.oy, coords[0], coords[1]}; + VGboolean on_current_segment = VG_FALSE; + *current_length = line_lengthv(line); + on_current_segment = point_on_current_segment(distance, + length, + *current_length); + if (on_current_segment) { + VGfloat at = (distance - length) / line_lengthv(line); + line_normal_vector(line, normal); + line_point_at(line, at, point); + return VG_TRUE; + } + } + break; + case VG_CUBIC_TO_ABS: { + struct bezier bezier; + bezier_init(&bezier, prev_iter.ox, prev_iter.oy, + coords[0], coords[1], + coords[2], coords[3], + coords[4], coords[5]); + *current_length = bezier_length(&bezier, BEZIER_DEFAULT_ERROR); + if (point_on_current_segment(distance, length, *current_length)) { + bezier_point_at_length(&bezier, distance - length, + point, normal); + return VG_TRUE; + } + } + break; + case VG_SCCWARC_TO: + case VG_SCWARC_TO: + case VG_LCCWARC_TO: + case VG_LCWARC_TO: { + struct arc arc; + struct matrix identity; + struct path *path = path_create(VG_PATH_DATATYPE_F, + 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL); + + matrix_load_identity(&identity); + arc_init(&arc, iter.segment, + prev_iter.ox, prev_iter.oy, coords[3], coords[4], + coords[0], coords[1], coords[2]); + + arc_to_path(&arc, path, &identity); + + *current_length = path_length(path, 0, path_num_segments(path)); + if (point_on_current_segment(distance, length, *current_length)) { + path_point(path, 0, path_num_segments(path), + distance - length, point, normal); + return VG_TRUE; + } + } + break; + default: + assert(0); + } + return VG_FALSE; +} + +void path_point(struct path *p, VGint start_segment, VGint num_segments, + VGfloat distance, VGfloat *point, VGfloat *normal) +{ + VGint i; + VGfloat coords[8]; + struct path_iter_data iter, prev_iter; + VGint num_coords; + VGfloat length = 0; + VGfloat current_length = 0; + + memset(&iter, 0, sizeof(struct path_iter_data)); + memset(&prev_iter, 0, sizeof(struct path_iter_data)); + + point[0] = 0; + point[1] = 0; + + normal[0] = 0; + normal[1] = -1; + + iter.path = p; + iter.coords = p->control_points->data; + if (distance < 0) + distance = 0; + + for (i = 0; i < (start_segment + num_segments); ++i) { + VGboolean outside_range = (i < start_segment || + i >= (start_segment + num_segments)); + + prev_iter = iter; + + iter.segment = ((VGubyte*)(p->segments->data))[i]; + iter.segment = normalize_coords(&iter, &num_coords, coords); + + if (outside_range) + continue; + + if (path_point_segment(iter, prev_iter, coords, + distance, length, ¤t_length, + point, normal)) + return; + + length += current_length; + } + + /* + *OpenVG 1.0 - 8.6.11 vgPointAlongPath + * + * If distance is greater than or equal to the path length + *(i.e., the value returned by vgPathLength when called with the same + *startSegment and numSegments parameters), the visual ending point of + *the path is used. + */ + { + switch (iter.segment) { + case VG_MOVE_TO_ABS: + break; + case VG_CLOSE_PATH: { + VGfloat line[4] = {prev_iter.ox, prev_iter.oy, iter.sx, iter.sy}; + line_normal_vector(line, normal); + line_point_at(line, 1.f, point); + } + break; + case VG_LINE_TO_ABS: { + VGfloat line[4] = {prev_iter.ox, prev_iter.oy, coords[0], coords[1]}; + line_normal_vector(line, normal); + line_point_at(line, 1.f, point); + } + break; + case VG_CUBIC_TO_ABS: { + struct bezier bezier; + bezier_init(&bezier, prev_iter.ox, prev_iter.oy, + coords[0], coords[1], + coords[2], coords[3], + coords[4], coords[5]); + bezier_point_at_t(&bezier, 1.f, point, normal); + } + break; + case VG_SCCWARC_TO: + case VG_SCWARC_TO: + case VG_LCCWARC_TO: + case VG_LCWARC_TO: { + struct arc arc; + struct matrix identity; + struct path *path = path_create(VG_PATH_DATATYPE_F, + 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL); + + matrix_load_identity(&identity); + arc_init(&arc, iter.segment, + prev_iter.ox, prev_iter.oy, coords[3], coords[4], + coords[0], coords[1], coords[2]); + + arc_to_path(&arc, path, &identity); + + path_point(path, 0, path_num_segments(path), + /* to make sure we're bigger than len * 2 it */ + 2 * path_length(path, 0, path_num_segments(path)), + point, normal); + } + break; + default: + assert(0); + } + } +} + +VGboolean path_is_empty(struct path *p) +{ + return p->segments->num_elements == 0; +} diff --git a/src/gallium/state_trackers/vega/path.h b/src/gallium/state_trackers/vega/path.h new file mode 100644 index 00000000000..e34538b7368 --- /dev/null +++ b/src/gallium/state_trackers/vega/path.h @@ -0,0 +1,126 @@ +/************************************************************************** + * + * 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 _PATH_H +#define _PATH_H + +#include "VG/openvg.h" + +struct path; +struct polygon; +struct matrix; + +enum fill_rule { + ODD_EVEN_FILL, + WINDING_FILL +}; + + +struct path_for_each_data { + VGubyte segment; + /* all coords are absolute, even if segment is relative */ + const VGfloat *coords; + VGfloat sx, sy, ox, oy, px, py; + void *user_data; +}; + +typedef VGboolean (*path_for_each_cb)(struct path *p, + struct path_for_each_data *data); + + +struct path *path_create(VGPathDatatype dt, VGfloat scale, VGfloat bias, + VGint segmentCapacityHint, + VGint coordCapacityHint, + VGbitfield capabilities); +void path_destroy(struct path *p); + +VGbitfield path_capabilities(struct path *p); +void path_set_capabilities(struct path *p, VGbitfield bf); + +void path_append_data(struct path *p, + VGint numSegments, + const VGubyte * pathSegments, + const void * pathData); + +void path_append_path(struct path *dst, + struct path *src); + +VGint path_num_segments(struct path *p); + +void path_bounding_rect(struct path *p, float *x, float *y, + float *w, float *h); +float path_length(struct path *p, int start_segment, int num_segments); + +void path_set_fill_rule(enum fill_rule fill); +enum fill_rule path_fill_rule(enum fill_rule fill); + +VGboolean path_is_empty(struct path *p); + +VGbyte path_datatype_size(struct path *p); + +VGPathDatatype path_datatype(struct path *p); +VGfloat path_scale(struct path *p); +VGfloat path_bias(struct path *p); +VGint path_num_coords(struct path *p); + +void path_modify_coords(struct path *p, + VGint startIndex, + VGint numSegments, + const void * pathData); + +struct path *path_create_stroke(struct path *p, + struct matrix *m); + +void path_for_each_segment(struct path *path, + path_for_each_cb cb, + void *user_data); + +void path_transform(struct path *dst, struct path *src); +VGboolean path_interpolate(struct path *dst, + struct path *start, struct path *end, + VGfloat amount); + +void path_clear(struct path *p, VGbitfield capabilities); +void path_render(struct path *p, VGbitfield paintModes); +void path_fill(struct path *p, struct matrix *mat); +void path_stroke(struct path *p); + +void path_move_to(struct path *p, float x, float y); +void path_line_to(struct path *p, float x, float y); +void path_cubic_to(struct path *p, float px1, float py1, + float px2, float py2, + float x, float y); + +void path_point(struct path *p, VGint startSegment, VGint numSegments, + VGfloat distance, VGfloat *point, VGfloat *normal); + + + +void vg_float_to_datatype(VGPathDatatype datatype, + VGubyte *common_data, + const VGfloat *data, + VGint num_coords); +#endif diff --git a/src/gallium/state_trackers/vega/path_utils.h b/src/gallium/state_trackers/vega/path_utils.h new file mode 100644 index 00000000000..c2b3221dc53 --- /dev/null +++ b/src/gallium/state_trackers/vega/path_utils.h @@ -0,0 +1,109 @@ +/************************************************************************** + * + * 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 PATH_UTILS_H +#define PATH_UTILS_H + +#include "VG/openvg.h" + +#define SEGMENT_COMMAND(command) /* Extract segment type */ \ + ((command) & 0x1e) +#define SEGMENT_ABS_REL(command) /* Extract absolute/relative bit */ \ + ((command) & 0x1) + +static INLINE VGint size_for_datatype(VGPathDatatype datatype) +{ + switch(datatype) { + case VG_PATH_DATATYPE_S_8: + return 1; + case VG_PATH_DATATYPE_S_16: + return 2; + case VG_PATH_DATATYPE_S_32: + return 4; + case VG_PATH_DATATYPE_F: + return 4; + default: + assert(!"unknown datatype"); + } + return 0; +} + +static INLINE VGint num_elements_for_segments(const VGubyte *segments, + VGint num_segments) +{ + VGint i; + VGint count = 0; + + for (i = 0; i < num_segments; ++i) { + VGubyte segment = segments[i]; + VGint command = SEGMENT_COMMAND(segment); + switch(command) { + case VG_CLOSE_PATH: + break; + case VG_MOVE_TO: + count += 2; + break; + case VG_LINE_TO: + count += 2; + break; + case VG_HLINE_TO: + count += 1; + break; + case VG_VLINE_TO: + count += 1; + break; + case VG_QUAD_TO: + count += 4; + break; + case VG_CUBIC_TO: + count += 6; + break; + case VG_SQUAD_TO: + count += 2; + break; + case VG_SCUBIC_TO: + count += 4; + break; + case VG_SCCWARC_TO: + count += 5; + break; + case VG_SCWARC_TO: + count += 5; + break; + case VG_LCCWARC_TO: + count += 5; + break; + case VG_LCWARC_TO: + count += 5; + break; + default: + assert(!"Unknown segment!"); + } + } + return count; +} + +#endif diff --git a/src/gallium/state_trackers/vega/polygon.c b/src/gallium/state_trackers/vega/polygon.c new file mode 100644 index 00000000000..b6d282d803b --- /dev/null +++ b/src/gallium/state_trackers/vega/polygon.c @@ -0,0 +1,550 @@ +/************************************************************************** + * + * 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 "polygon.h" + +#include "matrix.h" /*for floatsEqual*/ +#include "vg_context.h" +#include "vg_state.h" +#include "paint.h" +#include "renderer.h" +#include "util_array.h" +#include "VG/openvg.h" + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" +#include "pipe/p_inlines.h" +#include "pipe/p_screen.h" + +#include "util/u_draw_quad.h" +#include "util/u_math.h" + +#include <string.h> +#include <stdlib.h> + +#define DEBUG_POLYGON 0 + +#define COMPONENTS 2 + +struct polygon +{ + VGfloat *data; + VGint size; + + VGint num_verts; + + VGboolean dirty; + struct pipe_buffer *vbuf; + struct pipe_screen *screen; +}; + +static float *ptr_to_vertex(float *data, int idx) +{ + return data + (idx * COMPONENTS); +} + +#if 0 +static void polygon_print(struct polygon *poly) +{ + int i; + float *vert; + debug_printf("Polygon %p, size = %d\n", poly, poly->num_verts); + for (i = 0; i < poly->num_verts; ++i) { + vert = ptr_to_vertex(poly->data, i); + debug_printf("%f, %f, ", vert[0], vert[1]); + } + debug_printf("\nend\n"); +} +#endif + + +struct polygon * polygon_create(int size) +{ + struct polygon *poly = (struct polygon*)malloc(sizeof(struct polygon)); + + poly->data = malloc(sizeof(float) * COMPONENTS * size); + poly->size = size; + poly->num_verts = 0; + poly->dirty = VG_TRUE; + poly->vbuf = NULL; + + return poly; +} + +struct polygon * polygon_create_from_data(float *data, int size) +{ + struct polygon *poly = polygon_create(size); + + memcpy(poly->data, data, sizeof(float) * COMPONENTS * size); + poly->num_verts = size; + poly->dirty = VG_TRUE; + poly->vbuf = NULL; + + return poly; +} + +void polygon_destroy(struct polygon *poly) +{ + if (poly->vbuf) + pipe_buffer_reference(&poly->vbuf, NULL); + + free(poly->data); + free(poly); +} + +void polygon_resize(struct polygon *poly, int new_size) +{ + float *data = (float*)malloc(sizeof(float) * COMPONENTS * new_size); + int size = MIN2(sizeof(float) * COMPONENTS * new_size, + sizeof(float) * COMPONENTS * poly->size); + memcpy(data, poly->data, size); + free(poly->data); + poly->data = data; + poly->size = new_size; + poly->dirty = VG_TRUE; +} + +int polygon_size(struct polygon *poly) +{ + return poly->size; +} + +int polygon_vertex_count(struct polygon *poly) +{ + return poly->num_verts; +} + +float * polygon_data(struct polygon *poly) +{ + return poly->data; +} + +void polygon_vertex_append(struct polygon *p, + float x, float y) +{ + float *vert; +#if DEBUG_POLYGON + debug_printf("Append vertex [%f, %f]\n", x, y); +#endif + if (p->num_verts >= p->size) { + polygon_resize(p, p->size * 2); + } + + vert = ptr_to_vertex(p->data, p->num_verts); + vert[0] = x; + vert[1] = y; + ++p->num_verts; + p->dirty = VG_TRUE; +} + +void polygon_set_vertex(struct polygon *p, int idx, + float x, float y) +{ + float *vert; + if (idx >= p->num_verts) { + /*fixme: error reporting*/ + abort(); + return; + } + + vert = ptr_to_vertex(p->data, idx); + vert[0] = x; + vert[1] = y; + p->dirty = VG_TRUE; +} + +void polygon_vertex(struct polygon *p, int idx, + float *vertex) +{ + float *vert; + if (idx >= p->num_verts) { + /*fixme: error reporting*/ + abort(); + return; + } + + vert = ptr_to_vertex(p->data, idx); + vertex[0] = vert[0]; + vertex[1] = vert[1]; +} + +void polygon_bounding_rect(struct polygon *p, + float *rect) +{ + int i; + float minx, miny, maxx, maxy; + float *vert = ptr_to_vertex(p->data, 0); + minx = vert[0]; + maxx = vert[0]; + miny = vert[1]; + maxy = vert[1]; + + for (i = 1; i < p->num_verts; ++i) { + vert = ptr_to_vertex(p->data, i); + minx = MIN2(vert[0], minx); + miny = MIN2(vert[1], miny); + + maxx = MAX2(vert[0], maxx); + maxy = MAX2(vert[1], maxy); + } + + rect[0] = minx; + rect[1] = miny; + rect[2] = maxx - minx; + rect[3] = maxy - miny; +} + +int polygon_contains_point(struct polygon *p, + float x, float y) +{ + return 0; +} + +void polygon_append_polygon(struct polygon *dst, + struct polygon *src) +{ + if (dst->num_verts + src->num_verts >= dst->size) { + polygon_resize(dst, dst->num_verts + src->num_verts * 1.5); + } + memcpy(ptr_to_vertex(dst->data, dst->num_verts), + src->data, src->num_verts * COMPONENTS * sizeof(VGfloat)); + dst->num_verts += src->num_verts; +} + +VGboolean polygon_is_closed(struct polygon *p) +{ + VGfloat start[2], end[2]; + + polygon_vertex(p, 0, start); + polygon_vertex(p, p->num_verts - 1, end); + + return floatsEqual(start[0], end[0]) && floatsEqual(start[1], end[1]); +} + +static void set_blend_for_fill(struct pipe_blend_state *blend) +{ + memset(blend, 0, sizeof(struct pipe_blend_state)); + blend->colormask = 0; /*disable colorwrites*/ + + blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend->rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; + blend->alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; +} + +static void draw_polygon(struct vg_context *ctx, + struct polygon *poly) +{ + int vert_size; + struct pipe_context *pipe; + struct pipe_vertex_buffer vbuffer; + struct pipe_vertex_element velement; + + vert_size = poly->num_verts * COMPONENTS * sizeof(float); + + /*polygon_print(poly);*/ + + pipe = ctx->pipe; + + if (poly->vbuf == NULL || poly->dirty) { + if (poly->vbuf) { + pipe_buffer_reference(&poly->vbuf, + NULL); + } + poly->screen = pipe->screen; + poly->vbuf= pipe_user_buffer_create(poly->screen, + poly->data, + vert_size); + poly->dirty = VG_FALSE; + } + + + /* tell pipe about the vertex buffer */ + memset(&vbuffer, 0, sizeof(vbuffer)); + vbuffer.buffer = poly->vbuf; + vbuffer.stride = COMPONENTS * sizeof(float); /* vertex size */ + vbuffer.buffer_offset = 0; + vbuffer.max_index = poly->num_verts - 1; + pipe->set_vertex_buffers(pipe, 1, &vbuffer); + + /* tell pipe about the vertex attributes */ + velement.src_offset = 0; + velement.vertex_buffer_index = 0; + velement.src_format = PIPE_FORMAT_R32G32_FLOAT; + velement.nr_components = COMPONENTS; + pipe->set_vertex_elements(pipe, 1, &velement); + + /* draw */ + pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_FAN, + 0, poly->num_verts); +} + +void polygon_fill(struct polygon *poly, struct vg_context *ctx) +{ + struct pipe_depth_stencil_alpha_state dsa; + struct pipe_blend_state blend; + VGfloat bounds[4]; + VGfloat min_x, min_y, max_x, max_y; + assert(poly); + polygon_bounding_rect(poly, bounds); + min_x = bounds[0]; + min_y = bounds[1]; + max_x = bounds[0] + bounds[2]; + max_y = bounds[1] + bounds[3]; + +#if DEBUG_POLYGON + debug_printf("Poly bounds are [%f, %f], [%f, %f]\n", + min_x, min_y, max_x, max_y); +#endif + + set_blend_for_fill(&blend); + + memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); + + cso_save_blend(ctx->cso_context); + cso_save_depth_stencil_alpha(ctx->cso_context); + + dsa.stencil[0].enabled = 1; + if (ctx->state.vg.fill_rule == VG_EVEN_ODD) { + dsa.stencil[0].writemask = 1; + dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT; + dsa.stencil[0].func = PIPE_FUNC_ALWAYS; + dsa.stencil[0].ref_value = 0; + dsa.stencil[0].valuemask = ~0; + + cso_set_blend(ctx->cso_context, &blend); + cso_set_depth_stencil_alpha(ctx->cso_context, &dsa); + draw_polygon(ctx, poly); + } else if (ctx->state.vg.fill_rule == VG_NON_ZERO) { + struct pipe_screen *screen = ctx->pipe->screen; + + if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) { + /* front */ + dsa.stencil[0].writemask = ~0; + dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP; + dsa.stencil[0].func = PIPE_FUNC_ALWAYS; + dsa.stencil[0].ref_value = 0; + dsa.stencil[0].valuemask = ~0; + + /* back */ + dsa.stencil[1].enabled = 1; + dsa.stencil[1].writemask = ~0; + dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP; + dsa.stencil[1].func = PIPE_FUNC_ALWAYS; + dsa.stencil[1].ref_value = 0; + dsa.stencil[1].valuemask = ~0; + + cso_set_blend(ctx->cso_context, &blend); + cso_set_depth_stencil_alpha(ctx->cso_context, &dsa); + draw_polygon(ctx, poly); + } else { + struct pipe_rasterizer_state raster; + + memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state)); + + cso_save_rasterizer(ctx->cso_context); + dsa.stencil[0].func = PIPE_FUNC_ALWAYS; + dsa.stencil[0].ref_value = 0; + dsa.stencil[0].valuemask = ~0; + + raster.cull_mode = raster.front_winding ^ PIPE_WINDING_BOTH; + dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP; + + cso_set_blend(ctx->cso_context, &blend); + cso_set_depth_stencil_alpha(ctx->cso_context, &dsa); + cso_set_rasterizer(ctx->cso_context, &raster); + draw_polygon(ctx, poly); + + raster.cull_mode = raster.front_winding; + dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP; + cso_set_depth_stencil_alpha(ctx->cso_context, &dsa); + cso_set_rasterizer(ctx->cso_context, &raster); + draw_polygon(ctx, poly); + + cso_restore_rasterizer(ctx->cso_context); + } + } + + /* restore color writes */ + cso_restore_blend(ctx->cso_context); + /* setup stencil ops */ + dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL; + dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; + dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; + dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; + dsa.stencil[0].ref_value = 0; + dsa.stencil[0].valuemask = dsa.stencil[0].writemask; + dsa.stencil[1].enabled = 0; + memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth, + sizeof(struct pipe_depth_state)); + cso_set_depth_stencil_alpha(ctx->cso_context, &dsa); + + /* render the quad to propagate the rendering from stencil */ + renderer_draw_quad(ctx->renderer, min_x, min_y, + max_x, max_y, 0.0f/*depth should be disabled*/); + + cso_restore_depth_stencil_alpha(ctx->cso_context); +} + +void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx) +{ + struct array *polys = polyarray->array; + struct pipe_depth_stencil_alpha_state dsa; + struct pipe_blend_state blend; + VGfloat min_x = polyarray->min_x; + VGfloat min_y = polyarray->min_y; + VGfloat max_x = polyarray->max_x; + VGfloat max_y = polyarray->max_y; + VGint i; + + +#if DEBUG_POLYGON + debug_printf("%s: Poly bounds are [%f, %f], [%f, %f]\n", + __FUNCTION__, + min_x, min_y, max_x, max_y); +#endif + + set_blend_for_fill(&blend); + + memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); + + cso_save_blend(ctx->cso_context); + cso_save_depth_stencil_alpha(ctx->cso_context); + + dsa.stencil[0].enabled = 1; + if (ctx->state.vg.fill_rule == VG_EVEN_ODD) { + dsa.stencil[0].writemask = 1; + dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT; + dsa.stencil[0].func = PIPE_FUNC_ALWAYS; + dsa.stencil[0].ref_value = 0; + dsa.stencil[0].valuemask = ~0; + + cso_set_blend(ctx->cso_context, &blend); + cso_set_depth_stencil_alpha(ctx->cso_context, &dsa); + for (i = 0; i < polys->num_elements; ++i) { + struct polygon *poly = (((struct polygon**)polys->data)[i]); + draw_polygon(ctx, poly); + } + } else if (ctx->state.vg.fill_rule == VG_NON_ZERO) { + struct pipe_screen *screen = ctx->pipe->screen; + + if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) { + /* front */ + dsa.stencil[0].writemask = ~0; + dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP; + dsa.stencil[0].func = PIPE_FUNC_ALWAYS; + dsa.stencil[0].ref_value = 0; + dsa.stencil[0].valuemask = ~0; + + /* back */ + dsa.stencil[1].enabled = 1; + dsa.stencil[1].writemask = ~0; + dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP; + dsa.stencil[1].func = PIPE_FUNC_ALWAYS; + dsa.stencil[1].ref_value = 0; + dsa.stencil[1].valuemask = ~0; + + cso_set_blend(ctx->cso_context, &blend); + cso_set_depth_stencil_alpha(ctx->cso_context, &dsa); + for (i = 0; i < polys->num_elements; ++i) { + struct polygon *poly = (((struct polygon**)polys->data)[i]); + draw_polygon(ctx, poly); + } + } else { + struct pipe_rasterizer_state raster; + + memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state)); + + cso_save_rasterizer(ctx->cso_context); + dsa.stencil[0].func = PIPE_FUNC_ALWAYS; + dsa.stencil[0].ref_value = 0; + dsa.stencil[0].valuemask = ~0; + + raster.cull_mode = raster.front_winding ^ PIPE_WINDING_BOTH; + dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP; + + cso_set_blend(ctx->cso_context, &blend); + cso_set_depth_stencil_alpha(ctx->cso_context, &dsa); + cso_set_rasterizer(ctx->cso_context, &raster); + for (i = 0; i < polys->num_elements; ++i) { + struct polygon *poly = (((struct polygon**)polys->data)[i]); + draw_polygon(ctx, poly); + } + + raster.cull_mode = raster.front_winding; + dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP; + cso_set_depth_stencil_alpha(ctx->cso_context, &dsa); + cso_set_rasterizer(ctx->cso_context, &raster); + for (i = 0; i < polys->num_elements; ++i) { + struct polygon *poly = (((struct polygon**)polys->data)[i]); + draw_polygon(ctx, poly); + } + + cso_restore_rasterizer(ctx->cso_context); + } + } + + /* restore color writes */ + cso_restore_blend(ctx->cso_context); + /* setup stencil ops */ + dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL; + dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; + dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; + dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; + dsa.stencil[0].ref_value = 0; + dsa.stencil[0].valuemask = dsa.stencil[0].writemask; + dsa.stencil[1].enabled = 0; + memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth, + sizeof(struct pipe_depth_state)); + cso_set_depth_stencil_alpha(ctx->cso_context, &dsa); + + /* render the quad to propagate the rendering from stencil */ + renderer_draw_quad(ctx->renderer, min_x, min_y, + max_x, max_y, 0.0f/*depth should be disabled*/); + + cso_restore_depth_stencil_alpha(ctx->cso_context); +} diff --git a/src/gallium/state_trackers/vega/polygon.h b/src/gallium/state_trackers/vega/polygon.h new file mode 100644 index 00000000000..22672b728ed --- /dev/null +++ b/src/gallium/state_trackers/vega/polygon.h @@ -0,0 +1,75 @@ +/************************************************************************** + * + * 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 POLYGON_H +#define POLYGON_H + +#include "VG/openvg.h" + +struct polygon; +struct vg_context; +struct vg_paint; +struct array; + +struct polygon *polygon_create(int size); +struct polygon *polygon_create_from_data(float *data, int size); +void polygon_destroy(struct polygon *poly); + +void polygon_resize(struct polygon *poly, int new_size); +int polygon_size(struct polygon *poly); + +int polygon_vertex_count(struct polygon *poly); +float * polygon_data(struct polygon *poly); + +void polygon_vertex_append(struct polygon *p, + float x, float y); +void polygon_append_polygon(struct polygon *dst, + struct polygon *src); +void polygon_set_vertex(struct polygon *p, int idx, + float x, float y); +void polygon_vertex(struct polygon *p, int idx, + float *vertex); + +void polygon_bounding_rect(struct polygon *p, + float *rect); +int polygon_contains_point(struct polygon *p, + float x, float y); + +VGboolean polygon_is_closed(struct polygon *p); + +void polygon_fill(struct polygon *p, struct vg_context *pipe); + +/* TODO: make a file/module around this struct + */ +struct polygon_array { + struct array *array; + VGfloat min_x, max_x; + VGfloat min_y, max_y; +}; + +void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx); + +#endif diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c new file mode 100644 index 00000000000..f7c5f2f0cdf --- /dev/null +++ b/src/gallium/state_trackers/vega/renderer.c @@ -0,0 +1,592 @@ +/************************************************************************** + * + * 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 "renderer.h" + +#include "vg_context.h" + +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "pipe/p_inlines.h" +#include "pipe/p_screen.h" +#include "pipe/p_shader_tokens.h" + +#include "util/u_draw_quad.h" +#include "util/u_simple_shaders.h" +#include "util/u_memory.h" + +#include "cso_cache/cso_context.h" + +struct renderer { + struct pipe_context *pipe; + struct vg_context *owner; + + struct cso_context *cso; + + void *fs; + + VGfloat vertices[4][2][4]; +}; + +static void setup_shaders(struct renderer *ctx) +{ + struct pipe_context *pipe = ctx->pipe; + /* fragment shader */ + ctx->fs = util_make_fragment_tex_shader(pipe); +} + +static struct pipe_buffer * +setup_vertex_data(struct renderer *ctx, + float x0, float y0, float x1, float y1, float z) +{ + ctx->vertices[0][0][0] = x0; + ctx->vertices[0][0][1] = y0; + ctx->vertices[0][0][2] = z; + ctx->vertices[0][1][0] = 0.0f; /*s*/ + ctx->vertices[0][1][1] = 0.0f; /*t*/ + + ctx->vertices[1][0][0] = x1; + ctx->vertices[1][0][1] = y0; + ctx->vertices[1][0][2] = z; + ctx->vertices[1][1][0] = 1.0f; /*s*/ + ctx->vertices[1][1][1] = 0.0f; /*t*/ + + ctx->vertices[2][0][0] = x1; + ctx->vertices[2][0][1] = y1; + ctx->vertices[2][0][2] = z; + ctx->vertices[2][1][0] = 1.0f; + ctx->vertices[2][1][1] = 1.0f; + + ctx->vertices[3][0][0] = x0; + ctx->vertices[3][0][1] = y1; + ctx->vertices[3][0][2] = z; + ctx->vertices[3][1][0] = 0.0f; + ctx->vertices[3][1][1] = 1.0f; + + return pipe_user_buffer_create( ctx->pipe->screen, + ctx->vertices, + sizeof(ctx->vertices) ); +} + +static struct pipe_buffer * +setup_vertex_data_tex(struct renderer *ctx, + float x0, float y0, float x1, float y1, + float s0, float t0, float s1, float t1, + float z) +{ + ctx->vertices[0][0][0] = x0; + ctx->vertices[0][0][1] = y0; + ctx->vertices[0][0][2] = z; + ctx->vertices[0][1][0] = s0; /*s*/ + ctx->vertices[0][1][1] = t0; /*t*/ + + ctx->vertices[1][0][0] = x1; + ctx->vertices[1][0][1] = y0; + ctx->vertices[1][0][2] = z; + ctx->vertices[1][1][0] = s1; /*s*/ + ctx->vertices[1][1][1] = t0; /*t*/ + + ctx->vertices[2][0][0] = x1; + ctx->vertices[2][0][1] = y1; + ctx->vertices[2][0][2] = z; + ctx->vertices[2][1][0] = s1; + ctx->vertices[2][1][1] = t1; + + ctx->vertices[3][0][0] = x0; + ctx->vertices[3][0][1] = y1; + ctx->vertices[3][0][2] = z; + ctx->vertices[3][1][0] = s0; + ctx->vertices[3][1][1] = t1; + + return pipe_user_buffer_create( ctx->pipe->screen, + ctx->vertices, + sizeof(ctx->vertices) ); +} + + +static struct pipe_buffer * +setup_vertex_data_qtex(struct renderer *ctx, + float x0, float y0, float x1, float y1, + float x2, float y2, float x3, float y3, + float s0, float t0, float s1, float t1, + float z) +{ + ctx->vertices[0][0][0] = x0; + ctx->vertices[0][0][1] = y0; + ctx->vertices[0][0][2] = z; + ctx->vertices[0][1][0] = s0; /*s*/ + ctx->vertices[0][1][1] = t0; /*t*/ + + ctx->vertices[1][0][0] = x1; + ctx->vertices[1][0][1] = y1; + ctx->vertices[1][0][2] = z; + ctx->vertices[1][1][0] = s1; /*s*/ + ctx->vertices[1][1][1] = t0; /*t*/ + + ctx->vertices[2][0][0] = x2; + ctx->vertices[2][0][1] = y2; + ctx->vertices[2][0][2] = z; + ctx->vertices[2][1][0] = s1; + ctx->vertices[2][1][1] = t1; + + ctx->vertices[3][0][0] = x3; + ctx->vertices[3][0][1] = y3; + ctx->vertices[3][0][2] = z; + ctx->vertices[3][1][0] = s0; + ctx->vertices[3][1][1] = t1; + + return pipe_user_buffer_create( ctx->pipe->screen, + ctx->vertices, + sizeof(ctx->vertices) ); +} + +struct renderer * renderer_create(struct vg_context *owner) +{ + VGint i; + struct renderer *renderer = CALLOC_STRUCT(renderer); + + if (!renderer) + return NULL; + + renderer->owner = owner; + renderer->pipe = owner->pipe; + renderer->cso = owner->cso_context; + + setup_shaders(renderer); + + /* init vertex data that doesn't change */ + for (i = 0; i < 4; i++) { + renderer->vertices[i][0][3] = 1.0f; /* w */ + renderer->vertices[i][1][2] = 0.0f; /* r */ + renderer->vertices[i][1][3] = 1.0f; /* q */ + } + + return renderer; +} + +void renderer_destroy(struct renderer *ctx) +{ +#if 0 + if (ctx->fs) { + cso_delete_fragment_shader(ctx->cso, ctx->fs); + ctx->fs = NULL; + } +#endif + free(ctx); +} + +void renderer_draw_quad(struct renderer *r, + VGfloat x1, VGfloat y1, + VGfloat x2, VGfloat y2, + VGfloat depth) +{ + struct pipe_buffer *buf; + + buf = setup_vertex_data(r, x1, y1, x2, y2, depth); + + if (buf) { + util_draw_vertex_buffer(r->pipe, buf, 0, + PIPE_PRIM_TRIANGLE_FAN, + 4, /* verts */ + 2); /* attribs/vert */ + + pipe_buffer_reference( &buf, + NULL ); + } +} + +void renderer_draw_texture(struct renderer *r, + struct pipe_texture *tex, + VGfloat x1offset, VGfloat y1offset, + VGfloat x2offset, VGfloat y2offset, + VGfloat x1, VGfloat y1, + VGfloat x2, VGfloat y2) +{ + struct pipe_context *pipe = r->pipe; + struct pipe_buffer *buf; + VGfloat s0, t0, s1, t1; + + assert(tex->width[0] != 0); + assert(tex->height[0] != 0); + + s0 = x1offset / tex->width[0]; + s1 = x2offset / tex->width[0]; + t0 = y1offset / tex->height[0]; + t1 = y2offset / tex->height[0]; + + cso_save_vertex_shader(r->cso); + /* shaders */ + cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner)); + + /* draw quad */ + buf = setup_vertex_data_tex(r, x1, y1, x2, y2, + s0, t0, s1, t1, 0.0f); + + if (buf) { + util_draw_vertex_buffer(pipe, buf, 0, + PIPE_PRIM_TRIANGLE_FAN, + 4, /* verts */ + 2); /* attribs/vert */ + + pipe_buffer_reference( &buf, + NULL ); + } + + cso_restore_vertex_shader(r->cso); +} + +void renderer_copy_texture(struct renderer *ctx, + struct pipe_texture *src, + VGfloat sx1, VGfloat sy1, + VGfloat sx2, VGfloat sy2, + struct pipe_texture *dst, + VGfloat dx1, VGfloat dy1, + VGfloat dx2, VGfloat dy2) +{ + struct pipe_context *pipe = ctx->pipe; + struct pipe_screen *screen = pipe->screen; + struct pipe_buffer *buf; + struct pipe_surface *dst_surf = screen->get_tex_surface( + screen, dst, 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_WRITE); + struct pipe_framebuffer_state fb; + float s0, t0, s1, t1; + + assert(src->width[0] != 0); + assert(src->height[0] != 0); + assert(dst->width[0] != 0); + assert(dst->height[0] != 0); + +#if 0 + debug_printf("copy texture [%f, %f, %f, %f], [%f, %f, %f, %f]\n", + sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2); +#endif + +#if 1 + s0 = sx1 / src->width[0]; + s1 = sx2 / src->width[0]; + t0 = sy1 / src->height[0]; + t1 = sy2 / src->height[0]; +#else + s0 = 0; + s1 = 1; + t0 = 0; + t1 = 1; +#endif + + assert(screen->is_format_supported(screen, dst_surf->format, PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); + + /* save state (restored below) */ + cso_save_blend(ctx->cso); + cso_save_samplers(ctx->cso); + cso_save_sampler_textures(ctx->cso); + cso_save_framebuffer(ctx->cso); + cso_save_fragment_shader(ctx->cso); + cso_save_vertex_shader(ctx->cso); + + cso_save_viewport(ctx->cso); + + + /* set misc state we care about */ + { + struct pipe_blend_state blend; + memset(&blend, 0, sizeof(blend)); + blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.colormask = PIPE_MASK_RGBA; + cso_set_blend(ctx->cso, &blend); + } + + /* sampler */ + { + struct pipe_sampler_state sampler; + memset(&sampler, 0, sizeof(sampler)); + sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler.normalized_coords = 1; + cso_single_sampler(ctx->cso, 0, &sampler); + cso_single_sampler_done(ctx->cso); + } + + vg_set_viewport(ctx->owner, VEGA_Y0_TOP); + + /* texture */ + cso_set_sampler_textures(ctx->cso, 1, &src); + + /* shaders */ + cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner)); + cso_set_fragment_shader_handle(ctx->cso, ctx->fs); + + /* drawing dest */ + memset(&fb, 0, sizeof(fb)); + fb.width = dst_surf->width; + fb.height = dst_surf->height; + fb.nr_cbufs = 1; + fb.cbufs[0] = dst_surf; + { + VGint i; + for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) + fb.cbufs[i] = 0; + } + cso_set_framebuffer(ctx->cso, &fb); + + /* draw quad */ + buf = setup_vertex_data_tex(ctx, + dx1, dy1, + dx2, dy2, + s0, t0, s1, t1, + 0.0f); + + if (buf) { + util_draw_vertex_buffer(ctx->pipe, buf, 0, + PIPE_PRIM_TRIANGLE_FAN, + 4, /* verts */ + 2); /* attribs/vert */ + + pipe_buffer_reference( &buf, + NULL ); + } + + /* restore state we changed */ + cso_restore_blend(ctx->cso); + cso_restore_samplers(ctx->cso); + cso_restore_sampler_textures(ctx->cso); + cso_restore_framebuffer(ctx->cso); + cso_restore_vertex_shader(ctx->cso); + cso_restore_fragment_shader(ctx->cso); + cso_restore_viewport(ctx->cso); + + pipe_surface_reference(&dst_surf, NULL); +} + +void renderer_copy_surface(struct renderer *ctx, + struct pipe_surface *src, + int srcX0, int srcY0, + int srcX1, int srcY1, + struct pipe_surface *dst, + int dstX0, int dstY0, + int dstX1, int dstY1, + float z, unsigned filter) +{ + struct pipe_context *pipe = ctx->pipe; + struct pipe_screen *screen = pipe->screen; + struct pipe_buffer *buf; + struct pipe_texture texTemp, *tex; + struct pipe_surface *texSurf; + struct pipe_framebuffer_state fb; + struct st_framebuffer *stfb = ctx->owner->draw_buffer; + const int srcW = abs(srcX1 - srcX0); + const int srcH = abs(srcY1 - srcY0); + const int srcLeft = MIN2(srcX0, srcX1); + const int srcTop = MIN2(srcY0, srcY1); + + assert(filter == PIPE_TEX_MIPFILTER_NEAREST || + filter == PIPE_TEX_MIPFILTER_LINEAR); + + if (srcLeft != srcX0) { + /* left-right flip */ + int tmp = dstX0; + dstX0 = dstX1; + dstX1 = tmp; + } + + if (srcTop != srcY0) { + /* up-down flip */ + int tmp = dstY0; + dstY0 = dstY1; + dstY1 = tmp; + } + + assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_SAMPLER, 0)); + assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_SAMPLER, 0)); + assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, + PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); + + /* + * XXX for now we're always creating a temporary texture. + * Strictly speaking that's not always needed. + */ + + /* create temp texture */ + memset(&texTemp, 0, sizeof(texTemp)); + texTemp.target = PIPE_TEXTURE_2D; + texTemp.format = src->format; + texTemp.last_level = 0; + texTemp.width[0] = srcW; + texTemp.height[0] = srcH; + texTemp.depth[0] = 1; + pf_get_block(src->format, &texTemp.block); + + tex = screen->texture_create(screen, &texTemp); + if (!tex) + return; + + texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_WRITE); + + /* load temp texture */ + pipe->surface_copy(pipe, + texSurf, 0, 0, /* dest */ + src, srcLeft, srcTop, /* src */ + srcW, srcH); /* size */ + + /* free the surface, update the texture if necessary.*/ + screen->tex_surface_destroy(texSurf); + + /* save state (restored below) */ + cso_save_blend(ctx->cso); + cso_save_samplers(ctx->cso); + cso_save_sampler_textures(ctx->cso); + cso_save_framebuffer(ctx->cso); + cso_save_fragment_shader(ctx->cso); + cso_save_vertex_shader(ctx->cso); + cso_save_viewport(ctx->cso); + + /* set misc state we care about */ + { + struct pipe_blend_state blend; + memset(&blend, 0, sizeof(blend)); + blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.colormask = PIPE_MASK_RGBA; + cso_set_blend(ctx->cso, &blend); + } + + vg_set_viewport(ctx->owner, VEGA_Y0_TOP); + + /* sampler */ + { + struct pipe_sampler_state sampler; + memset(&sampler, 0, sizeof(sampler)); + sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; + sampler.normalized_coords = 1; + cso_single_sampler(ctx->cso, 0, &sampler); + cso_single_sampler_done(ctx->cso); + } + + /* texture */ + cso_set_sampler_textures(ctx->cso, 1, &tex); + + /* shaders */ + cso_set_fragment_shader_handle(ctx->cso, ctx->fs); + cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner)); + + /* drawing dest */ + if (stfb->strb->surface != dst) { + memset(&fb, 0, sizeof(fb)); + fb.width = dst->width; + fb.height = dst->height; + fb.nr_cbufs = 1; + fb.cbufs[0] = dst; + fb.zsbuf = stfb->dsrb->surface; + cso_set_framebuffer(ctx->cso, &fb); + } + + /* draw quad */ + buf = setup_vertex_data(ctx, + (float) dstX0, (float) dstY0, + (float) dstX1, (float) dstY1, z); + + if (buf) { + util_draw_vertex_buffer(ctx->pipe, buf, 0, + PIPE_PRIM_TRIANGLE_FAN, + 4, /* verts */ + 2); /* attribs/vert */ + + pipe_buffer_reference( &buf, + NULL ); + } + + + /* restore state we changed */ + cso_restore_blend(ctx->cso); + cso_restore_samplers(ctx->cso); + cso_restore_sampler_textures(ctx->cso); + cso_restore_framebuffer(ctx->cso); + cso_restore_fragment_shader(ctx->cso); + cso_restore_vertex_shader(ctx->cso); + cso_restore_viewport(ctx->cso); + + pipe_texture_reference(&tex, NULL); +} + +void renderer_texture_quad(struct renderer *r, + struct pipe_texture *tex, + VGfloat x1offset, VGfloat y1offset, + VGfloat x2offset, VGfloat y2offset, + VGfloat x1, VGfloat y1, + VGfloat x2, VGfloat y2, + VGfloat x3, VGfloat y3, + VGfloat x4, VGfloat y4) +{ + struct pipe_context *pipe = r->pipe; + struct pipe_buffer *buf; + VGfloat s0, t0, s1, t1; + + assert(tex->width[0] != 0); + assert(tex->height[0] != 0); + + s0 = x1offset / tex->width[0]; + s1 = x2offset / tex->width[0]; + t0 = y1offset / tex->height[0]; + t1 = y2offset / tex->height[0]; + + cso_save_vertex_shader(r->cso); + /* shaders */ + cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner)); + + /* draw quad */ + buf = setup_vertex_data_qtex(r, x1, y1, x2, y2, x3, y3, x4, y4, + s0, t0, s1, t1, 0.0f); + + if (buf) { + util_draw_vertex_buffer(pipe, buf, 0, + PIPE_PRIM_TRIANGLE_FAN, + 4, /* verts */ + 2); /* attribs/vert */ + + pipe_buffer_reference(&buf, + NULL); + } + + cso_restore_vertex_shader(r->cso); +} diff --git a/src/gallium/state_trackers/vega/renderer.h b/src/gallium/state_trackers/vega/renderer.h new file mode 100644 index 00000000000..990cd32c313 --- /dev/null +++ b/src/gallium/state_trackers/vega/renderer.h @@ -0,0 +1,76 @@ +/************************************************************************** + * + * 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 RENDERER_H +#define RENDERER_H + +#include "VG/openvg.h" + +struct renderer; + +struct vg_context; +struct pipe_texture; +struct pipe_surface; + +struct renderer *renderer_create(struct vg_context *owner); +void renderer_destroy(struct renderer *); + +void renderer_draw_quad(struct renderer *, + VGfloat x1, VGfloat y1, + VGfloat x2, VGfloat y2, + VGfloat depth); +void renderer_draw_texture(struct renderer *, + struct pipe_texture *texture, + VGfloat x1offset, VGfloat y1offset, + VGfloat x2offset, VGfloat y2offset, + VGfloat x1, VGfloat y1, + VGfloat x2, VGfloat y2); +void renderer_texture_quad(struct renderer *, + struct pipe_texture *texture, + VGfloat x1offset, VGfloat y1offset, + VGfloat x2offset, VGfloat y2offset, + VGfloat x1, VGfloat y1, + VGfloat x2, VGfloat y2, + VGfloat x3, VGfloat y3, + VGfloat x4, VGfloat y4); +void renderer_copy_texture(struct renderer *r, + struct pipe_texture *src, + VGfloat sx1, VGfloat sy1, + VGfloat sx2, VGfloat sy2, + struct pipe_texture *dst, + VGfloat dx1, VGfloat dy1, + VGfloat dx2, VGfloat dy2); +void renderer_copy_surface(struct renderer *r, + struct pipe_surface *src, + int sx1, int sy1, + int sx2, int sy2, + struct pipe_surface *dst, + int dx1, int dy1, + int dx2, int dy2, + float z, unsigned filter); + + +#endif diff --git a/src/gallium/state_trackers/vega/shader.c b/src/gallium/state_trackers/vega/shader.c new file mode 100644 index 00000000000..d9074a377b3 --- /dev/null +++ b/src/gallium/state_trackers/vega/shader.c @@ -0,0 +1,310 @@ +/************************************************************************** + * + * 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 "shader.h" + +#include "vg_context.h" +#include "shaders_cache.h" +#include "paint.h" +#include "mask.h" +#include "image.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "pipe/p_state.h" +#include "pipe/p_inlines.h" +#include "util/u_memory.h" + +#define MAX_CONSTANTS 20 + +struct shader { + struct vg_context *context; + + VGboolean masking; + struct vg_paint *paint; + struct vg_image *image; + + VGboolean drawing_image; + VGImageMode image_mode; + + float constants[MAX_CONSTANTS]; + struct pipe_constant_buffer cbuf; + struct pipe_shader_state fs_state; + void *fs; +}; + +struct shader * shader_create(struct vg_context *ctx) +{ + struct shader *shader = 0; + + shader = CALLOC_STRUCT(shader); + shader->context = ctx; + + return shader; +} + +void shader_destroy(struct shader *shader) +{ + free(shader); +} + +void shader_set_masking(struct shader *shader, VGboolean set) +{ + shader->masking = set; +} + +VGboolean shader_is_masking(struct shader *shader) +{ + return shader->masking; +} + +void shader_set_paint(struct shader *shader, struct vg_paint *paint) +{ + shader->paint = paint; +} + +struct vg_paint * shader_paint(struct shader *shader) +{ + return shader->paint; +} + + +static void setup_constant_buffer(struct shader *shader) +{ + struct vg_context *ctx = shader->context; + struct pipe_context *pipe = shader->context->pipe; + struct pipe_constant_buffer *cbuf = &shader->cbuf; + VGint param_bytes = paint_constant_buffer_size(shader->paint); + float temp_buf[MAX_CONSTANTS]; + + assert(param_bytes <= sizeof(temp_buf)); + paint_fill_constant_buffer(shader->paint, temp_buf); + + if (cbuf->buffer == NULL || + memcmp(temp_buf, shader->constants, param_bytes) != 0) + { + pipe_buffer_reference(&cbuf->buffer, NULL); + + memcpy(shader->constants, temp_buf, param_bytes); + cbuf->buffer = pipe_user_buffer_create(pipe->screen, + &shader->constants, + sizeof(shader->constants)); + } + + ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf); +} + +static VGint blend_bind_samplers(struct vg_context *ctx, + struct pipe_sampler_state **samplers, + struct pipe_texture **textures) +{ + VGBlendMode bmode = ctx->state.vg.blend_mode; + + if (bmode == VG_BLEND_MULTIPLY || + bmode == VG_BLEND_SCREEN || + bmode == VG_BLEND_DARKEN || + bmode == VG_BLEND_LIGHTEN) { + struct st_framebuffer *stfb = ctx->draw_buffer; + + vg_prepare_blend_surface(ctx); + + samplers[2] = &ctx->blend_sampler; + textures[2] = stfb->blend_texture; + + if (!samplers[0] || !textures[0]) { + samplers[1] = samplers[2]; + textures[1] = textures[2]; + } + if (!samplers[1] || !textures[1]) { + samplers[1] = samplers[0]; + textures[1] = textures[0]; + } + + return 1; + } + return 0; +} + +static void setup_samplers(struct shader *shader) +{ + struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; + struct pipe_texture *textures[PIPE_MAX_SAMPLERS]; + struct vg_context *ctx = shader->context; + /* a little wonky: we use the num as a boolean that just says + * whether any sampler/textures have been set. the actual numbering + * for samplers is always the same: + * 0 - paint sampler/texture for gradient/pattern + * 1 - mask sampler/texture + * 2 - blend sampler/texture + * 3 - image sampler/texture + * */ + VGint num = 0; + + samplers[0] = NULL; + samplers[1] = NULL; + samplers[2] = NULL; + samplers[3] = NULL; + textures[0] = NULL; + textures[1] = NULL; + textures[2] = NULL; + textures[3] = NULL; + + num += paint_bind_samplers(shader->paint, samplers, textures); + num += mask_bind_samplers(samplers, textures); + num += blend_bind_samplers(ctx, samplers, textures); + if (shader->drawing_image && shader->image) + num += image_bind_samplers(shader->image, samplers, textures); + + if (num) { + cso_set_samplers(ctx->cso_context, 4, (const struct pipe_sampler_state **)samplers); + cso_set_sampler_textures(ctx->cso_context, 4, textures); + } +} + +static INLINE VGboolean is_format_bw(struct shader *shader) +{ +#if 0 + struct vg_context *ctx = shader->context; + struct st_framebuffer *stfb = ctx->draw_buffer; +#endif + + if (shader->drawing_image && shader->image) { + if (shader->image->format == VG_BW_1) + return VG_TRUE; + } + + return VG_FALSE; +} + +static void setup_shader_program(struct shader *shader) +{ + struct vg_context *ctx = shader->context; + VGint shader_id = 0; + VGBlendMode blend_mode = ctx->state.vg.blend_mode; + VGboolean black_white = is_format_bw(shader); + + /* 1st stage: fill */ + if (!shader->drawing_image || + (shader->image_mode == VG_DRAW_IMAGE_MULTIPLY || shader->image_mode == VG_DRAW_IMAGE_STENCIL)) { + switch(paint_type(shader->paint)) { + case VG_PAINT_TYPE_COLOR: + shader_id |= VEGA_SOLID_FILL_SHADER; + break; + case VG_PAINT_TYPE_LINEAR_GRADIENT: + shader_id |= VEGA_LINEAR_GRADIENT_SHADER; + break; + case VG_PAINT_TYPE_RADIAL_GRADIENT: + shader_id |= VEGA_RADIAL_GRADIENT_SHADER; + break; + case VG_PAINT_TYPE_PATTERN: + shader_id |= VEGA_PATTERN_SHADER; + break; + + default: + abort(); + } + } + + /* second stage image */ + if (shader->drawing_image) { + switch(shader->image_mode) { + case VG_DRAW_IMAGE_NORMAL: + shader_id |= VEGA_IMAGE_NORMAL_SHADER; + break; + case VG_DRAW_IMAGE_MULTIPLY: + shader_id |= VEGA_IMAGE_MULTIPLY_SHADER; + break; + case VG_DRAW_IMAGE_STENCIL: + shader_id |= VEGA_IMAGE_STENCIL_SHADER; + break; + default: + debug_printf("Unknown image mode!"); + } + } + + if (shader->masking) + shader_id |= VEGA_MASK_SHADER; + + switch(blend_mode) { + case VG_BLEND_MULTIPLY: + shader_id |= VEGA_BLEND_MULTIPLY_SHADER; + break; + case VG_BLEND_SCREEN: + shader_id |= VEGA_BLEND_SCREEN_SHADER; + break; + case VG_BLEND_DARKEN: + shader_id |= VEGA_BLEND_DARKEN_SHADER; + break; + case VG_BLEND_LIGHTEN: + shader_id |= VEGA_BLEND_LIGHTEN_SHADER; + break; + default: + /* handled by pipe_blend_state */ + break; + } + + if (black_white) + shader_id |= VEGA_BW_SHADER; + + shader->fs = shaders_cache_fill(ctx->sc, shader_id); + cso_set_fragment_shader_handle(ctx->cso_context, shader->fs); +} + + +void shader_bind(struct shader *shader) +{ + /* first resolve the real paint type */ + paint_resolve_type(shader->paint); + + setup_constant_buffer(shader); + setup_samplers(shader); + setup_shader_program(shader); +} + +void shader_set_image_mode(struct shader *shader, VGImageMode image_mode) +{ + shader->image_mode = image_mode; +} + +VGImageMode shader_image_mode(struct shader *shader) +{ + return shader->image_mode; +} + +void shader_set_drawing_image(struct shader *shader, VGboolean drawing_image) +{ + shader->drawing_image = drawing_image; +} + +VGboolean shader_drawing_image(struct shader *shader) +{ + return shader->drawing_image; +} + +void shader_set_image(struct shader *shader, struct vg_image *img) +{ + shader->image = img; +} diff --git a/src/gallium/state_trackers/vega/shader.h b/src/gallium/state_trackers/vega/shader.h new file mode 100644 index 00000000000..847eee6a310 --- /dev/null +++ b/src/gallium/state_trackers/vega/shader.h @@ -0,0 +1,56 @@ +/************************************************************************** + * + * 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 SHADER_H +#define SHADER_H + +#include "VG/openvg.h" + +struct shader; +struct vg_paint; +struct vg_context; +struct vg_image; + +struct shader *shader_create(struct vg_context *context); +void shader_destroy(struct shader *shader); + +void shader_set_masking(struct shader *shader, VGboolean set); +VGboolean shader_is_masking(struct shader *shader); + +void shader_set_paint(struct shader *shader, struct vg_paint *paint); +struct vg_paint *shader_paint(struct shader *shader); + +void shader_set_image_mode(struct shader *shader, VGImageMode image_mode); +VGImageMode shader_image_mode(struct shader *shader); + +void shader_set_drawing_image(struct shader *shader, VGboolean drawing_image); +VGboolean shader_drawing_image(struct shader *shader); + +void shader_set_image(struct shader *shader, struct vg_image *img); + +void shader_bind(struct shader *shader); + +#endif diff --git a/src/gallium/state_trackers/vega/shaders_cache.c b/src/gallium/state_trackers/vega/shaders_cache.c new file mode 100644 index 00000000000..fd0831fab1f --- /dev/null +++ b/src/gallium/state_trackers/vega/shaders_cache.c @@ -0,0 +1,439 @@ +/************************************************************************** + * + * 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 "shaders_cache.h" + +#include "vg_context.h" + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_inlines.h" +#include "pipe/p_screen.h" +#include "pipe/p_shader_tokens.h" + +#include "tgsi/tgsi_build.h" +#include "tgsi/tgsi_dump.h" +#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_util.h" +#include "tgsi/tgsi_text.h" + +#include "util/u_memory.h" +#include "util/u_math.h" +#include "util/u_debug.h" +#include "cso_cache/cso_hash.h" +#include "cso_cache/cso_context.h" + +#include "VG/openvg.h" + +#include "asm_fill.h" + +/* Essentially we construct an ubber-shader based on the state + * of the pipeline. The stages are: + * 1) Fill (mandatory, solid color/gradient/pattern/image draw) + * 2) Image composition (image mode multiply and stencil) + * 3) Mask + * 4) Extended blend (multiply/screen/darken/lighten) + * 5) Premultiply/Unpremultiply + * 6) Color transform (to black and white) + */ +#define SHADER_STAGES 6 + +struct cached_shader { + void *driver_shader; + struct pipe_shader_state state; +}; + +struct shaders_cache { + struct vg_context *pipe; + + struct cso_hash *hash; +}; + + +static INLINE struct tgsi_token *tokens_from_assembly(const char *txt, int num_tokens) +{ + struct tgsi_token *tokens; + + tokens = (struct tgsi_token *) MALLOC(num_tokens * sizeof(tokens[0])); + + tgsi_text_translate(txt, tokens, num_tokens); + +#if DEBUG_SHADERS + tgsi_dump(tokens, 0); +#endif + + return tokens; +} + +#define ALL_FILLS (VEGA_SOLID_FILL_SHADER | \ + VEGA_LINEAR_GRADIENT_SHADER | \ + VEGA_RADIAL_GRADIENT_SHADER | \ + VEGA_PATTERN_SHADER | \ + VEGA_IMAGE_NORMAL_SHADER) + + +/* +static const char max_shader_preamble[] = + "FRAG1.1\n" + "DCL IN[0], POSITION, LINEAR\n" + "DCL IN[1], GENERIC[0], PERSPECTIVE\n" + "DCL OUT[0], COLOR, CONSTANT\n" + "DCL CONST[0..9], CONSTANT\n" + "DCL TEMP[0..9], CONSTANT\n" + "DCL SAMP[0..9], CONSTANT\n"; + + max_shader_preamble strlen == 175 +*/ +#define MAX_PREAMBLE 175 + +static INLINE VGint range_min(VGint min, VGint current) +{ + if (min < 0) + min = current; + else + min = MIN2(min, current); + return min; +} + +static INLINE VGint range_max(VGint max, VGint current) +{ + return MAX2(max, current); +} + +static void +create_preamble(char *txt, + const struct shader_asm_info *shaders[SHADER_STAGES], + int num_shaders) +{ + VGboolean declare_input = VG_FALSE; + VGint start_const = -1, end_const = 0; + VGint start_temp = -1, end_temp = 0; + VGint start_sampler = -1, end_sampler = 0; + VGint i; + VGint num_consts, num_temps, num_samplers; + + for (i = 0; i < num_shaders; ++i) { + if (shaders[i]->num_consts) + start_const = range_min(start_const, shaders[i]->start_const); + if (shaders[i]->num_temps) + start_temp = range_min(start_temp, shaders[i]->start_temp); + if (shaders[i]->num_samplers) + start_sampler = range_min(start_sampler, shaders[i]->start_sampler); + + end_const = range_max(end_const, shaders[i]->start_const + + shaders[i]->num_consts); + end_temp = range_max(end_temp, shaders[i]->start_temp + + shaders[i]->num_temps); + end_sampler = range_max(end_sampler, shaders[i]->start_sampler + + shaders[i]->num_samplers); + if (shaders[i]->needs_position) + declare_input = VG_TRUE; + } + /* if they're still unitialized, initialize them */ + if (start_const < 0) + start_const = 0; + if (start_temp < 0) + start_temp = 0; + if (start_sampler < 0) + start_sampler = 0; + + num_consts = end_const - start_const; + num_temps = end_temp - start_temp; + num_samplers = end_sampler - start_sampler; + /* end exclusive */ + --end_const; + --end_temp; + --end_sampler; + + sprintf(txt, "FRAG1.1\n"); + + if (declare_input) { + sprintf(txt + strlen(txt), "DCL IN[0], POSITION, LINEAR\n"); + sprintf(txt + strlen(txt), "DCL IN[1], GENERIC[0], PERSPECTIVE\n"); + } + + /* we always have a color output */ + sprintf(txt + strlen(txt), "DCL OUT[0], COLOR, CONSTANT\n"); + + if (num_consts > 1) + sprintf(txt + strlen(txt), "DCL CONST[%d..%d], CONSTANT\n", start_const, end_const); + else if (num_consts == 1) + sprintf(txt + strlen(txt), "DCL CONST[%d], CONSTANT\n", start_const); + + if (num_temps > 1) + sprintf(txt + strlen(txt), "DCL TEMP[%d..%d], CONSTANT\n", start_temp, end_temp); + else if (num_temps > 1) + sprintf(txt + strlen(txt), "DCL TEMP[%d], CONSTANT\n", start_temp); + + if (num_samplers > 1) + sprintf(txt + strlen(txt), "DCL SAMP[%d..%d], CONSTANT\n", start_sampler, end_sampler); + else if (num_samplers == 1) + sprintf(txt + strlen(txt), "DCL SAMP[%d], CONSTANT\n", start_sampler); +} + +static void * +combine_shaders(const struct shader_asm_info *shaders[SHADER_STAGES], int num_shaders, + struct pipe_context *pipe, + struct pipe_shader_state *shader) +{ + char *combined_txt; + int combined_len = MAX_PREAMBLE; + int combined_tokens = 0; + int i = 0; + int current_shader = 0; + int current_len; + + for (i = 0; i < num_shaders; ++i) { + combined_len += strlen(shaders[i]->txt); + combined_tokens += shaders[i]->num_tokens; + } + /* add for the %s->TEMP[0] substitutions */ + combined_len += num_shaders * 7 /*TEMP[0]*/ + 4 /*"END\n"*/; + + combined_txt = (char*)malloc(combined_len); + combined_txt[0] = '\0'; + + create_preamble(combined_txt, shaders, num_shaders); + + while (current_shader < num_shaders) { + const char temp[] = "TEMP[0]"; + const char out[] = "OUT[0]"; + const char *subst = temp; + + current_len = strlen(combined_txt); + + /* if the last shader then output */ + if (current_shader + 1 == num_shaders) + subst = out; + + snprintf(combined_txt + current_len, + combined_len - current_len, + shaders[current_shader]->txt, + subst); + ++current_shader; + } + + + current_len = strlen(combined_txt); + snprintf(combined_txt + current_len, + combined_len - current_len, + "END\n"); + + debug_printf("Combined shader is : \n%s\n", + combined_txt); + + shader->tokens = tokens_from_assembly( + combined_txt, combined_tokens); + + free(combined_txt); + + return pipe->create_fs_state(pipe, shader); +} + +static void * +create_shader(struct pipe_context *pipe, + int id, + struct pipe_shader_state *shader) +{ + int idx = 0; + const struct shader_asm_info * shaders[SHADER_STAGES]; + + /* the shader has to have a fill */ + debug_assert(id & ALL_FILLS); + + /* first stage */ + if (id & VEGA_SOLID_FILL_SHADER) { + debug_assert(idx == 0); + shaders[idx] = &shaders_asm[0]; + debug_assert(shaders_asm[0].id == VEGA_SOLID_FILL_SHADER); + ++idx; + } + if ((id & VEGA_LINEAR_GRADIENT_SHADER)) { + debug_assert(idx == 0); + shaders[idx] = &shaders_asm[1]; + debug_assert(shaders_asm[1].id == VEGA_LINEAR_GRADIENT_SHADER); + ++idx; + } + if ((id & VEGA_RADIAL_GRADIENT_SHADER)) { + debug_assert(idx == 0); + shaders[idx] = &shaders_asm[2]; + debug_assert(shaders_asm[2].id == VEGA_RADIAL_GRADIENT_SHADER); + ++idx; + } + if ((id & VEGA_PATTERN_SHADER)) { + debug_assert(idx == 0); + debug_assert(shaders_asm[3].id == VEGA_PATTERN_SHADER); + shaders[idx] = &shaders_asm[3]; + ++idx; + } + if ((id & VEGA_IMAGE_NORMAL_SHADER)) { + debug_assert(idx == 0); + debug_assert(shaders_asm[4].id == VEGA_IMAGE_NORMAL_SHADER); + shaders[idx] = &shaders_asm[4]; + ++idx; + } + + /* second stage */ + if ((id & VEGA_IMAGE_MULTIPLY_SHADER)) { + debug_assert(shaders_asm[5].id == VEGA_IMAGE_MULTIPLY_SHADER); + shaders[idx] = &shaders_asm[5]; + ++idx; + } else if ((id & VEGA_IMAGE_STENCIL_SHADER)) { + debug_assert(shaders_asm[6].id == VEGA_IMAGE_STENCIL_SHADER); + shaders[idx] = &shaders_asm[6]; + ++idx; + } + + /* third stage */ + if ((id & VEGA_MASK_SHADER)) { + debug_assert(idx == 1); + debug_assert(shaders_asm[7].id == VEGA_MASK_SHADER); + shaders[idx] = &shaders_asm[7]; + ++idx; + } + + /* fourth stage */ + if ((id & VEGA_BLEND_MULTIPLY_SHADER)) { + debug_assert(shaders_asm[8].id == VEGA_BLEND_MULTIPLY_SHADER); + shaders[idx] = &shaders_asm[8]; + ++idx; + } else if ((id & VEGA_BLEND_SCREEN_SHADER)) { + debug_assert(shaders_asm[9].id == VEGA_BLEND_SCREEN_SHADER); + shaders[idx] = &shaders_asm[9]; + ++idx; + } else if ((id & VEGA_BLEND_DARKEN_SHADER)) { + debug_assert(shaders_asm[10].id == VEGA_BLEND_DARKEN_SHADER); + shaders[idx] = &shaders_asm[10]; + ++idx; + } else if ((id & VEGA_BLEND_LIGHTEN_SHADER)) { + debug_assert(shaders_asm[11].id == VEGA_BLEND_LIGHTEN_SHADER); + shaders[idx] = &shaders_asm[11]; + ++idx; + } + + /* fifth stage */ + if ((id & VEGA_PREMULTIPLY_SHADER)) { + debug_assert(shaders_asm[12].id == VEGA_PREMULTIPLY_SHADER); + shaders[idx] = &shaders_asm[12]; + ++idx; + } else if ((id & VEGA_UNPREMULTIPLY_SHADER)) { + debug_assert(shaders_asm[13].id == VEGA_UNPREMULTIPLY_SHADER); + shaders[idx] = &shaders_asm[13]; + ++idx; + } + + /* sixth stage */ + if ((id & VEGA_BW_SHADER)) { + debug_assert(shaders_asm[14].id == VEGA_BW_SHADER); + shaders[idx] = &shaders_asm[14]; + ++idx; + } + + return combine_shaders(shaders, idx, pipe, shader); +} + +/*************************************************/ + +struct shaders_cache * shaders_cache_create(struct vg_context *vg) +{ + struct shaders_cache *sc = CALLOC_STRUCT(shaders_cache); + + sc->pipe = vg; + sc->hash = cso_hash_create(); + + return sc; +} + +void shaders_cache_destroy(struct shaders_cache *sc) +{ + struct cso_hash_iter iter = cso_hash_first_node(sc->hash); + + while (!cso_hash_iter_is_null(iter)) { + struct cached_shader *cached = + (struct cached_shader *)cso_hash_iter_data(iter); + cso_delete_fragment_shader(sc->pipe->cso_context, + cached->driver_shader); + iter = cso_hash_erase(sc->hash, iter); + } + + cso_hash_delete(sc->hash); + free(sc); +} + +void * shaders_cache_fill(struct shaders_cache *sc, + int shader_key) +{ + VGint key = shader_key; + struct cached_shader *cached; + struct cso_hash_iter iter = cso_hash_find(sc->hash, key); + + if (cso_hash_iter_is_null(iter)) { + cached = CALLOC_STRUCT(cached_shader); + cached->driver_shader = create_shader(sc->pipe->pipe, key, &cached->state); + + cso_hash_insert(sc->hash, key, cached); + + return cached->driver_shader; + } + + cached = (struct cached_shader *)cso_hash_iter_data(iter); + + assert(cached->driver_shader); + return cached->driver_shader; +} + +struct vg_shader * shader_create_from_text(struct pipe_context *pipe, + const char *txt, int num_tokens, + int type) +{ + struct vg_shader *shader = (struct vg_shader *)malloc( + sizeof(struct vg_shader)); + struct tgsi_token *tokens = tokens_from_assembly(txt, num_tokens); + struct pipe_shader_state state; + + debug_assert(type == PIPE_SHADER_VERTEX || + type == PIPE_SHADER_FRAGMENT); + + state.tokens = tokens; + shader->type = type; + shader->tokens = tokens; + + if (type == PIPE_SHADER_FRAGMENT) + shader->driver = pipe->create_fs_state(pipe, &state); + else + shader->driver = pipe->create_vs_state(pipe, &state); + return shader; +} + +void vg_shader_destroy(struct vg_context *ctx, struct vg_shader *shader) +{ + if (shader->type == PIPE_SHADER_FRAGMENT) + cso_delete_fragment_shader(ctx->cso_context, shader->driver); + else + cso_delete_vertex_shader(ctx->cso_context, shader->driver); + free(shader->tokens); + free(shader); +} diff --git a/src/gallium/state_trackers/vega/shaders_cache.h b/src/gallium/state_trackers/vega/shaders_cache.h new file mode 100644 index 00000000000..feca58b61a9 --- /dev/null +++ b/src/gallium/state_trackers/vega/shaders_cache.h @@ -0,0 +1,77 @@ +/************************************************************************** + * + * 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 SHADERS_CACHE_H +#define SHADERS_CACHE_H + + +struct vg_context; +struct pipe_context; +struct tgsi_token; +struct shaders_cache; + +enum VegaShaderType { + VEGA_SOLID_FILL_SHADER = 1 << 0, + VEGA_LINEAR_GRADIENT_SHADER = 1 << 1, + VEGA_RADIAL_GRADIENT_SHADER = 1 << 2, + VEGA_PATTERN_SHADER = 1 << 3, + VEGA_IMAGE_NORMAL_SHADER = 1 << 4, + VEGA_IMAGE_MULTIPLY_SHADER = 1 << 5, + VEGA_IMAGE_STENCIL_SHADER = 1 << 6, + + VEGA_MASK_SHADER = 1 << 7, + + VEGA_BLEND_MULTIPLY_SHADER = 1 << 8, + VEGA_BLEND_SCREEN_SHADER = 1 << 9, + VEGA_BLEND_DARKEN_SHADER = 1 << 10, + VEGA_BLEND_LIGHTEN_SHADER = 1 << 11, + + VEGA_PREMULTIPLY_SHADER = 1 << 12, + VEGA_UNPREMULTIPLY_SHADER = 1 << 13, + + VEGA_BW_SHADER = 1 << 14 +}; + +struct vg_shader { + void *driver; + struct tgsi_token *tokens; + int type;/* PIPE_SHADER_VERTEX, PIPE_SHADER_FRAGMENT */ +}; + +struct shaders_cache *shaders_cache_create(struct vg_context *pipe); +void shaders_cache_destroy(struct shaders_cache *sc); +void *shaders_cache_fill(struct shaders_cache *sc, + int shader_key); + +struct vg_shader *shader_create_from_text(struct pipe_context *pipe, + const char *txt, int num_tokens, + int type); + +void vg_shader_destroy(struct vg_context *ctx, struct vg_shader *shader); + + + +#endif diff --git a/src/gallium/state_trackers/vega/st_inlines.h b/src/gallium/state_trackers/vega/st_inlines.h new file mode 100644 index 00000000000..1f331dfcdb7 --- /dev/null +++ b/src/gallium/state_trackers/vega/st_inlines.h @@ -0,0 +1,159 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/** + * Functions for checking if buffers/textures are referenced when we need + * to read/write from/to them. Flush when needed. + */ + +#ifndef ST_INLINES_H +#define ST_INLINES_H + +#include "vg_context.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "pipe/p_defines.h" +#include "pipe/p_inlines.h" +#include "pipe/p_state.h" + +static INLINE struct pipe_transfer * +st_cond_flush_get_tex_transfer(struct vg_context *st, + struct pipe_texture *pt, + unsigned int face, + unsigned int level, + unsigned int zslice, + enum pipe_transfer_usage usage, + unsigned int x, unsigned int y, + unsigned int w, unsigned int h) +{ + struct pipe_screen *screen = st->pipe->screen; + struct pipe_context *pipe = st->pipe; + unsigned referenced = + pipe->is_texture_referenced(pipe, pt, face, level); + + if (referenced && ((referenced & PIPE_REFERENCED_FOR_WRITE) || + usage == PIPE_TRANSFER_WRITE || + usage == PIPE_TRANSFER_READ_WRITE)) + vgFlush(); + + return screen->get_tex_transfer(screen, pt, face, level, zslice, usage, + x, y, w, h); +} + +static INLINE struct pipe_transfer * +st_no_flush_get_tex_transfer(struct vg_context *st, + struct pipe_texture *pt, + unsigned int face, + unsigned int level, + unsigned int zslice, + enum pipe_transfer_usage usage, + unsigned int x, unsigned int y, + unsigned int w, unsigned int h) +{ + struct pipe_screen *screen = st->pipe->screen; + + return screen->get_tex_transfer(screen, pt, face, level, + zslice, usage, x, y, w, h); +} + +static INLINE void * +st_cond_flush_pipe_buffer_map(struct vg_context *st, + struct pipe_buffer *buf, + unsigned int map_flags) +{ + struct pipe_context *pipe = st->pipe; + unsigned int referenced = pipe->is_buffer_referenced(pipe, buf); + + if (referenced && ((referenced & PIPE_REFERENCED_FOR_WRITE) || + (map_flags & PIPE_BUFFER_USAGE_CPU_WRITE))) + vgFlush(); + + return pipe_buffer_map(pipe->screen, buf, map_flags); +} + +static INLINE void * +st_no_flush_pipe_buffer_map(struct vg_context *st, + struct pipe_buffer *buf, + unsigned int map_flags) +{ + return pipe_buffer_map(st->pipe->screen, buf, map_flags); +} + + +static INLINE void +st_cond_flush_pipe_buffer_write(struct vg_context *st, + struct pipe_buffer *buf, + unsigned int offset, + unsigned int size, + const void * data) +{ + struct pipe_context *pipe = st->pipe; + + if (pipe->is_buffer_referenced(pipe, buf)) + vgFlush(); + + pipe_buffer_write(pipe->screen, buf, offset, size, data); +} + +static INLINE void +st_no_flush_pipe_buffer_write(struct vg_context *st, + struct pipe_buffer *buf, + unsigned int offset, + unsigned int size, + const void * data) +{ + pipe_buffer_write(st->pipe->screen, buf, offset, size, data); +} + +static INLINE void +st_cond_flush_pipe_buffer_read(struct vg_context *st, + struct pipe_buffer *buf, + unsigned int offset, + unsigned int size, + void * data) +{ + struct pipe_context *pipe = st->pipe; + + if (pipe->is_buffer_referenced(pipe, buf) & PIPE_REFERENCED_FOR_WRITE) + vgFlush(); + + pipe_buffer_read(pipe->screen, buf, offset, size, data); +} + +static INLINE void +st_no_flush_pipe_buffer_read(struct vg_context *st, + struct pipe_buffer *buf, + unsigned int offset, + unsigned int size, + void * data) +{ + pipe_buffer_read(st->pipe->screen, buf, offset, size, data); +} + +#endif + diff --git a/src/gallium/state_trackers/vega/stroker.c b/src/gallium/state_trackers/vega/stroker.c new file mode 100644 index 00000000000..1b92d2b5c62 --- /dev/null +++ b/src/gallium/state_trackers/vega/stroker.c @@ -0,0 +1,1349 @@ +/************************************************************************** + * + * 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 "stroker.h" + +#include "path.h" +#include "vg_state.h" +#include "util_array.h" +#include "arc.h" +#include "bezier.h" +#include "matrix.h" +#include "path_utils.h" +#include "polygon.h" + +#include "math.h" + +#ifndef M_2PI +#define M_2PI 6.28318530717958647692528676655900576 +#endif + +#define STROKE_SEGMENTS 0 +#define STROKE_DEBUG 0 +#define DEBUG_EMITS 0 + +static const VGfloat curve_threshold = 0.25f; + +static const VGfloat zero_coords[] = {0.f, 0.f}; + +enum intersection_type { + NoIntersections, + BoundedIntersection, + UnboundedIntersection, +}; + +enum line_join_mode { + FlatJoin, + SquareJoin, + MiterJoin, + RoundJoin, + RoundCap +}; + +struct stroke_iterator { + void (*next)(struct stroke_iterator *); + VGboolean (*has_next)(struct stroke_iterator *); + + VGPathCommand (*current_command)(struct stroke_iterator *it); + void (*current_coords)(struct stroke_iterator *it, VGfloat *coords); + + VGint position; + VGint coord_position; + + const VGubyte *cmds; + const VGfloat *coords; + VGint num_commands; + VGint num_coords; + + struct polygon *curve_poly; + VGint curve_index; +}; + +static VGPathCommand stroke_itr_command(struct stroke_iterator *itr) +{ + return itr->current_command(itr); +} + +static void stroke_itr_coords(struct stroke_iterator *itr, VGfloat *coords) +{ + itr->current_coords(itr, coords); +} + +static void stroke_fw_itr_coords(struct stroke_iterator *itr, VGfloat *coords) +{ + if (itr->position >= itr->num_commands) + return; + switch (stroke_itr_command(itr)) { + case VG_MOVE_TO_ABS: + coords[0] = itr->coords[itr->coord_position]; + coords[1] = itr->coords[itr->coord_position + 1]; + break; + case VG_LINE_TO_ABS: + coords[0] = itr->coords[itr->coord_position]; + coords[1] = itr->coords[itr->coord_position + 1]; + break; + case VG_CUBIC_TO_ABS: + coords[0] = itr->coords[itr->coord_position]; + coords[1] = itr->coords[itr->coord_position + 1]; + coords[2] = itr->coords[itr->coord_position + 2]; + coords[3] = itr->coords[itr->coord_position + 3]; + coords[4] = itr->coords[itr->coord_position + 4]; + coords[5] = itr->coords[itr->coord_position + 5]; + break; + default: + debug_assert(!"invalid command!\n"); + } +} + + +static void stroke_bw_itr_coords(struct stroke_iterator *itr, VGfloat *coords) +{ + if (itr->position >= itr->num_commands) + return; + switch (stroke_itr_command(itr)) { + case VG_MOVE_TO_ABS: + coords[0] = itr->coords[itr->coord_position]; + coords[1] = itr->coords[itr->coord_position + 1]; + break; + case VG_LINE_TO_ABS: + coords[0] = itr->coords[itr->coord_position]; + coords[1] = itr->coords[itr->coord_position + 1]; + break; + case VG_CUBIC_TO_ABS: + coords[0] = itr->coords[itr->coord_position + 4]; + coords[1] = itr->coords[itr->coord_position + 5]; + coords[2] = itr->coords[itr->coord_position + 2]; + coords[3] = itr->coords[itr->coord_position + 3]; + coords[4] = itr->coords[itr->coord_position + 0]; + coords[5] = itr->coords[itr->coord_position + 1]; + break; + default: + debug_assert(!"invalid command!\n"); + } +} + + +static VGPathCommand stroke_fw_current_command(struct stroke_iterator *it) +{ + return it->cmds[it->position]; +} + +static VGPathCommand stroke_bw_current_command(struct stroke_iterator *it) +{ + VGPathCommand prev_cmd; + if (it->position == it->num_commands -1) + return VG_MOVE_TO_ABS; + + prev_cmd = it->cmds[it->position + 1]; + return prev_cmd; +} + +static VGboolean stroke_fw_has_next(struct stroke_iterator *itr) +{ + return itr->position < (itr->num_commands - 1); +} + +static VGboolean stroke_bw_has_next(struct stroke_iterator *itr) +{ + return itr->position > 0; +} + +static void stroke_fw_next(struct stroke_iterator *itr) +{ + VGubyte cmd; + debug_assert(stroke_fw_has_next(itr)); + + cmd = stroke_itr_command(itr); + + itr->coord_position += num_elements_for_segments(&cmd, 1); + ++itr->position; +} + +static void stroke_bw_next(struct stroke_iterator *itr) +{ + VGubyte cmd; + debug_assert(stroke_bw_has_next(itr)); + + --itr->position; + cmd = stroke_itr_command(itr); + + itr->coord_position -= num_elements_for_segments(&cmd, 1); +} + +static void stroke_itr_common_init(struct stroke_iterator *itr, + struct array *cmds, + struct array *coords) +{ + itr->cmds = (VGubyte*)cmds->data; + itr->num_commands = cmds->num_elements; + + itr->coords = (VGfloat*)coords->data; + itr->num_coords = coords->num_elements; +} + +static void stroke_forward_iterator(struct stroke_iterator *itr, + struct array *cmds, + struct array *coords) +{ + stroke_itr_common_init(itr, cmds, coords); + itr->position = 0; + itr->coord_position = 0; + + itr->next = stroke_fw_next; + itr->has_next = stroke_fw_has_next; + itr->current_command = stroke_fw_current_command; + itr->current_coords = stroke_fw_itr_coords; +} + +static void stroke_backward_iterator(struct stroke_iterator *itr, + struct array *cmds, + struct array *coords) +{ + VGubyte cmd; + stroke_itr_common_init(itr, cmds, coords); + itr->position = itr->num_commands - 1; + + cmd = stroke_bw_current_command(itr); + itr->coord_position = itr->num_coords - + num_elements_for_segments(&cmd, 1); + + itr->next = stroke_bw_next; + itr->has_next = stroke_bw_has_next; + itr->current_command = stroke_bw_current_command; + itr->current_coords = stroke_bw_itr_coords; +} + + + +static void stroke_flat_next(struct stroke_iterator *itr) +{ + VGubyte cmd; + + if (itr->curve_index >= 0) { + ++itr->curve_index; + if (itr->curve_index >= polygon_vertex_count(itr->curve_poly)) { + itr->curve_index = -1; + polygon_destroy(itr->curve_poly); + itr->curve_poly = 0; + } else + return; + } + debug_assert(stroke_fw_has_next(itr)); + + cmd = itr->cmds[itr->position]; + itr->coord_position += num_elements_for_segments(&cmd, 1); + ++itr->position; + + cmd = itr->cmds[itr->position]; + + if (cmd == VG_CUBIC_TO_ABS) { + struct bezier bezier; + VGfloat bez[8]; + + bez[0] = itr->coords[itr->coord_position - 2]; + bez[1] = itr->coords[itr->coord_position - 1]; + bez[2] = itr->coords[itr->coord_position]; + bez[3] = itr->coords[itr->coord_position + 1]; + bez[4] = itr->coords[itr->coord_position + 2]; + bez[5] = itr->coords[itr->coord_position + 3]; + bez[6] = itr->coords[itr->coord_position + 4]; + bez[7] = itr->coords[itr->coord_position + 5]; + + bezier_init(&bezier, + bez[0], bez[1], + bez[2], bez[3], + bez[4], bez[5], + bez[6], bez[7]); + /* skip the first one, it's the same as the prev point */ + itr->curve_index = 1; + if (itr->curve_poly) { + polygon_destroy(itr->curve_poly); + itr->curve_poly = 0; + } + itr->curve_poly = bezier_to_polygon(&bezier); + } +} + +static VGboolean stroke_flat_has_next(struct stroke_iterator *itr) +{ + return (itr->curve_index >= 0 && + itr->curve_index < (polygon_vertex_count(itr->curve_poly)-1)) + || itr->position < (itr->num_commands - 1); +} + +static VGPathCommand stroke_flat_current_command(struct stroke_iterator *it) +{ + if (it->cmds[it->position] == VG_CUBIC_TO_ABS) { + return VG_LINE_TO_ABS; + } + return it->cmds[it->position]; +} + +static void stroke_flat_itr_coords(struct stroke_iterator *itr, VGfloat *coords) +{ + if (itr->curve_index <= -1 && itr->position >= itr->num_commands) + return; + + if (itr->curve_index >= 0) { + polygon_vertex(itr->curve_poly, itr->curve_index, + coords); + return; + } + + switch (stroke_itr_command(itr)) { + case VG_MOVE_TO_ABS: + coords[0] = itr->coords[itr->coord_position]; + coords[1] = itr->coords[itr->coord_position + 1]; + break; + case VG_LINE_TO_ABS: + coords[0] = itr->coords[itr->coord_position]; + coords[1] = itr->coords[itr->coord_position + 1]; + break; + case VG_CUBIC_TO_ABS: + default: + debug_assert(!"invalid command!\n"); + } +} + +static void stroke_flat_iterator(struct stroke_iterator *itr, + struct array *cmds, + struct array *coords) +{ + stroke_itr_common_init(itr, cmds, coords); + itr->position = 0; + itr->coord_position = 0; + + itr->next = stroke_flat_next; + itr->has_next = stroke_flat_has_next; + itr->current_command = stroke_flat_current_command; + itr->current_coords = stroke_flat_itr_coords; + itr->curve_index = -1; + itr->curve_poly = 0; +} + + +static INLINE VGboolean finite_coords4(const VGfloat *c) +{ + return + isfinite(c[0]) && isfinite(c[1]) && + isfinite(c[2]) && isfinite(c[3]); +} + +/* from Graphics Gems II */ +#define SAME_SIGNS(a, b) ((a) * (b) >= 0) +static VGboolean do_lines_intersect(VGfloat x1, VGfloat y1, VGfloat x2, VGfloat y2, + VGfloat x3, VGfloat y3, VGfloat x4, VGfloat y4) +{ + VGfloat a1, a2, b1, b2, c1, c2; /* Coefficients of line eqns */ + VGfloat r1, r2, r3, r4; /* 'sign' values */ + + a1 = y2 - y1; + b1 = x1 - x2; + c1 = x2 * y1 - x1 * y2; + + r3 = a1 * x3 + b1 * y3 + c1; + r4 = a1 * x4 + b1 * y4 + c1; + + if (r3 != 0 && r4 != 0 && SAME_SIGNS(r3, r4)) + return VG_FALSE; + + a2 = y4 - y3; + b2 = x3 - x4; + c2 = x4 * y3 - x3 * y4; + + r1 = a2 * x1 + b2 * y1 + c2; + r2 = a2 * x2 + b2 * y2 + c2; + + if (r1 != 0 && r2 != 0 && SAME_SIGNS(r1, r2)) + return VG_FALSE; + + return VG_TRUE; +} + +static INLINE VGfloat line_dx(const VGfloat *l) +{ + return l[2] - l[0]; +} + +static INLINE VGfloat line_dy(const VGfloat *l) +{ + return l[3] - l[1]; +} + +static INLINE VGfloat line_angle(const VGfloat *l) +{ + const VGfloat dx = line_dx(l); + const VGfloat dy = line_dy(l); + + const VGfloat theta = atan2(-dy, dx) * 360.0 / M_2PI; + + const VGfloat theta_normalized = theta < 0 ? theta + 360 : theta; + + if (floatsEqual(theta_normalized, 360.f)) + return 0; + else + return theta_normalized; +} + +static INLINE void line_set_length(VGfloat *l, VGfloat len) +{ + VGfloat uv[] = {l[0], l[1], l[2], l[3]}; + if (null_line(l)) + return; + line_normalize(uv); + l[2] = l[0] + line_dx(uv) * len; + l[3] = l[1] + line_dy(uv) * len; +} + +static INLINE void line_translate(VGfloat *l, VGfloat x, VGfloat y) +{ + l[0] += x; + l[1] += y; + l[2] += x; + l[3] += y; +} + +static INLINE VGfloat line_angle_to(const VGfloat *l1, + const VGfloat *l2) +{ + VGfloat a1, a2, delta, delta_normalized; + if (null_line(l1) || null_line(l1)) + return 0; + + a1 = line_angle(l1); + a2 = line_angle(l2); + + delta = a2 - a1; + delta_normalized = delta < 0 ? delta + 360 : delta; + + if (floatsEqual(delta, 360.f)) + return 0; + else + return delta_normalized; +} + +static INLINE VGfloat line_angles(const VGfloat *l1, + const VGfloat *l2) +{ + VGfloat cos_line, rad = 0; + + if (null_line(l1) || null_line(l2)) + return 0; + + cos_line = (line_dx(l1)*line_dx(l2) + line_dy(l1)*line_dy(l2)) / + (line_lengthv(l1)*line_lengthv(l2)); + rad = 0; + + if (cos_line >= -1.0 && cos_line <= 1.0) + rad = acos(cos_line); + return rad * 360 / M_2PI; +} + + +static INLINE VGfloat adapted_angle_on_x(const VGfloat *line) +{ + const VGfloat identity[] = {0, 0, 1, 0}; + VGfloat angle = line_angles(line, identity); + if (line_dy(line) > 0) + angle = 360 - angle; + return angle; +} + +static enum intersection_type line_intersect(const VGfloat *l1, + const VGfloat *l2, + float *intersection_point) +{ + VGfloat isect[2]; + enum intersection_type type; + VGboolean dx_zero, ldx_zero; + + if (null_line(l1) || null_line(l2) || + !finite_coords4(l1) || !finite_coords4(l2)) + return NoIntersections; + + type = do_lines_intersect(l1[0], l1[1], l1[2], l1[3], l2[0], l2[1], l2[2], l2[3]) + ? BoundedIntersection : UnboundedIntersection; + + dx_zero = floatsEqual(line_dx(l1) + 1, 1); + ldx_zero = floatsEqual(line_dx(l2) + 1, 1); + + /* one of the lines is vertical */ + if (dx_zero && ldx_zero) { + type = NoIntersections; + } else if (dx_zero) { + VGfloat la = line_dy(l2) / line_dx(l2); + isect[0] = l1[0]; + isect[1] = la * l1[0] + l2[1] - la * l2[0]; + } else if (ldx_zero) { + VGfloat ta = line_dy(l1) / line_dx(l1); + isect[0] = l2[0]; + isect[1] = ta * l2[0] + l1[1] - ta*l1[0]; + } else { + VGfloat x; + VGfloat ta = line_dy(l1) / line_dx(l1); + VGfloat la = line_dy(l2) / line_dx(l2); + if (ta == la) + return NoIntersections; + + x = ( - l2[1] + la * l2[0] + l1[1] - ta * l1[0] ) / (la - ta); + isect[0] = x; + isect[1] = ta*(x - l1[0]) + l1[1]; + } + if (intersection_point) { + intersection_point[0] = isect[0]; + intersection_point[1] = isect[1]; + } + return type; +} + +static INLINE enum line_join_mode stroker_join_mode(struct stroker *s) +{ + switch(s->join_style) { + case VG_JOIN_MITER: + return MiterJoin; + case VG_JOIN_ROUND: + return RoundJoin; + case VG_JOIN_BEVEL: + return FlatJoin; + default: + return FlatJoin; + } +} + +static INLINE enum line_join_mode stroker_cap_mode(struct stroker *s) +{ + switch(s->cap_style) { + case VG_CAP_BUTT: + return FlatJoin; + case VG_CAP_ROUND: + return RoundCap; + case VG_CAP_SQUARE: + return SquareJoin; + default: + return FlatJoin; + } +} + +void stroker_emit_move_to(struct stroker *stroker, VGfloat x, VGfloat y) +{ + VGubyte cmds = VG_MOVE_TO_ABS; + VGfloat coords[2] = {x, y}; +#if DEBUG_EMITS + debug_printf("emit move %f, %f\n", x, y); +#endif + stroker->back2_x = stroker->back1_x; + stroker->back2_y = stroker->back1_y; + stroker->back1_x = x; + stroker->back1_y = y; + + path_append_data(stroker->path, + 1, + &cmds, &coords); +} + +void stroker_emit_line_to(struct stroker *stroker, VGfloat x, VGfloat y) +{ + VGubyte cmds = VG_LINE_TO_ABS; + VGfloat coords[2] = {x, y}; +#if DEBUG_EMITS + debug_printf("emit line %f, %f\n", x, y); +#endif + stroker->back2_x = stroker->back1_x; + stroker->back2_y = stroker->back1_y; + stroker->back1_x = x; + stroker->back1_y = y; + path_append_data(stroker->path, + 1, + &cmds, &coords); +} + +void stroker_emit_curve_to(struct stroker *stroker, VGfloat px1, VGfloat py1, + VGfloat px2, VGfloat py2, + VGfloat x, VGfloat y) +{ + VGubyte cmds = VG_CUBIC_TO_ABS; + VGfloat coords[6] = {px1, py1, px2, py2, x, y}; +#if DEBUG_EMITS + debug_printf("emit curve %f, %f, %f, %f, %f, %f\n", px1, py1, + px2, py2, x, y); +#endif + + if (px2 == x && py2 == y) { + if (px1 == x && py1 == y) { + stroker->back2_x = stroker->back1_x; + stroker->back2_y = stroker->back1_y; + } else { + stroker->back2_x = px1; + stroker->back2_y = py1; + } + } else { + stroker->back2_x = px2; + stroker->back2_y = py2; + } + stroker->back1_x = x; + stroker->back1_y = y; + + path_append_data(stroker->path, + 1, + &cmds, &coords); +} + +static INLINE void create_round_join(struct stroker *stroker, + VGfloat x1, VGfloat y1, + VGfloat x2, VGfloat y2, + VGfloat width, VGfloat height) +{ + struct arc arc; + struct matrix matrix; + + matrix_load_identity(&matrix); + + /*stroker_emit_line_to(stroker, nx, ny);*/ + + arc_init(&arc, VG_SCCWARC_TO_ABS, + x1, y1, x2, y2, width/2, height/2, 0); + arc_stroker_emit(&arc, stroker, &matrix); +} + + +static void create_joins(struct stroker *stroker, + VGfloat focal_x, VGfloat focal_y, + const VGfloat *next_line, enum line_join_mode join) +{ +#if DEBUG_EMITS + debug_printf("create_joins: focal=[%f, %f], next_line=[%f, %f,%f, %f]\n", + focal_x, focal_y, + next_line[0], next_line[1], next_line[2], next_line[3]); +#endif + /* if we're alredy connected do nothing */ + if (floatsEqual(stroker->back1_x, next_line[0]) && + floatsEqual(stroker->back1_y, next_line[1])) + return; + + if (join == FlatJoin) { + stroker_emit_line_to(stroker, next_line[0], next_line[1]); + } else { + VGfloat prev_line[] = {stroker->back2_x, stroker->back2_y, + stroker->back1_x, stroker->back1_y}; + + VGfloat isect[2]; + enum intersection_type type = line_intersect(prev_line, next_line, isect); + + if (join == SquareJoin) { + VGfloat offset = stroker->stroke_width / 2; + VGfloat l1[4] = {prev_line[0], + prev_line[1], + prev_line[2], + prev_line[3]}; + VGfloat l2[4] = {next_line[2], + next_line[3], + next_line[0], + next_line[1]}; + + line_translate(l1, line_dx(l1), line_dy(l1)); + line_set_length(l1, offset); + + line_translate(l2, line_dx(l2), line_dy(l2)); + line_set_length(l2, offset); + + stroker_emit_line_to(stroker, l1[2], l1[3]); + stroker_emit_line_to(stroker, l2[2], l2[3]); + stroker_emit_line_to(stroker, l2[0], l2[1]); + } else if (join == RoundJoin) { + VGfloat offset = stroker->stroke_width / 2; + VGfloat short_cut[4] = {prev_line[2], prev_line[3], + next_line[0], next_line[1]}; + VGfloat angle = line_angles(prev_line, short_cut); + + if (type == BoundedIntersection || + (angle > 90 && !floatsEqual(angle, 90.f))) { + stroker_emit_line_to(stroker, next_line[0], next_line[1]); + return; + } + create_round_join(stroker, prev_line[2], prev_line[3], + next_line[0], next_line[1], + offset * 2, offset * 2); + + stroker_emit_line_to(stroker, next_line[0], next_line[1]); + } else if (join == RoundCap) { + VGfloat offset = stroker->stroke_width / 2; + VGfloat l1[4] = { prev_line[0], prev_line[1], + prev_line[2], prev_line[3] }; + VGfloat l2[4] = {focal_x, focal_y, + prev_line[2], prev_line[3]}; + + line_translate(l1, line_dx(l1), line_dy(l1)); + line_set_length(l1, KAPPA * offset); + + /* normal between prev_line and focal */ + line_translate(l2, -line_dy(l2), line_dx(l2)); + line_set_length(l2, KAPPA * offset); + + stroker_emit_curve_to(stroker, l1[2], l1[3], + l2[2], l2[3], + l2[0], l2[1]); + + l2[0] = l2[0]; + l2[1] = l2[1]; + l2[2] = l2[0] - line_dx(l2); + l2[3] = l2[1] - line_dy(l2); + + line_translate(l1, next_line[0] - l1[0], next_line[1] - l1[1]); + + stroker_emit_curve_to(stroker, + l2[2], l2[3], + l1[2], l1[3], + l1[0], l1[1]); + } else if (join == MiterJoin) { + VGfloat miter_line[4] = {stroker->back1_x, stroker->back1_y, + isect[0], isect[1]}; + VGfloat sl = (stroker->stroke_width * stroker->miter_limit); + VGfloat inside_line[4] = {prev_line[2], prev_line[3], + next_line[0], next_line[1]}; + VGfloat angle = line_angle_to(inside_line, prev_line); + + if (type == BoundedIntersection || + (angle > 90 && !floatsEqual(angle, 90.f))) { + /* + debug_printf("f = %f, nl = %f, pl = %f, is = %f\n", + focal_x, next_line[0], + prev_line[2], isect[0]);*/ + stroker_emit_line_to(stroker, next_line[0], next_line[1]); + return; + } + + if (type == NoIntersections || line_lengthv(miter_line) > sl) { + stroker_emit_line_to(stroker, next_line[0], next_line[1]); + } else { + stroker_emit_line_to(stroker, isect[0], isect[1]); + stroker_emit_line_to(stroker, next_line[0], next_line[1]); + } + } else { + debug_assert(!"create_joins bad join style"); + } + } +} + +static void stroker_add_segment(struct stroker *stroker, + VGPathCommand cmd, + const VGfloat *coords, + VGint num_coords) +{ + /* skip duplicated points */ + if (stroker->segments->num_elements && + stroker->last_cmd == cmd) { + VGfloat *data = stroker->control_points->data; + data += stroker->control_points->num_elements; + data -= num_coords; + switch (cmd) { + case VG_MOVE_TO_ABS: + if (floatsEqual(coords[0], data[0]) && + floatsEqual(coords[1], data[1])) + return; + break; + case VG_LINE_TO_ABS: + if (floatsEqual(coords[0], data[0]) && + floatsEqual(coords[1], data[1])) + return; + break; + case VG_CUBIC_TO_ABS: + if (floatsEqual(coords[0], data[0]) && + floatsEqual(coords[1], data[1]) && + floatsEqual(coords[2], data[2]) && + floatsEqual(coords[3], data[3]) && + floatsEqual(coords[4], data[4]) && + floatsEqual(coords[5], data[5])) + return; + break; + default: + debug_assert(!"Invalid stroke segment"); + } + } else if (stroker->last_cmd == VG_CUBIC_TO_ABS && + cmd == VG_LINE_TO_ABS) { + VGfloat *data = stroker->control_points->data; + data += stroker->control_points->num_elements; + data -= 2; + if (floatsEqual(coords[0], data[0]) && + floatsEqual(coords[1], data[1])) + return; + } + stroker->last_cmd = cmd; + array_append_data(stroker->segments, &cmd, 1); + array_append_data(stroker->control_points, coords, num_coords); +} + +void stroker_move_to(struct stroker *stroker, VGfloat x, VGfloat y) +{ + VGfloat coords[2] = {x, y}; +#if STROKE_SEGMENTS + debug_printf("stroker_move_to(%f, %f)\n", x, y); +#endif + + if (stroker->segments->num_elements > 0) + stroker->process_subpath(stroker); + + array_reset(stroker->segments); + array_reset(stroker->control_points); + + stroker_add_segment(stroker, VG_MOVE_TO_ABS, coords, 2); +} + +void stroker_line_to(struct stroker *stroker, VGfloat x, VGfloat y) +{ + VGfloat coords[] = {x, y}; + +#if STROKE_SEGMENTS + debug_printf("stroker_line_to(%f, %f)\n", x, y); +#endif + if (!stroker->segments->num_elements) + stroker_add_segment(stroker, VG_MOVE_TO_ABS, zero_coords, 2); + + stroker_add_segment(stroker, VG_LINE_TO_ABS, coords, 2); +} + +void stroker_curve_to(struct stroker *stroker, VGfloat px1, VGfloat py1, + VGfloat px2, VGfloat py2, + VGfloat x, VGfloat y) +{ + VGfloat coords[] = {px1, py1, + px2, py2, + x, y}; +#if STROKE_SEGMENTS + debug_printf("stroker_curve_to(%f, %f, %f, %f, %f, %f)\n", + px1, py1, px2, py2, x, y); +#endif + if (!stroker->segments->num_elements) + stroker_add_segment(stroker, VG_MOVE_TO_ABS, zero_coords, 2); + + stroker_add_segment(stroker, VG_CUBIC_TO_ABS, coords, 6); +} + +static INLINE VGboolean is_segment_null(VGPathCommand cmd, + VGfloat *coords, + VGfloat *res) +{ + switch(cmd) { + case VG_MOVE_TO_ABS: + case VG_LINE_TO_ABS: + return floatsEqual(coords[0], res[0]) && + floatsEqual(coords[1], res[1]); + break; + case VG_CUBIC_TO_ABS: + return floatsEqual(coords[0], res[0]) && + floatsEqual(coords[1], res[1]) && + floatsEqual(coords[2], res[0]) && + floatsEqual(coords[3], res[1]) && + floatsEqual(coords[4], res[0]) && + floatsEqual(coords[5], res[1]); + break; + default: + assert(0); + } + return VG_FALSE; +} + +static VGboolean vg_stroke_outline(struct stroke_iterator *it, + struct stroker *stroker, + VGboolean cap_first, + VGfloat *start_tangent) +{ + const int MAX_OFFSET = 16; + struct bezier offset_curves[MAX_OFFSET]; + VGPathCommand first_element; + VGfloat start[2], prev[2]; + VGboolean first = VG_TRUE; + VGfloat offset; + + first_element = stroke_itr_command(it); + if (first_element != VG_MOVE_TO_ABS) { + stroker_emit_move_to(stroker, 0.f, 0.f); + prev[0] = 0.f; + prev[1] = 0.f; + } + stroke_itr_coords(it, start); +#if STROKE_DEBUG + debug_printf(" -> (side) [%.2f, %.2f]\n", + start[0], + start[1]); +#endif + + prev[0] = start[0]; + prev[1] = start[1]; + + offset = stroker->stroke_width / 2; + + if (!it->has_next(it)) { + /* single point */ + + return VG_TRUE; + } + + while (it->has_next(it)) { + VGPathCommand cmd; + VGfloat coords[8]; + + it->next(it); + cmd = stroke_itr_command(it); + stroke_itr_coords(it, coords); + + if (cmd == VG_LINE_TO_ABS) { + VGfloat line[4] = {prev[0], prev[1], coords[0], coords[1]}; + VGfloat normal[4]; + line_normal(line, normal); + +#if STROKE_DEBUG + debug_printf("\n ---> (side) lineto [%.2f, %.2f]\n", coords[0], coords[1]); +#endif + line_set_length(normal, offset); + line_translate(line, line_dx(normal), line_dy(normal)); + + /* if we are starting a new subpath, move to correct starting point */ + if (first) { + if (cap_first) + create_joins(stroker, prev[0], prev[1], line, + stroker_cap_mode(stroker)); + else + stroker_emit_move_to(stroker, line[0], line[1]); + memcpy(start_tangent, line, + sizeof(VGfloat) * 4); + first = VG_FALSE; + } else { + create_joins(stroker, prev[0], prev[1], line, + stroker_join_mode(stroker)); + } + + /* add the stroke for this line */ + stroker_emit_line_to(stroker, line[2], line[3]); + prev[0] = coords[0]; + prev[1] = coords[1]; + } else if (cmd == VG_CUBIC_TO_ABS) { +#if STROKE_DEBUG + debug_printf("\n ---> (side) cubicTo [%.2f, %.2f]\n", + coords[4], + coords[5]); +#endif + struct bezier bezier; + int count; + + bezier_init(&bezier, + prev[0], prev[1], coords[0], coords[1], + coords[2], coords[3], coords[4], coords[5]); + + count = bezier_translate_by_normal(&bezier, + offset_curves, + MAX_OFFSET, + offset, + curve_threshold); + + if (count) { + /* if we are starting a new subpath, move to correct starting point */ + VGfloat tangent[4]; + VGint i; + + bezier_start_tangent(&bezier, tangent); + line_translate(tangent, + offset_curves[0].x1 - bezier.x1, + offset_curves[0].y1 - bezier.y1); + if (first) { + VGfloat pt[2] = {offset_curves[0].x1, + offset_curves[0].y1}; + + if (cap_first) { + create_joins(stroker, prev[0], prev[1], tangent, + stroker_cap_mode(stroker)); + } else { + stroker_emit_move_to(stroker, pt[0], pt[1]); + } + start_tangent[0] = tangent[0]; + start_tangent[1] = tangent[1]; + start_tangent[2] = tangent[2]; + start_tangent[3] = tangent[3]; + first = VG_FALSE; + } else { + create_joins(stroker, prev[0], prev[1], tangent, + stroker_join_mode(stroker)); + } + + /* add these beziers */ + for (i = 0; i < count; ++i) { + struct bezier *bez = &offset_curves[i]; + stroker_emit_curve_to(stroker, + bez->x2, bez->y2, + bez->x3, bez->y3, + bez->x4, bez->y4); + } + } + + prev[0] = coords[4]; + prev[1] = coords[5]; + } + } + + if (floatsEqual(start[0], prev[0]) && + floatsEqual(start[1], prev[1])) { + /* closed subpath, join first and last point */ +#if STROKE_DEBUG + debug_printf("\n stroker: closed subpath\n"); +#endif + create_joins(stroker, prev[0], prev[1], start_tangent, + stroker_join_mode(stroker)); + return VG_TRUE; + } else { +#if STROKE_DEBUG + debug_printf("\n stroker: open subpath\n"); +#endif + return VG_FALSE; + } +} + +static void stroker_process_subpath(struct stroker *stroker) +{ + VGboolean fwclosed, bwclosed; + VGfloat fw_start_tangent[4], bw_start_tangent[4]; + struct stroke_iterator fwit; + struct stroke_iterator bwit; + debug_assert(stroker->segments->num_elements > 0); + + memset(fw_start_tangent, 0, + sizeof(VGfloat)*4); + memset(bw_start_tangent, 0, + sizeof(VGfloat)*4); + + stroke_forward_iterator(&fwit, stroker->segments, + stroker->control_points); + stroke_backward_iterator(&bwit, stroker->segments, + stroker->control_points); + + debug_assert(fwit.cmds[0] == VG_MOVE_TO_ABS); + + fwclosed = vg_stroke_outline(&fwit, stroker, VG_FALSE, fw_start_tangent); + bwclosed = vg_stroke_outline(&bwit, stroker, !fwclosed, bw_start_tangent); + + if (!bwclosed) + create_joins(stroker, + fwit.coords[0], fwit.coords[1], fw_start_tangent, + stroker_cap_mode(stroker)); + else { + /* hack to handle the requirement of the VG spec that says that strokes + * of len==0 that have butt cap or round cap still need + * to be rendered. (8.7.4 Stroke Generation) */ + if (stroker->segments->num_elements <= 3) { + VGPathCommand cmd; + VGfloat data[8], coords[8]; + struct stroke_iterator *it = &fwit; + + stroke_forward_iterator(it, stroker->segments, + stroker->control_points); + cmd = stroke_itr_command(it); + stroke_itr_coords(it, coords); + if (cmd != VG_MOVE_TO_ABS) { + memset(data, 0, sizeof(VGfloat) * 8); + if (!is_segment_null(cmd, coords, data)) + return; + } else { + data[0] = coords[0]; + data[1] = coords[1]; + } + while (it->has_next(it)) { + it->next(it); + cmd = stroke_itr_command(it); + stroke_itr_coords(it, coords); + if (!is_segment_null(cmd, coords, data)) + return; + } + /* generate the square/round cap */ + if (stroker->cap_style == VG_CAP_SQUARE) { + VGfloat offset = stroker->stroke_width / 2; + stroker_emit_move_to(stroker, data[0] - offset, + data[1] - offset); + stroker_emit_line_to(stroker, data[0] + offset, + data[1] - offset); + stroker_emit_line_to(stroker, data[0] + offset, + data[1] + offset); + stroker_emit_line_to(stroker, data[0] - offset, + data[1] + offset); + stroker_emit_line_to(stroker, data[0] - offset, + data[1] - offset); + } else if (stroker->cap_style == VG_CAP_ROUND) { + VGfloat offset = stroker->stroke_width / 2; + VGfloat cx = data[0], cy = data[1]; + { /*circle */ + struct arc arc; + struct matrix matrix; + matrix_load_identity(&matrix); + + stroker_emit_move_to(stroker, cx + offset, cy); + arc_init(&arc, VG_SCCWARC_TO_ABS, + cx + offset, cy, + cx - offset, cy, + offset, offset, 0); + arc_stroker_emit(&arc, stroker, &matrix); + arc_init(&arc, VG_SCCWARC_TO_ABS, + cx - offset, cy, + cx + offset, cy, + offset, offset, 0); + arc_stroker_emit(&arc, stroker, &matrix); + } + } + } + } +} + +static INLINE VGfloat dash_pattern(struct dash_stroker *stroker, + VGint idx) +{ + if (stroker->dash_pattern[idx] < 0) + return 0.f; + return stroker->dash_pattern[idx]; +} + +static void dash_stroker_process_subpath(struct stroker *str) +{ + struct dash_stroker *stroker = (struct dash_stroker *)str; + VGfloat sum_length = 0; + VGint i; + VGint idash = 0; + VGfloat pos = 0; + VGfloat elen = 0; + VGfloat doffset = stroker->dash_phase; + VGfloat estart = 0; + VGfloat estop = 0; + VGfloat cline[4]; + struct stroke_iterator it; + VGfloat prev[2]; + VGfloat move_to_pos[2]; + VGfloat line_to_pos[2]; + + VGboolean has_move_to = VG_FALSE; + + stroke_flat_iterator(&it, stroker->base.segments, + stroker->base.control_points); + + stroke_itr_coords(&it, prev); + move_to_pos[0] = prev[0]; + move_to_pos[1] = prev[1]; + + debug_assert(stroker->dash_pattern_num > 0); + + for (i = 0; i < stroker->dash_pattern_num; ++i) { + sum_length += dash_pattern(stroker, i); + } + + if (floatIsZero(sum_length)) { + return; + } + + doffset -= floorf(doffset / sum_length) * sum_length; + + while (!floatIsZero(doffset) && doffset >= dash_pattern(stroker, idash)) { + doffset -= dash_pattern(stroker, idash); + idash = (idash + 1) % stroker->dash_pattern_num; + } + + while (it.has_next(&it)) { + VGPathCommand cmd; + VGfloat coords[8]; + VGboolean done; + + it.next(&it); + cmd = stroke_itr_command(&it); + stroke_itr_coords(&it, coords); + + debug_assert(cmd == VG_LINE_TO_ABS); + cline[0] = prev[0]; + cline[1] = prev[1]; + cline[2] = coords[0]; + cline[3] = coords[1]; + + elen = line_lengthv(cline); + + estop = estart + elen; + + done = pos >= estop; + while (!done) { + VGfloat p2[2]; + + VGint idash_incr = 0; + VGboolean has_offset = doffset > 0; + VGfloat dpos = pos + dash_pattern(stroker, idash) - doffset - estart; + + debug_assert(dpos >= 0); + + if (dpos > elen) { /* dash extends this line */ + doffset = dash_pattern(stroker, idash) - (dpos - elen); + pos = estop; + done = VG_TRUE; + p2[0] = cline[2]; + p2[1] = cline[3]; + } else { /* Dash is on this line */ + line_point_at(cline, dpos/elen, p2); + pos = dpos + estart; + done = pos >= estop; + idash_incr = 1; + doffset = 0; + } + + if (idash % 2 == 0) { + line_to_pos[0] = p2[0]; + line_to_pos[1] = p2[1]; + + if (!has_offset || !has_move_to) { + stroker_move_to(&stroker->stroker, move_to_pos[0], move_to_pos[1]); + has_move_to = VG_TRUE; + } + stroker_line_to(&stroker->stroker, line_to_pos[0], line_to_pos[1]); + } else { + move_to_pos[0] = p2[0]; + move_to_pos[1] = p2[1]; + } + + idash = (idash + idash_incr) % stroker->dash_pattern_num; + } + + estart = estop; + prev[0] = coords[0]; + prev[1] = coords[1]; + } + + if (it.curve_poly) { + polygon_destroy(it.curve_poly); + it.curve_poly = 0; + } + + stroker->base.path = stroker->stroker.path; +} + +static void default_begin(struct stroker *stroker) +{ + array_reset(stroker->segments); + array_reset(stroker->control_points); +} + +static void default_end(struct stroker *stroker) +{ + if (stroker->segments->num_elements > 0) + stroker->process_subpath(stroker); +} + + +static void dash_stroker_begin(struct stroker *stroker) +{ + struct dash_stroker *dasher = + (struct dash_stroker *)stroker; + + default_begin(&dasher->stroker); + default_begin(stroker); +} + +static void dash_stroker_end(struct stroker *stroker) +{ + struct dash_stroker *dasher = + (struct dash_stroker *)stroker; + + default_end(stroker); + default_end(&dasher->stroker); +} + +void stroker_init(struct stroker *stroker, + struct vg_state *state) +{ + stroker->stroke_width = state->stroke.line_width.f; + stroker->miter_limit = state->stroke.miter_limit.f; + stroker->cap_style = state->stroke.cap_style; + stroker->join_style = state->stroke.join_style; + + stroker->begin = default_begin; + stroker->process_subpath = stroker_process_subpath; + stroker->end = default_end; + + stroker->segments = array_create(sizeof(VGubyte)); + stroker->control_points = array_create(sizeof(VGfloat)); + + stroker->back1_x = 0; + stroker->back1_y = 0; + stroker->back2_x = 0; + stroker->back2_y = 0; + + stroker->path = path_create(VG_PATH_DATATYPE_F, 1.0f, 0.0f, + 0, 0, VG_PATH_CAPABILITY_ALL); + + stroker->last_cmd = VG_CLOSE_PATH; +} + +void dash_stroker_init(struct stroker *str, + struct vg_state *state) +{ + struct dash_stroker *stroker = (struct dash_stroker *)str; + int i; + + stroker_init(str, state); + stroker_init(&stroker->stroker, state); + + { + int real_num = state->stroke.dash_pattern_num; + if (real_num % 2)/* if odd, ignore the last one */ + --real_num; + for (i = 0; i < real_num; ++i) + stroker->dash_pattern[i] = state->stroke.dash_pattern[i].f; + stroker->dash_pattern_num = real_num; + } + + stroker->dash_phase = state->stroke.dash_phase.f; + stroker->dash_phase_reset = state->stroke.dash_phase_reset; + + stroker->base.begin = dash_stroker_begin; + stroker->base.process_subpath = dash_stroker_process_subpath; + stroker->base.end = dash_stroker_end; + path_destroy(stroker->base.path); + stroker->base.path = NULL; +} + +void stroker_begin(struct stroker *stroker) +{ + stroker->begin(stroker); +} + +void stroker_end(struct stroker *stroker) +{ + stroker->end(stroker); +} + +void stroker_cleanup(struct stroker *stroker) +{ + array_destroy(stroker->segments); + array_destroy(stroker->control_points); +} + +void dash_stroker_cleanup(struct dash_stroker *stroker) +{ + /* if stroker->base.path is null means we never + * processed a valid path so delete the temp one + * we already created */ + if (!stroker->base.path) + path_destroy(stroker->stroker.path); + stroker_cleanup(&stroker->stroker); + stroker_cleanup((struct stroker*)stroker); +} diff --git a/src/gallium/state_trackers/vega/stroker.h b/src/gallium/state_trackers/vega/stroker.h new file mode 100644 index 00000000000..36543cd9237 --- /dev/null +++ b/src/gallium/state_trackers/vega/stroker.h @@ -0,0 +1,89 @@ +/************************************************************************** + * + * 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 STROKER_H +#define STROKER_H + +#include "VG/openvg.h" +#include "api_consts.h" + +struct path; +struct vg_state; +struct array; + +struct stroker { + void (*begin)(struct stroker *stroker); + void (*process_subpath)(struct stroker *stroker); + void (*end)(struct stroker *stroker); + + struct array *segments; + struct array *control_points; + struct path *path; + + VGfloat back1_x, back1_y; + VGfloat back2_x, back2_y; + + VGfloat stroke_width; + VGfloat miter_limit; + VGCapStyle cap_style; + VGJoinStyle join_style; + + VGPathCommand last_cmd; +}; + +struct dash_stroker { + struct stroker base; + + struct stroker stroker; + + VGfloat dash_pattern[VEGA_MAX_DASH_COUNT]; + VGint dash_pattern_num; + VGfloat dash_phase; + VGboolean dash_phase_reset; +}; + +void stroker_init(struct stroker *stroker, + struct vg_state *state); +void dash_stroker_init(struct stroker *stroker, + struct vg_state *state); +void dash_stroker_cleanup(struct dash_stroker *stroker); +void stroker_cleanup(struct stroker *stroker); + +void stroker_begin(struct stroker *stroker); +void stroker_move_to(struct stroker *stroker, VGfloat x, VGfloat y); +void stroker_line_to(struct stroker *stroker, VGfloat x, VGfloat y); +void stroker_curve_to(struct stroker *stroker, VGfloat px1, VGfloat py1, + VGfloat px2, VGfloat py2, + VGfloat x, VGfloat y); +void stroker_end(struct stroker *stroker); + +void stroker_emit_move_to(struct stroker *stroker, VGfloat x, VGfloat y); +void stroker_emit_line_to(struct stroker *stroker, VGfloat x, VGfloat y); +void stroker_emit_curve_to(struct stroker *stroker, VGfloat px1, VGfloat py1, + VGfloat px2, VGfloat py2, + VGfloat x, VGfloat y); + +#endif diff --git a/src/gallium/state_trackers/vega/util_array.h b/src/gallium/state_trackers/vega/util_array.h new file mode 100644 index 00000000000..4343dfe36e2 --- /dev/null +++ b/src/gallium/state_trackers/vega/util_array.h @@ -0,0 +1,122 @@ +/************************************************************************** + * + * 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 UTIL_ARRAY_H +#define UTIL_ARRAY_H + +#include "util/u_memory.h" + +#define DEFAULT_ARRAY_SIZE 256 + +struct array { + VGint datatype_size; + void *data; + VGint size; + VGint num_elements; +}; + +static INLINE struct array *array_create(VGint datatype_size) +{ + struct array *array = CALLOC_STRUCT(array); + array->datatype_size = datatype_size; + + array->size = DEFAULT_ARRAY_SIZE; + array->data = malloc(array->size * array->datatype_size); + + return array; +} + + +static INLINE struct array *array_create_size(VGint datatype_size, VGint size) +{ + struct array *array = CALLOC_STRUCT(array); + array->datatype_size = datatype_size; + + array->size = size; + array->data = malloc(array->size * array->datatype_size); + + return array; +} + +static INLINE void array_destroy(struct array *array) +{ + if (array) + free(array->data); + free(array); +} + +static INLINE void array_resize(struct array *array, int num) +{ + VGint size = array->datatype_size * num; + void *data = malloc(size); + memcpy(data, array->data, array->size * array->datatype_size); + free(array->data); + array->data = data; + array->size = num; + array->num_elements = (array->num_elements > num) ? num : + array->num_elements; +} + +static INLINE void array_append_data(struct array *array, + const void *data, int num_elements) +{ + VGbyte *adata; + + while (array->num_elements + num_elements > array->size) { + array_resize(array, (array->num_elements + num_elements) * 1.5); + } + adata = (VGbyte *)array->data; + memcpy(adata + (array->num_elements * array->datatype_size), data, + num_elements * array->datatype_size); + array->num_elements += num_elements; +} + +static INLINE void array_change_data(struct array *array, + const void *data, + int start_idx, + int num_elements) +{ + VGbyte *adata = (VGbyte *)array->data; + memcpy(adata + (start_idx * array->datatype_size), data, + num_elements * array->datatype_size); +} + +static INLINE void array_remove_element(struct array *array, + int idx) +{ + VGbyte *adata = (VGbyte *)array->data; + memmove(adata + (idx * array->datatype_size), + adata + ((idx + 1) * array->datatype_size), + (array->num_elements - idx - 1) * array->datatype_size); + --array->num_elements; +} + +static INLINE void array_reset(struct array *array) +{ + array->num_elements = 0; +} + +#endif diff --git a/src/gallium/state_trackers/vega/vg_context.c b/src/gallium/state_trackers/vega/vg_context.c new file mode 100644 index 00000000000..e0ff02f3a99 --- /dev/null +++ b/src/gallium/state_trackers/vega/vg_context.c @@ -0,0 +1,543 @@ +/************************************************************************** + * + * 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 "vg_context.h" + +#include "paint.h" +#include "renderer.h" +#include "shaders_cache.h" +#include "shader.h" +#include "asm_util.h" +#include "st_inlines.h" + +#include "pipe/p_context.h" +#include "pipe/p_inlines.h" +#include "pipe/p_shader_tokens.h" + +#include "cso_cache/cso_context.h" + +#include "util/u_simple_shaders.h" +#include "util/u_memory.h" +#include "util/u_blit.h" + +struct vg_context *_vg_context = 0; + +struct vg_context * vg_current_context(void) +{ + return _vg_context; +} + +static void init_clear(struct vg_context *st) +{ + struct pipe_context *pipe = st->pipe; + + /* rasterizer state: bypass clipping */ + memset(&st->clear.raster, 0, sizeof(st->clear.raster)); + st->clear.raster.gl_rasterization_rules = 1; + + /* fragment shader state: color pass-through program */ + st->clear.fs = + util_make_fragment_passthrough_shader(pipe); +} +void vg_set_current_context(struct vg_context *ctx) +{ + _vg_context = ctx; +} + +struct vg_context * vg_create_context(struct pipe_context *pipe, + const void *visual, + struct vg_context *share) +{ + struct vg_context *ctx; + + ctx = CALLOC_STRUCT(vg_context); + + ctx->pipe = pipe; + + vg_init_state(&ctx->state.vg); + ctx->state.dirty = ALL_DIRTY; + + ctx->cso_context = cso_create_context(pipe); + + init_clear(ctx); + + ctx->default_paint = paint_create(ctx); + ctx->state.vg.stroke_paint = ctx->default_paint; + ctx->state.vg.fill_paint = ctx->default_paint; + + + ctx->mask.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + ctx->mask.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + ctx->mask.sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + ctx->mask.sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; + ctx->mask.sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; + ctx->mask.sampler.normalized_coords = 0; + + ctx->blend_sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + ctx->blend_sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + ctx->blend_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + ctx->blend_sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; + ctx->blend_sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; + ctx->blend_sampler.normalized_coords = 0; + + vg_set_error(ctx, VG_NO_ERROR); + + ctx->owned_objects[VG_OBJECT_PAINT] = cso_hash_create(); + ctx->owned_objects[VG_OBJECT_IMAGE] = cso_hash_create(); + ctx->owned_objects[VG_OBJECT_MASK] = cso_hash_create(); + ctx->owned_objects[VG_OBJECT_FONT] = cso_hash_create(); + ctx->owned_objects[VG_OBJECT_PATH] = cso_hash_create(); + + ctx->renderer = renderer_create(ctx); + ctx->sc = shaders_cache_create(ctx); + ctx->shader = shader_create(ctx); + + ctx->blit = util_create_blit(ctx->pipe, ctx->cso_context); + + return ctx; +} + +void vg_destroy_context(struct vg_context *ctx) +{ + struct pipe_constant_buffer *cbuf = &ctx->mask.cbuf; + struct pipe_constant_buffer *vsbuf = &ctx->vs_const_buffer; + + util_destroy_blit(ctx->blit); + renderer_destroy(ctx->renderer); + shaders_cache_destroy(ctx->sc); + shader_destroy(ctx->shader); + paint_destroy(ctx->default_paint); + + if (cbuf && cbuf->buffer) + pipe_buffer_reference(&cbuf->buffer, NULL); + + if (vsbuf && vsbuf->buffer) + pipe_buffer_reference(&vsbuf->buffer, NULL); + + if (ctx->clear.fs) { + cso_delete_fragment_shader(ctx->cso_context, ctx->clear.fs); + ctx->clear.fs = NULL; + } + + if (ctx->plain_vs) { + vg_shader_destroy(ctx, ctx->plain_vs); + ctx->plain_vs = NULL; + } + if (ctx->clear_vs) { + vg_shader_destroy(ctx, ctx->clear_vs); + ctx->clear_vs = NULL; + } + if (ctx->texture_vs) { + vg_shader_destroy(ctx, ctx->texture_vs); + ctx->texture_vs = NULL; + } + + if (ctx->pass_through_depth_fs) + vg_shader_destroy(ctx, ctx->pass_through_depth_fs); + if (ctx->mask.union_fs) + vg_shader_destroy(ctx, ctx->mask.union_fs); + if (ctx->mask.intersect_fs) + vg_shader_destroy(ctx, ctx->mask.intersect_fs); + if (ctx->mask.subtract_fs) + vg_shader_destroy(ctx, ctx->mask.subtract_fs); + if (ctx->mask.set_fs) + vg_shader_destroy(ctx, ctx->mask.set_fs); + + cso_release_all(ctx->cso_context); + cso_destroy_context(ctx->cso_context); + + cso_hash_delete(ctx->owned_objects[VG_OBJECT_PAINT]); + cso_hash_delete(ctx->owned_objects[VG_OBJECT_IMAGE]); + cso_hash_delete(ctx->owned_objects[VG_OBJECT_MASK]); + cso_hash_delete(ctx->owned_objects[VG_OBJECT_FONT]); + cso_hash_delete(ctx->owned_objects[VG_OBJECT_PATH]); + + free(ctx); +} + +void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_object_type type) +{ + obj->type = type; + obj->ctx = ctx; +} + +VGboolean vg_context_is_object_valid(struct vg_context *ctx, + enum vg_object_type type, + void *ptr) +{ + if (ctx) { + struct cso_hash *hash = ctx->owned_objects[type]; + if (!hash) + return VG_FALSE; + return cso_hash_contains(hash, (unsigned)(long)ptr); + } + return VG_FALSE; +} + +void vg_context_add_object(struct vg_context *ctx, + enum vg_object_type type, + void *ptr) +{ + if (ctx) { + struct cso_hash *hash = ctx->owned_objects[type]; + if (!hash) + return; + cso_hash_insert(hash, (unsigned)(long)ptr, ptr); + } +} + +void vg_context_remove_object(struct vg_context *ctx, + enum vg_object_type type, + void *ptr) +{ + if (ctx) { + struct cso_hash *hash = ctx->owned_objects[type]; + if (!hash) + return; + cso_hash_take(hash, (unsigned)(long)ptr); + } +} + +static void update_clip_state(struct vg_context *ctx) +{ + struct pipe_depth_stencil_alpha_state *dsa = &ctx->state.g3d.dsa; + struct vg_state *state = &ctx->state.vg; + + memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); + + if (state->scissoring) { + struct pipe_blend_state *blend = &ctx->state.g3d.blend; + struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; + dsa->depth.writemask = 1;/*glDepthMask(TRUE);*/ + dsa->depth.func = PIPE_FUNC_ALWAYS; + dsa->depth.enabled = 1; + + cso_save_blend(ctx->cso_context); + cso_save_fragment_shader(ctx->cso_context); + /* set a passthrough shader */ + if (!ctx->pass_through_depth_fs) + ctx->pass_through_depth_fs = shader_create_from_text(ctx->pipe, + pass_through_depth_asm, + 40, + PIPE_SHADER_FRAGMENT); + cso_set_fragment_shader_handle(ctx->cso_context, + ctx->pass_through_depth_fs->driver); + cso_set_depth_stencil_alpha(ctx->cso_context, dsa); + + ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0, 0); + + /* disable color writes */ + blend->colormask = 0; /*disable colorwrites*/ + cso_set_blend(ctx->cso_context, blend); + + /* enable scissoring */ + for (int i = 0; i < state->scissor_rects_num; ++i) { + const float x = state->scissor_rects[i * 4 + 0].f; + const float y = state->scissor_rects[i * 4 + 1].f; + const float width = state->scissor_rects[i * 4 + 2].f; + const float height = state->scissor_rects[i * 4 + 3].f; + VGfloat minx, miny, maxx, maxy; + + minx = 0; + miny = 0; + maxx = fb->width; + maxy = fb->height; + + if (x > minx) + minx = x; + if (y > miny) + miny = y; + + if (x + width < maxx) + maxx = x + width; + if (y + height < maxy) + maxy = y + height; + + /* check for null space */ + if (minx >= maxx || miny >= maxy) + minx = miny = maxx = maxy = 0; + + /*glClear(GL_DEPTH_BUFFER_BIT);*/ + renderer_draw_quad(ctx->renderer, minx, miny, maxx, maxy, 0.0f); + } + + blend->colormask = 1; /*enable colorwrites*/ + cso_restore_blend(ctx->cso_context); + cso_restore_fragment_shader(ctx->cso_context); + + dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */ + dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/ + dsa->depth.func = PIPE_FUNC_GEQUAL; + } +} + +void vg_validate_state(struct vg_context *ctx) +{ + if ((ctx->state.dirty & BLEND_DIRTY)) { + struct pipe_blend_state *blend = &ctx->state.g3d.blend; + memset(blend, 0, sizeof(struct pipe_blend_state)); + blend->blend_enable = 1; + blend->colormask |= PIPE_MASK_R; + blend->colormask |= PIPE_MASK_G; + blend->colormask |= PIPE_MASK_B; + blend->colormask |= PIPE_MASK_A; + + switch (ctx->state.vg.blend_mode) { + case VG_BLEND_SRC: + blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend->rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend->alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + break; + case VG_BLEND_SRC_OVER: + blend->rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; + blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend->rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; + blend->alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; + break; + case VG_BLEND_DST_OVER: + blend->rgb_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA; + blend->alpha_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA; + blend->rgb_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA; + blend->alpha_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA; + break; + case VG_BLEND_SRC_IN: + blend->rgb_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; + blend->alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; + blend->rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend->alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + break; + case VG_BLEND_DST_IN: + blend->rgb_src_factor = PIPE_BLENDFACTOR_ZERO; + blend->alpha_src_factor = PIPE_BLENDFACTOR_ZERO; + blend->rgb_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; + blend->alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; + break; + case VG_BLEND_MULTIPLY: + case VG_BLEND_SCREEN: + case VG_BLEND_DARKEN: + case VG_BLEND_LIGHTEN: + blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend->rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend->alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + break; + case VG_BLEND_ADDITIVE: + blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend->rgb_dst_factor = PIPE_BLENDFACTOR_ONE; + blend->alpha_dst_factor = PIPE_BLENDFACTOR_ONE; + break; + default: + assert(!"not implemented blend mode"); + } + cso_set_blend(ctx->cso_context, &ctx->state.g3d.blend); + } + if ((ctx->state.dirty & RASTERIZER_DIRTY)) { + struct pipe_rasterizer_state *raster = &ctx->state.g3d.rasterizer; + memset(raster, 0, sizeof(struct pipe_rasterizer_state)); + raster->gl_rasterization_rules = 1; + cso_set_rasterizer(ctx->cso_context, &ctx->state.g3d.rasterizer); + } + if ((ctx->state.dirty & VIEWPORT_DIRTY)) { + struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; + const VGint param_bytes = 8 * sizeof(VGfloat); + VGfloat vs_consts[8] = { + 2.f/fb->width, 2.f/fb->height, 1, 1, + -1, -1, 0, 0 + }; + struct pipe_constant_buffer *cbuf = &ctx->vs_const_buffer; + + vg_set_viewport(ctx, VEGA_Y0_BOTTOM); + + pipe_buffer_reference(&cbuf->buffer, NULL); + cbuf->buffer = pipe_buffer_create(ctx->pipe->screen, 16, + PIPE_BUFFER_USAGE_CONSTANT, + param_bytes); + + if (cbuf->buffer) { + st_no_flush_pipe_buffer_write(ctx, cbuf->buffer, + 0, param_bytes, vs_consts); + } + ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, cbuf); + } + if ((ctx->state.dirty & VS_DIRTY)) { + cso_set_vertex_shader_handle(ctx->cso_context, + vg_plain_vs(ctx)); + } + + /* must be last because it renders to the depth buffer*/ + if ((ctx->state.dirty & DEPTH_STENCIL_DIRTY)) { + update_clip_state(ctx); + cso_set_depth_stencil_alpha(ctx->cso_context, &ctx->state.g3d.dsa); + } + + shader_set_masking(ctx->shader, ctx->state.vg.masking); + shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode); + + ctx->state.dirty = NONE_DIRTY; +} + +VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type) +{ + struct vg_object *obj = ptr; + if (ptr && is_aligned(obj) && obj->type == type) + return VG_TRUE; + else + return VG_FALSE; +} + +void vg_set_error(struct vg_context *ctx, + VGErrorCode code) +{ + /*vgGetError returns the oldest error code provided by + * an API call on the current context since the previous + * call to vgGetError on that context (or since the creation + of the context).*/ + if (ctx->_error == VG_NO_ERROR) + ctx->_error = code; +} + +void vg_prepare_blend_surface(struct vg_context *ctx) +{ + struct pipe_surface *dest_surface = NULL; + struct pipe_context *pipe = ctx->pipe; + struct st_framebuffer *stfb = ctx->draw_buffer; + struct st_renderbuffer *strb = stfb->strb; + + /* first finish all pending rendering */ + vgFinish(); + + dest_surface = pipe->screen->get_tex_surface(pipe->screen, + stfb->blend_texture, + 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_WRITE); + /* flip it, because we want to use it as a sampler */ + util_blit_pixels_tex(ctx->blit, + strb->texture, + 0, strb->height, + strb->width, 0, + dest_surface, + 0, 0, + strb->width, strb->height, + 0.0, PIPE_TEX_MIPFILTER_NEAREST); + + if (dest_surface) + pipe_surface_reference(&dest_surface, NULL); + + /* make sure it's complete */ + vgFinish(); +} + + +void vg_prepare_blend_surface_from_mask(struct vg_context *ctx) +{ + struct pipe_surface *dest_surface = NULL; + struct pipe_context *pipe = ctx->pipe; + struct st_framebuffer *stfb = ctx->draw_buffer; + struct st_renderbuffer *strb = stfb->strb; + + vg_validate_state(ctx); + + /* first finish all pending rendering */ + vgFinish(); + + dest_surface = pipe->screen->get_tex_surface(pipe->screen, + stfb->blend_texture, + 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_WRITE); + + /* flip it, because we want to use it as a sampler */ + util_blit_pixels_tex(ctx->blit, + stfb->alpha_mask, + 0, strb->height, + strb->width, 0, + dest_surface, + 0, 0, + strb->width, strb->height, + 0.0, PIPE_TEX_MIPFILTER_NEAREST); + + /* make sure it's complete */ + vgFinish(); + + if (dest_surface) + pipe_surface_reference(&dest_surface, NULL); +} + +void * vg_plain_vs(struct vg_context *ctx) +{ + if (!ctx->plain_vs) { + ctx->plain_vs = shader_create_from_text(ctx->pipe, + vs_plain_asm, + 200, + PIPE_SHADER_VERTEX); + } + + return ctx->plain_vs->driver; +} + + +void * vg_clear_vs(struct vg_context *ctx) +{ + if (!ctx->clear_vs) { + ctx->clear_vs = shader_create_from_text(ctx->pipe, + vs_clear_asm, + 200, + PIPE_SHADER_VERTEX); + } + + return ctx->clear_vs->driver; +} + +void * vg_texture_vs(struct vg_context *ctx) +{ + if (!ctx->texture_vs) { + ctx->texture_vs = shader_create_from_text(ctx->pipe, + vs_texture_asm, + 200, + PIPE_SHADER_VERTEX); + } + + return ctx->texture_vs->driver; +} + +void vg_set_viewport(struct vg_context *ctx, VegaOrientation orientation) +{ + struct pipe_viewport_state viewport; + struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; + VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f; + + viewport.scale[0] = fb->width / 2.f; + viewport.scale[1] = fb->height / y_scale; + viewport.scale[2] = 1.0; + viewport.scale[3] = 1.0; + viewport.translate[0] = fb->width / 2.f; + viewport.translate[1] = fb->height / 2.f; + viewport.translate[2] = 0.0; + viewport.translate[3] = 0.0; + + cso_set_viewport(ctx->cso_context, &viewport); +} diff --git a/src/gallium/state_trackers/vega/vg_context.h b/src/gallium/state_trackers/vega/vg_context.h new file mode 100644 index 00000000000..ccc8889c8c5 --- /dev/null +++ b/src/gallium/state_trackers/vega/vg_context.h @@ -0,0 +1,292 @@ +/************************************************************************** + * + * 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 VG_CONTEXT_H +#define VG_CONTEXT_H + +#include "vg_state.h" + +#include "pipe/p_format.h" +#include "pipe/p_state.h" +#include "util/u_pointer.h" +#include "util/u_math.h" + +#include "cso_cache/cso_hash.h" +#include "cso_cache/cso_context.h" + +struct renderer; +struct shaders_cache; +struct shader; +struct vg_shader; + +struct st_renderbuffer { + enum pipe_format format; + struct pipe_surface *surface; + struct pipe_texture *texture; + VGint width, height; +}; + +struct st_framebuffer { + VGint init_width, init_height; + struct st_renderbuffer *strb; + struct st_renderbuffer *dsrb; + + struct pipe_texture *alpha_mask; + + struct pipe_texture *blend_texture; + + void *privateData; +}; + +enum vg_object_type { + VG_OBJECT_UNKNOWN = 0, + VG_OBJECT_PAINT, + VG_OBJECT_IMAGE, + VG_OBJECT_MASK, + VG_OBJECT_FONT, + VG_OBJECT_PATH, + + VG_OBJECT_LAST +}; +enum dirty_state { + NONE_DIRTY = 0<<0, + BLEND_DIRTY = 1<<1, + RASTERIZER_DIRTY = 1<<2, + VIEWPORT_DIRTY = 1<<3, + VS_DIRTY = 1<<4, + DEPTH_STENCIL_DIRTY = 1<<5, + ALL_DIRTY = BLEND_DIRTY | RASTERIZER_DIRTY | + VIEWPORT_DIRTY | VS_DIRTY | DEPTH_STENCIL_DIRTY +}; + +struct vg_context +{ + struct pipe_context *pipe; + + struct { + struct vg_state vg; + struct { + struct pipe_blend_state blend; + struct pipe_rasterizer_state rasterizer; + struct pipe_shader_state vs_state; + struct pipe_depth_stencil_alpha_state dsa; + struct pipe_framebuffer_state fb; + } g3d; + VGbitfield dirty; + } state; + + VGErrorCode _error; + + struct st_framebuffer *draw_buffer; + + struct cso_hash *owned_objects[VG_OBJECT_LAST]; + + struct { + struct pipe_shader_state vert_shader; + struct pipe_shader_state frag_shader; + struct pipe_rasterizer_state raster; + void *fs; + float vertices[4][2][4]; /**< vertex pos + color */ + } clear; + + struct { + struct pipe_constant_buffer cbuf; + struct pipe_sampler_state sampler; + + struct vg_shader *union_fs; + struct vg_shader *intersect_fs; + struct vg_shader *subtract_fs; + struct vg_shader *set_fs; + } mask; + + struct vg_shader *pass_through_depth_fs; + + struct cso_context *cso_context; + + struct pipe_buffer *stencil_quad; + VGfloat stencil_vertices[4][2][4]; + + struct renderer *renderer; + struct shaders_cache *sc; + struct shader *shader; + + struct pipe_sampler_state blend_sampler; + struct { + struct pipe_constant_buffer buffer; + void *color_matrix_fs; + } filter; + struct vg_paint *default_paint; + + struct blit_state *blit; + + struct vg_shader *plain_vs; + struct vg_shader *clear_vs; + struct vg_shader *texture_vs; + struct pipe_constant_buffer vs_const_buffer; +}; + +struct vg_object { + enum vg_object_type type; + struct vg_context *ctx; +}; +void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_object_type type); +VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type); + +struct vg_context *vg_create_context(struct pipe_context *pipe, + const void *visual, + struct vg_context *share); +void vg_destroy_context(struct vg_context *ctx); +struct vg_context *vg_current_context(void); +void vg_set_current_context(struct vg_context *ctx); + +VGboolean vg_context_is_object_valid(struct vg_context *ctx, + enum vg_object_type type, + void *ptr); +void vg_context_add_object(struct vg_context *ctx, + enum vg_object_type type, + void *ptr); +void vg_context_remove_object(struct vg_context *ctx, + enum vg_object_type type, + void *ptr); + +void vg_validate_state(struct vg_context *ctx); + +void vg_set_error(struct vg_context *ctx, + VGErrorCode code); + +void vg_prepare_blend_surface(struct vg_context *ctx); +void vg_prepare_blend_surface_from_mask(struct vg_context *ctx); + + +static INLINE VGboolean is_aligned_to(const void *ptr, VGbyte alignment) +{ + void *aligned = align_pointer(ptr, alignment); + return (ptr == aligned) ? VG_TRUE : VG_FALSE; +} + +static INLINE VGboolean is_aligned(const void *ptr) +{ + return is_aligned_to(ptr, 4); +} + +static INLINE void vg_shift_rectx(VGfloat coords[4], + const VGfloat *bounds, + const VGfloat shift) +{ + coords[0] += shift; + coords[2] -= shift; + if (bounds) { + coords[2] = MIN2(coords[2], bounds[2]); + /* bound x/y + width/height */ + if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) { + coords[2] = (bounds[0] + bounds[2]) - coords[0]; + } + } +} + +static INLINE void vg_shift_recty(VGfloat coords[4], + const VGfloat *bounds, + const VGfloat shift) +{ + coords[1] += shift; + coords[3] -= shift; + if (bounds) { + coords[3] = MIN2(coords[3], bounds[3]); + if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) { + coords[3] = (bounds[1] + bounds[3]) - coords[1]; + } + } +} + +static INLINE void vg_bound_rect(VGfloat coords[4], + const VGfloat bounds[4], + VGfloat shift[4]) +{ + /* if outside the bounds */ + if (coords[0] > (bounds[0] + bounds[2]) || + coords[1] > (bounds[1] + bounds[3]) || + (coords[0] + coords[2]) < bounds[0] || + (coords[1] + coords[3]) < bounds[1]) { + coords[0] = 0.f; + coords[1] = 0.f; + coords[2] = 0.f; + coords[3] = 0.f; + shift[0] = 0.f; + shift[1] = 0.f; + return; + } + + /* bound x */ + if (coords[0] < bounds[0]) { + shift[0] = bounds[0] - coords[0]; + coords[2] -= shift[0]; + coords[0] = bounds[0]; + } else + shift[0] = 0.f; + + /* bound y */ + if (coords[1] < bounds[1]) { + shift[1] = bounds[1] - coords[1]; + coords[3] -= shift[1]; + coords[1] = bounds[1]; + } else + shift[1] = 0.f; + + shift[2] = bounds[2] - coords[2]; + shift[3] = bounds[3] - coords[3]; + /* bound width/height */ + coords[2] = MIN2(coords[2], bounds[2]); + coords[3] = MIN2(coords[3], bounds[3]); + + /* bound x/y + width/height */ + if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) { + coords[2] = (bounds[0] + bounds[2]) - coords[0]; + } + if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) { + coords[3] = (bounds[1] + bounds[3]) - coords[1]; + } + + /* if outside the bounds */ + if ((coords[0] + coords[2]) < bounds[0] || + (coords[1] + coords[3]) < bounds[1]) { + coords[0] = 0.f; + coords[1] = 0.f; + coords[2] = 0.f; + coords[3] = 0.f; + return; + } +} + +void *vg_plain_vs(struct vg_context *ctx); +void *vg_clear_vs(struct vg_context *ctx); +void *vg_texture_vs(struct vg_context *ctx); +typedef enum { + VEGA_Y0_TOP, + VEGA_Y0_BOTTOM +} VegaOrientation; +void vg_set_viewport(struct vg_context *ctx, VegaOrientation orientation); + +#endif diff --git a/src/gallium/state_trackers/vega/vg_state.c b/src/gallium/state_trackers/vega/vg_state.c new file mode 100644 index 00000000000..6f6bfdaf7a2 --- /dev/null +++ b/src/gallium/state_trackers/vega/vg_state.c @@ -0,0 +1,124 @@ +/************************************************************************** + * + * 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 "vg_state.h" + +#include <string.h> + +void vg_init_state(struct vg_state *state) +{ + state->matrix_mode = VG_MATRIX_PATH_USER_TO_SURFACE; + state->fill_rule = VG_EVEN_ODD; + state->image_quality = VG_IMAGE_QUALITY_FASTER; + state->rendering_quality = VG_RENDERING_QUALITY_BETTER; + state->blend_mode = VG_BLEND_SRC_OVER; + state->image_mode = VG_DRAW_IMAGE_NORMAL; + + memset(state->scissor_rects, 0, sizeof(state->scissor_rects)); + state->scissor_rects_num = 0; + + state->color_transform = VG_FALSE; + state->color_transform_values[0] = 1.0f; + state->color_transform_values[1] = 1.0f; + state->color_transform_values[2] = 1.0f; + state->color_transform_values[3] = 1.0f; + state->color_transform_values[4] = 0.0f; + state->color_transform_values[5] = 0.0f; + state->color_transform_values[6] = 0.0f; + state->color_transform_values[7] = 0.0f; + + /* Stroke parameters */ + state->stroke.line_width.f = 1.0f; + state->stroke.line_width.i = 1; + state->stroke.cap_style = VG_CAP_BUTT; + state->stroke.join_style = VG_JOIN_MITER; + state->stroke.miter_limit.f = 4.0f; + state->stroke.miter_limit.i = 4; + state->stroke.dash_pattern_num = 0; + state->stroke.dash_phase.f = 0.0f; + state->stroke.dash_phase.i = 0; + state->stroke.dash_phase_reset = VG_FALSE; + + /* Edge fill color for VG_TILE_FILL tiling mode */ + state->tile_fill_color[0] = 0.0f; + state->tile_fill_color[1] = 0.0f; + state->tile_fill_color[2] = 0.0f; + state->tile_fill_color[3] = 0.0f; + + /* Color for vgClear */ + state->clear_color[0] = 0.0f; + state->clear_color[1] = 0.0f; + state->clear_color[2] = 0.0f; + state->clear_color[3] = 0.0f; + + /* Glyph origin */ + state->glyph_origin[0].f = 0.0f; + state->glyph_origin[1].f = 0.0f; + state->glyph_origin[0].i = 0; + state->glyph_origin[1].i = 0; + + /* Enable/disable alpha masking and scissoring */ + state->masking = VG_FALSE; + state->scissoring = VG_FALSE; + + /* Pixel layout information */ + state->pixel_layout = VG_PIXEL_LAYOUT_UNKNOWN; + state->screen_layout = VG_PIXEL_LAYOUT_UNKNOWN; + + /* Source format selection for image filters */ + state->filter_format_linear = VG_FALSE; + state->filter_format_premultiplied = VG_FALSE; + + /* Destination write enable mask for image filters */ + state->filter_channel_mask = (VG_RED | VG_GREEN | VG_BLUE | VG_ALPHA); + + matrix_load_identity(&state->path_user_to_surface_matrix); + matrix_load_identity(&state->image_user_to_surface_matrix); + matrix_load_identity(&state->fill_paint_to_user_matrix); + matrix_load_identity(&state->stroke_paint_to_user_matrix); + matrix_load_identity(&state->glyph_user_to_surface_matrix); +} + +struct matrix *vg_state_matrix(struct vg_state *state) +{ + switch(state->matrix_mode) { + case VG_MATRIX_PATH_USER_TO_SURFACE: + return &state->path_user_to_surface_matrix; + case VG_MATRIX_IMAGE_USER_TO_SURFACE: + return &state->image_user_to_surface_matrix; + case VG_MATRIX_FILL_PAINT_TO_USER: + return &state->fill_paint_to_user_matrix; + case VG_MATRIX_STROKE_PAINT_TO_USER: + return &state->stroke_paint_to_user_matrix; +#ifdef OPENVG_VERSION_1_1 + case VG_MATRIX_GLYPH_USER_TO_SURFACE: + return &state->glyph_user_to_surface_matrix; +#endif + default: + break; + } + return NULL; +} diff --git a/src/gallium/state_trackers/vega/vg_state.h b/src/gallium/state_trackers/vega/vg_state.h new file mode 100644 index 00000000000..ed90689f917 --- /dev/null +++ b/src/gallium/state_trackers/vega/vg_state.h @@ -0,0 +1,109 @@ +/************************************************************************** + * + * 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 VG_STATE_H +#define VG_STATE_H + +#include "VG/openvg.h" + +#include "api_consts.h" +#include "matrix.h" + +struct vg_value +{ + VGfloat f; + VGint i; +}; + +struct vg_state { + /* Mode settings */ + VGMatrixMode matrix_mode; + VGFillRule fill_rule; + VGImageQuality image_quality; + VGRenderingQuality rendering_quality; + VGBlendMode blend_mode; + VGImageMode image_mode; + + /* Scissoring rectangles */ + struct vg_value scissor_rects[32*4]; + VGint scissor_rects_num; + + /* Color Transformation */ + VGboolean color_transform; + VGfloat color_transform_values[8]; + + /* Stroke parameters */ + struct { + struct vg_value line_width; + VGCapStyle cap_style; + VGJoinStyle join_style; + struct vg_value miter_limit; + struct vg_value dash_pattern[VEGA_MAX_DASH_COUNT]; + VGint dash_pattern_num; + struct vg_value dash_phase; + VGboolean dash_phase_reset; + } stroke; + + /* Edge fill color for VG_TILE_FILL tiling mode */ + VGfloat tile_fill_color[4]; + VGint tile_fill_colori[4]; + + /* Color for vgClear */ + VGfloat clear_color[4]; + VGint clear_colori[4]; + + /* Glyph origin */ + struct vg_value glyph_origin[2]; + + /* Enable/disable alpha masking and scissoring */ + VGboolean masking; + VGboolean scissoring; + + /* Pixel layout information */ + VGPixelLayout pixel_layout; + VGPixelLayout screen_layout; + + /* Source format selection for image filters */ + VGboolean filter_format_linear; + VGboolean filter_format_premultiplied; + + /* Destination write enable mask for image filters */ + VGbitfield filter_channel_mask; + + struct matrix path_user_to_surface_matrix; + struct matrix image_user_to_surface_matrix; + struct matrix fill_paint_to_user_matrix; + struct matrix stroke_paint_to_user_matrix; + struct matrix glyph_user_to_surface_matrix; + + struct vg_paint *stroke_paint; + struct vg_paint *fill_paint; +}; + +void vg_init_state(struct vg_state *state); +struct matrix * vg_state_matrix(struct vg_state *state); + +#endif diff --git a/src/gallium/state_trackers/vega/vg_tracker.c b/src/gallium/state_trackers/vega/vg_tracker.c new file mode 100644 index 00000000000..c262ce08fa9 --- /dev/null +++ b/src/gallium/state_trackers/vega/vg_tracker.c @@ -0,0 +1,406 @@ +/************************************************************************** + * + * 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 "vg_context.h" +#include "vg_tracker.h" +#include "mask.h" + +#include "pipe/p_context.h" +#include "pipe/p_inlines.h" +#include "pipe/p_screen.h" +#include "util/u_memory.h" +#include "util/u_math.h" + +static struct pipe_texture * +create_texture(struct pipe_context *pipe, enum pipe_format format, + VGint width, VGint height) +{ + struct pipe_texture templ; + + memset(&templ, 0, sizeof(templ)); + + if (format != PIPE_FORMAT_NONE) { + templ.format = format; + } + else { + templ.format = PIPE_FORMAT_A8R8G8B8_UNORM; + } + + templ.target = PIPE_TEXTURE_2D; + pf_get_block(templ.format, &templ.block); + templ.width[0] = width; + templ.height[0] = height; + templ.depth[0] = 1; + templ.last_level = 0; + + if (pf_get_component_bits(format, PIPE_FORMAT_COMP_S)) { + templ.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; + } else { + templ.tex_usage = (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_RENDER_TARGET | + PIPE_TEXTURE_USAGE_SAMPLER); + } + + return pipe->screen->texture_create(pipe->screen, &templ); +} + +/** + * Allocate a renderbuffer for a an on-screen window (not a user-created + * renderbuffer). The window system code determines the format. + */ +static struct st_renderbuffer * +st_new_renderbuffer_fb(enum pipe_format format) +{ + struct st_renderbuffer *strb; + + strb = CALLOC_STRUCT(st_renderbuffer); + if (!strb) { + /*_vega_error(NULL, VG_OUT_OF_MEMORY, "creating renderbuffer");*/ + return NULL; + } + + strb->format = format; + + return strb; +} + + +/** + * This is called to allocate the original drawing surface, and + * during window resize. + */ +static VGboolean +st_renderbuffer_alloc_storage(struct vg_context * ctx, + struct st_renderbuffer *strb, + VGuint width, VGuint height) +{ + struct pipe_context *pipe = ctx->pipe; + unsigned surface_usage; + + /* Free the old surface and texture + */ + pipe_surface_reference(&strb->surface, NULL); + pipe_texture_reference(&strb->texture, NULL); + + + /* Probably need dedicated flags for surface usage too: + */ + surface_usage = (PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_GPU_WRITE); + + strb->texture = create_texture(pipe, strb->format, + width, height); + + if (!strb->texture) + return FALSE; + + strb->surface = pipe->screen->get_tex_surface(pipe->screen, + strb->texture, + 0, 0, 0, + surface_usage); + strb->width = width; + strb->height = height; + + assert(strb->surface->width == width); + assert(strb->surface->height == height); + + return strb->surface != NULL; +} + +struct vg_context * st_create_context(struct pipe_context *pipe, + const void *visual, + struct vg_context *share) +{ + struct vg_context *ctx = vg_create_context(pipe, visual, share); + /*debug_printf("--------- CREATE CONTEXT %p\n", ctx);*/ + return ctx; +} + +void st_destroy_context(struct vg_context *st) +{ + /*debug_printf("--------- DESTROY CONTEXT %p\n", st);*/ + vg_destroy_context(st); +} + +void st_copy_context_state(struct vg_context *dst, struct vg_context *src, + uint mask) +{ + fprintf(stderr, "FIXME: %s\n", __FUNCTION__); +} + +void st_get_framebuffer_dimensions(struct st_framebuffer *stfb, + uint *width, + uint *height) +{ + *width = stfb->strb->width; + *height = stfb->strb->height; +} + +struct st_framebuffer * st_create_framebuffer(const void *visual, + enum pipe_format colorFormat, + enum pipe_format depthFormat, + enum pipe_format stencilFormat, + uint width, uint height, + void *privateData) +{ + struct st_framebuffer *stfb = CALLOC_STRUCT(st_framebuffer); + if (stfb) { + struct st_renderbuffer *rb = + st_new_renderbuffer_fb(colorFormat); + stfb->strb = rb; +#if 0 + if (doubleBuffer) { + struct st_renderbuffer *rb = + st_new_renderbuffer_fb(colorFormat); + } +#endif + + /* we want to combine the depth/stencil */ + if (stencilFormat == depthFormat) + stfb->dsrb = st_new_renderbuffer_fb(stencilFormat); + else + stfb->dsrb = st_new_renderbuffer_fb(PIPE_FORMAT_S8Z24_UNORM); + + /*### currently we always allocate it but it's possible it's + not necessary if EGL_ALPHA_MASK_SIZE was 0 + */ + stfb->alpha_mask = 0; + + stfb->init_width = width; + stfb->init_height = height; + stfb->privateData = privateData; + } + + return stfb; +} + +static void setup_new_alpha_mask(struct vg_context *ctx, + struct st_framebuffer *stfb, + uint width, uint height) +{ + struct pipe_context *pipe = ctx->pipe; + struct pipe_texture *old_texture = stfb->alpha_mask; + + /* + we use PIPE_FORMAT_A8R8G8B8_UNORM because we want to render to + this texture and use it as a sampler, so while this wastes some + space it makes both of those a lot simpler + */ + stfb->alpha_mask = + create_texture(pipe, PIPE_FORMAT_A8R8G8B8_UNORM, width, height); + + if (!stfb->alpha_mask) { + if (old_texture) + pipe_texture_reference(&old_texture, NULL); + return; + } + + vg_validate_state(ctx); + + /* alpha mask starts with 1.f alpha */ + mask_fill(0, 0, width, height, 1.f); + + /* if we had an old surface copy it over */ + if (old_texture) { + struct pipe_surface *surface = pipe->screen->get_tex_surface( + pipe->screen, + stfb->alpha_mask, + 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_WRITE); + struct pipe_surface *old_surface = pipe->screen->get_tex_surface( + pipe->screen, + old_texture, + 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_READ); + pipe->surface_copy(pipe, + surface, + 0, 0, + old_surface, + 0, 0, + MIN2(old_surface->width, width), + MIN2(old_surface->height, height)); + if (surface) + pipe_surface_reference(&surface, NULL); + if (old_surface) + pipe_surface_reference(&old_surface, NULL); + } + + /* Free the old texture + */ + if (old_texture) + pipe_texture_reference(&old_texture, NULL); +} + +void st_resize_framebuffer(struct st_framebuffer *stfb, + uint width, uint height) +{ + struct vg_context *ctx = vg_current_context(); + struct st_renderbuffer *strb = stfb->strb; + struct pipe_framebuffer_state *state; + + if (!ctx) + return; + + state = &ctx->state.g3d.fb; + + /* If this is a noop, exit early and don't do the clear, etc below. + */ + if (strb->width == width && + strb->height == height && + state->zsbuf) + return; + + if (strb->width != width || strb->height != height) + st_renderbuffer_alloc_storage(ctx, strb, + width, height); + + if (stfb->dsrb->width != width || stfb->dsrb->height != height) + st_renderbuffer_alloc_storage(ctx, stfb->dsrb, + width, height); + + { + VGuint i; + + memset(state, 0, sizeof(struct pipe_framebuffer_state)); + + state->width = width; + state->height = height; + + state->nr_cbufs = 1; + state->cbufs[0] = strb->surface; + for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) + state->cbufs[i] = 0; + + state->zsbuf = stfb->dsrb->surface; + + cso_set_framebuffer(ctx->cso_context, state); + } + + ctx->state.dirty |= VIEWPORT_DIRTY; + ctx->state.dirty |= DEPTH_STENCIL_DIRTY;/*to reset the scissors*/ + + ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, + NULL, 0.0, 0); + + /* we need all the other state already set */ + + setup_new_alpha_mask(ctx, stfb, width, height); + + pipe_texture_reference( &stfb->blend_texture, NULL ); + stfb->blend_texture = create_texture(ctx->pipe, PIPE_FORMAT_A8R8G8B8_UNORM, + width, height); +} + +void st_set_framebuffer_surface(struct st_framebuffer *stfb, + uint surfIndex, struct pipe_surface *surf) +{ + struct st_renderbuffer *rb = stfb->strb; + + /* unreference existing surfaces */ + pipe_surface_reference( &rb->surface, NULL ); + pipe_texture_reference( &rb->texture, NULL ); + + /* reference new ones */ + pipe_surface_reference( &rb->surface, surf ); + pipe_texture_reference( &rb->texture, surf->texture ); + + rb->width = surf->width; + rb->height = surf->height; +} + +int st_get_framebuffer_surface(struct st_framebuffer *stfb, + uint surfIndex, struct pipe_surface **surf) +{ + struct st_renderbuffer *rb = stfb->strb; + *surf = rb->surface; + return VG_TRUE; +} + +int st_get_framebuffer_texture(struct st_framebuffer *stfb, + uint surfIndex, struct pipe_texture **tex) +{ + struct st_renderbuffer *rb = stfb->strb; + *tex = rb->texture; + return VG_TRUE; +} + +void * st_framebuffer_private(struct st_framebuffer *stfb) +{ + return stfb->privateData; +} + +void st_unreference_framebuffer(struct st_framebuffer *stfb) +{ + /* FIXME */ +} + +void st_make_current(struct vg_context *st, + struct st_framebuffer *draw, + struct st_framebuffer *read) +{ + vg_set_current_context(st); + if (st) { + st->draw_buffer = draw; + } +} + +void st_flush(struct vg_context *st, uint pipeFlushFlags, + struct pipe_fence_handle **fence) +{ + st->pipe->flush(st->pipe, pipeFlushFlags, fence); +} + +void st_finish(struct vg_context *st) +{ + struct pipe_fence_handle *fence = NULL; + + st_flush(st, PIPE_FLUSH_RENDER_CACHE, &fence); + + st->pipe->screen->fence_finish(st->pipe->screen, fence, 0); + st->pipe->screen->fence_reference(st->pipe->screen, &fence, NULL); +} + +void st_notify_swapbuffers(struct st_framebuffer *stfb) +{ + struct vg_context *ctx = vg_current_context(); + if (ctx && ctx->draw_buffer == stfb) { + st_flush(ctx, + PIPE_FLUSH_RENDER_CACHE | + PIPE_FLUSH_SWAPBUFFERS | + PIPE_FLUSH_FRAME, + NULL); + } +} + +void st_notify_swapbuffers_complete(struct st_framebuffer *stfb) +{ +} + +int +st_set_teximage(struct pipe_texture *pt, int target) +{ + return 0; +} diff --git a/src/gallium/state_trackers/vega/vg_tracker.h b/src/gallium/state_trackers/vega/vg_tracker.h new file mode 100644 index 00000000000..805c58ccc70 --- /dev/null +++ b/src/gallium/state_trackers/vega/vg_tracker.h @@ -0,0 +1,102 @@ +/************************************************************************** + * + * 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 VG_TRACKER_H +#define VG_TRACKER_H + +#include "VG/openvg.h" + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" + +#define ST_SURFACE_FRONT_LEFT 0 +#define ST_SURFACE_BACK_LEFT 1 +#define ST_SURFACE_FRONT_RIGHT 2 +#define ST_SURFACE_BACK_RIGHT 3 +#define ST_SURFACE_DEPTH 8 + +struct vg_context; +struct st_framebuffer; +struct pipe_context; +struct pipe_fence_handle; +struct pipe_surface; + + +struct vg_context *st_create_context(struct pipe_context *pipe, + const void *visual, + struct vg_context *share); + +void st_destroy_context( struct vg_context *st ); + +void st_copy_context_state(struct vg_context *dst, struct vg_context *src, + uint mask); + +struct st_framebuffer *st_create_framebuffer(const void *visual, + enum pipe_format colorFormat, + enum pipe_format depthFormat, + enum pipe_format stencilFormat, + uint width, uint height, + void *privateData); + +void st_resize_framebuffer(struct st_framebuffer *stfb, + uint width, uint height); + +void st_set_framebuffer_surface(struct st_framebuffer *stfb, + uint surfIndex, struct pipe_surface *surf); + +void st_get_framebuffer_dimensions( struct st_framebuffer *stfb, + uint *width, uint *height); + +int st_set_teximage(struct pipe_texture *pt, int target); + +int st_get_framebuffer_surface(struct st_framebuffer *stfb, + uint surfIndex, struct pipe_surface **surf); + +int st_get_framebuffer_texture(struct st_framebuffer *stfb, + uint surfIndex, struct pipe_texture **tex); + +void *st_framebuffer_private(struct st_framebuffer *stfb); + +void st_unreference_framebuffer(struct st_framebuffer *stfb); + +void st_make_current(struct vg_context *st, + struct st_framebuffer *draw, + struct st_framebuffer *read); + +void st_flush(struct vg_context *st, uint pipeFlushFlags, + struct pipe_fence_handle **fence); +void st_finish(struct vg_context *st); + +void st_notify_swapbuffers(struct st_framebuffer *stfb); +void st_notify_swapbuffers_complete(struct st_framebuffer *stfb); + + +/** Generic function type */ +typedef void (*st_proc)(); + +st_proc st_get_proc_address(const char *procname); + +#endif diff --git a/src/gallium/state_trackers/vega/vg_translate.c b/src/gallium/state_trackers/vega/vg_translate.c new file mode 100644 index 00000000000..00e07647062 --- /dev/null +++ b/src/gallium/state_trackers/vega/vg_translate.c @@ -0,0 +1,1030 @@ +/************************************************************************** + * + * 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 "vg_translate.h" + +#include "pipe/p_format.h" +#include "util/u_pack_color.h" + +void _vega_pack_rgba_span_float(struct vg_context *ctx, + VGuint n, VGfloat rgba[][4], + VGImageFormat dstFormat, + void *dstAddr) +{ + VGint i; + + switch (dstFormat) { + case VG_sRGBX_8888: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = 255; + dst[i] = r << 24 | g << 16 | b << 8 | a; + } + return; + } + break; + case VG_sRGBA_8888: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + dst[i] = r << 24 | g << 16 | b << 8 | a; + } + return; + } + break; + case VG_sRGBA_8888_PRE: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + dst[i] = r << 24 | g << 16 | b << 8 | a; + } + return; + } + break; + case VG_sRGB_565: { + VGshort *dst = (VGshort *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + r = (r / 255.0) * 32; + g = (g / 255.0) * 32; + b = (b / 255.0) * 32; + + dst[i] = b | g << 5 | r << 11; + } + return; + } + break; + case VG_sRGBA_5551: { + VGshort *dst = (VGshort *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b, a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + r = (r / 255.0) * 32; + g = (g / 255.0) * 32; + b = (b / 255.0) * 32; + a = (a / 255.0); + + dst[i] = a | b << 1 | g << 6 | r << 11; + } + return; + } + break; + case VG_sRGBA_4444: { + VGshort *dst = (VGshort *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b, a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + r = (r / 255.0) * 16; + g = (g / 255.0) * 16; + b = (b / 255.0) * 16; + a = (a / 255.0) * 16; + + dst[i] = a | b << 4 | g << 8 | r << 12; + } + return; + } + break; + case VG_sL_8: { + VGubyte *dst = (VGubyte *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b, a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + + dst[i] = a; + } + return; + } + break; + case VG_lRGBX_8888: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = 255; + dst[i] = r << 24 | g << 16 | b << 8 | a; + } + return; + } + break; + case VG_lRGBA_8888: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + dst[i] = r << 24 | g << 16 | b << 8 | a; + } + return; + } + case VG_lRGBA_8888_PRE: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + dst[i] = r << 24 | g << 16 | b << 8 | a; + } + return; + } + break; + case VG_lL_8: { + VGubyte *dst = (VGubyte *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + dst[i] = a; + } + return; + } + break; + case VG_A_8: { + VGubyte *dst = (VGubyte *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b, a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + + dst[i] = a; + } + return; + } + break; + case VG_BW_1: { + VGshort *dst = (VGshort *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b, a; + VGubyte res; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + + res = (r + g + b + a)/4; + dst[i] = (res & (128)); + } + return; + } + break; +#ifdef OPENVG_VERSION_1_1 + case VG_A_1: { + VGshort *dst = (VGshort *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b, a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + + dst[i] = (a & (128)); + } + return; + } + break; + case VG_A_4: { + VGshort *dst = (VGshort *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b, a; + VGubyte res; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + + res = a/4; + dst[i] = (res & (128)); + } + return; + } + break; +#endif + case VG_sXRGB_8888: + break; + case VG_sARGB_8888: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + dst[i] = a << 24 | r << 16 | g << 8 | b; + } + return; + } + break; + case VG_sARGB_8888_PRE: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + dst[i] = a << 24 | r << 16 | g << 8 | b; + } + return; + } + break; + case VG_sARGB_1555: + break; + case VG_sARGB_4444: + break; + case VG_lXRGB_8888: + break; + case VG_lARGB_8888: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + dst[i] = a << 24 | r << 16 | g << 8 | b; + } + return; + } + break; + case VG_lARGB_8888_PRE: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + dst[i] = a << 24 | r << 16 | g << 8 | b; + } + return; + } + break; + case VG_sBGRX_8888: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = 0xff; + dst[i] = b << 24 | g << 16 | r << 8 | a; + } + return; + } + break; + case VG_sBGRA_8888: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + dst[i] = b << 24 | g << 16 | r << 8 | a; + } + return; + } + break; + case VG_sBGRA_8888_PRE: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + dst[i] = b << 24 | g << 16 | r << 8 | a; + } + return; + } + break; + case VG_sBGR_565: + break; + case VG_sBGRA_5551: + break; + case VG_sBGRA_4444: + break; + case VG_lBGRX_8888: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = 0xff; + dst[i] = b << 24 | g << 16 | r << 8 | a; + } + return; + } + break; + case VG_lBGRA_8888: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + dst[i] = b << 24 | g << 16 | r << 8 | a; + } + return; + } + break; + case VG_lBGRA_8888_PRE: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + dst[i] = b << 24 | g << 16 | r << 8 | a; + } + return; + } + break; + case VG_sXBGR_8888: + break; + case VG_sABGR_8888: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + dst[i] = a << 24 | b << 16 | g << 8 | r; + } + return; + } + break; + case VG_sABGR_8888_PRE: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + dst[i] = a << 24 | b << 16 | g << 8 | r; + } + return; + } + break; + case VG_sABGR_1555: + break; + case VG_sABGR_4444: + break; + case VG_lXBGR_8888: + break; + case VG_lABGR_8888: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + dst[i] = a << 24 | b << 16 | g << 8 | r; + } + return; + } + break; + case VG_lABGR_8888_PRE: { + VGint *dst = (VGint *)dstAddr; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = float_to_ubyte(rgba[i][0]); + g = float_to_ubyte(rgba[i][1]); + b = float_to_ubyte(rgba[i][2]); + a = float_to_ubyte(rgba[i][3]); + dst[i] = a << 24 | b << 16 | g << 8 | r; + } + return; + } + break; + default: + assert(!"Unknown ReadPixels format"); + break; + } + assert(!"Not implemented ReadPixels format"); +} + +void _vega_unpack_float_span_rgba(struct vg_context *ctx, + VGuint n, + VGuint offset, + const void * data, + VGImageFormat dataFormat, + VGfloat rgba[][4]) +{ + VGint i; + + switch (dataFormat) { + case VG_sRGBX_8888: { + VGuint *src = (VGuint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = (*src >> 24) & 0xff; + g = (*src >> 16) & 0xff; + b = (*src >> 8) & 0xff; + a = 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + } + return; + case VG_sRGBA_8888: { + VGuint *src = (VGuint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = (*src >> 24) & 0xff; + g = (*src >> 16) & 0xff; + b = (*src >> 8) & 0xff; + a = (*src >> 0) & 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + return; + } + break; + case VG_sRGBA_8888_PRE: { + VGint *src = (VGint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = (*src >> 24) & 0xff; + g = (*src >> 16) & 0xff; + b = (*src >> 8) & 0xff; + a = (*src >> 0) & 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + return; + } + break; + case VG_sRGB_565: { + VGshort *src = (VGshort *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGfloat clr[4]; + clr[0] = ((*src >> 10) & 31)/31.; + clr[1] = ((*src >> 5) & 95)/95.; + clr[2] = ((*src >> 0) & 31)/31.; + clr[3] = 1.f; + + util_pack_color(clr, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + } + return; + case VG_sRGBA_5551: { + VGshort *src = (VGshort *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGfloat clr[4]; + clr[0] = ((*src >> 10) & 31)/31.; + clr[1] = ((*src >> 5) & 31)/31.; + clr[2] = ((*src >> 1) & 31)/31.; + clr[3] = ((*src >> 0) & 1)/1.; + + util_pack_color(clr, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + } + return; + case VG_sRGBA_4444: { + VGshort *src = (VGshort *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGfloat clr[4]; + clr[0] = ((*src >> 12) & 15)/15.; + clr[1] = ((*src >> 8) & 15)/15.; + clr[2] = ((*src >> 4) & 15)/15.; + clr[3] = ((*src >> 0) & 15)/15.; + + util_pack_color(clr, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + } + return; + case VG_sL_8: { + VGubyte *src = (VGubyte *)data; + src += offset; + for (i = 0; i < n; ++i) { + util_pack_color_ub(0xff, 0xff, 0xff, *src, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + } + return; + case VG_lRGBX_8888: { + VGuint *src = (VGuint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = (*src >> 24) & 0xff; + g = (*src >> 16) & 0xff; + b = (*src >> 8) & 0xff; + a = 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + } + return; + case VG_lRGBA_8888: { + VGint *src = (VGint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = (*src >> 24) & 0xff; + g = (*src >> 16) & 0xff; + b = (*src >> 8) & 0xff; + a = (*src >> 0) & 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + return; + } + break; + case VG_lRGBA_8888_PRE: { + VGint *src = (VGint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + r = (*src >> 24) & 0xff; + g = (*src >> 16) & 0xff; + b = (*src >> 8) & 0xff; + a = (*src >> 0) & 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + return; + } + break; + case VG_lL_8: { + VGubyte *src = (VGubyte *)data; + src += offset; + for (i = 0; i < n; ++i) { + util_pack_color_ub(0xff, 0xff, 0xff, *src, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + } + return; + case VG_A_8: { + VGubyte *src = (VGubyte *)data; + src += offset; + for (i = 0; i < n; ++i) { + util_pack_color_ub(0xff, 0xff, 0xff, *src, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + } + return; + case VG_BW_1: { + VGubyte *src = (VGubyte *)data; + src += offset; + for (i = 0; i < n; i += 8) { + VGfloat clr[4]; + VGint j; + for (j = 0; j < 8 && j < n ; ++j) { + VGint shift = j; + clr[0] = (((*src) & (1<<shift)) >> shift); + clr[1] = clr[0]; + clr[2] = clr[0]; + clr[3] = 1.f; + + util_pack_color(clr, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i+j]); + } + ++src; + } + } + return; +#ifdef OPENVG_VERSION_1_1 + case VG_A_1: { + VGubyte *src = (VGubyte *)data; + src += offset; + for (i = 0; i < n; i += 8) { + VGfloat clr[4]; + VGint j; + for (j = 0; j < 8 && j < n ; ++j) { + VGint shift = j; + clr[0] = 0.f; + clr[1] = 0.f; + clr[2] = 0.f; + clr[3] = (((*src) & (1<<shift)) >> shift); + + util_pack_color(clr, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i+j]); + } + ++src; + } + } + return; + case VG_A_4: { + VGubyte *src = (VGubyte *)data; + src += offset/2; + for (i = 0; i < n; i += 2) { + VGfloat clr[4]; + VGint j; + for (j = 0; j < n && j < 2; ++j) { + VGint bitter, shift; + if (j == 0) { + bitter = 0x0f; + shift = 0; + } else { + bitter = 0xf0; + shift = 4; + } + clr[0] = 0.f; + clr[1] = 0.f; + clr[2] = 0.f; + clr[3] = ((*src) & (bitter)) >> shift; + + util_pack_color(clr, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i +j]); + } + ++src; + } + } + return; +#endif + case VG_sXRGB_8888: + break; + case VG_sARGB_8888: { + VGuint *src = (VGuint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + a = (*src >> 24) & 0xff; + r = (*src >> 16) & 0xff; + g = (*src >> 8) & 0xff; + b = (*src >> 0) & 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + return; + } + break; + case VG_sARGB_8888_PRE: { + VGuint *src = (VGuint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + a = (*src >> 24) & 0xff; + r = (*src >> 16) & 0xff; + g = (*src >> 8) & 0xff; + b = (*src >> 0) & 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + return; + } + break; + case VG_sARGB_1555: + break; + case VG_sARGB_4444: + break; + case VG_lXRGB_8888: + break; + case VG_lARGB_8888: { + VGint *src = (VGint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + a = (*src >> 24) & 0xff; + r = (*src >> 16) & 0xff; + g = (*src >> 8) & 0xff; + b = (*src >> 0) & 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + return; + } + break; + case VG_lARGB_8888_PRE: { + VGint *src = (VGint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + a = (*src >> 24) & 0xff; + r = (*src >> 16) & 0xff; + g = (*src >> 8) & 0xff; + b = (*src >> 0) & 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + return; + } + break; + case VG_sBGRX_8888: + break; + case VG_sBGRA_8888: { + VGuint *src = (VGuint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + b = (*src >> 24) & 0xff; + g = (*src >> 16) & 0xff; + r = (*src >> 8) & 0xff; + a = (*src >> 0) & 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + return; + } + break; + case VG_sBGRA_8888_PRE: { + VGuint *src = (VGuint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + b = (*src >> 24) & 0xff; + g = (*src >> 16) & 0xff; + r = (*src >> 8) & 0xff; + a = (*src >> 0) & 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + return; + } + break; + case VG_sBGR_565: + break; + case VG_sBGRA_5551: + break; + case VG_sBGRA_4444: + break; + case VG_lBGRX_8888: + break; + case VG_lBGRA_8888: { + VGuint *src = (VGuint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + b = (*src >> 24) & 0xff; + g = (*src >> 16) & 0xff; + r = (*src >> 8) & 0xff; + a = (*src >> 0) & 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + return; + } + break; + case VG_lBGRA_8888_PRE: { + VGuint *src = (VGuint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + b = (*src >> 24) & 0xff; + g = (*src >> 16) & 0xff; + r = (*src >> 8) & 0xff; + a = (*src >> 0) & 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + return; + } + break; + case VG_sXBGR_8888: + break; + case VG_sABGR_8888: { + VGuint *src = (VGuint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + a = (*src >> 24) & 0xff; + b = (*src >> 16) & 0xff; + g = (*src >> 8) & 0xff; + r = (*src >> 0) & 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + return; + } + break; + case VG_sABGR_8888_PRE: { + VGuint *src = (VGuint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + a = (*src >> 24) & 0xff; + b = (*src >> 16) & 0xff; + g = (*src >> 8) & 0xff; + r = (*src >> 0) & 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + return; + } + break; + case VG_sABGR_1555: + break; + case VG_sABGR_4444: + break; + case VG_lXBGR_8888: + break; + case VG_lABGR_8888: { + VGuint *src = (VGuint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + a = (*src >> 24) & 0xff; + b = (*src >> 16) & 0xff; + g = (*src >> 8) & 0xff; + r = (*src >> 0) & 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + return; + } + break; + case VG_lABGR_8888_PRE: { + VGuint *src = (VGuint *)data; + src += offset; + for (i = 0; i < n; ++i) { + VGubyte r, g, b ,a; + a = (*src >> 24) & 0xff; + b = (*src >> 16) & 0xff; + g = (*src >> 8) & 0xff; + r = (*src >> 0) & 0xff; + + util_pack_color_ub(r, g, b, a, PIPE_FORMAT_R32G32B32A32_FLOAT, + rgba[i]); + ++src; + } + return; + } + break; + default: + assert(!"Unknown ReadPixels format"); + break; + } + assert(!"Not implemented ReadPixels format"); +} + +VGint _vega_size_for_format(VGImageFormat dataFormat) +{ + switch (dataFormat) { + case VG_sRGBX_8888: + case VG_sRGBA_8888: + case VG_sRGBA_8888_PRE: + return 4; + case VG_sRGB_565: + case VG_sRGBA_5551: + case VG_sRGBA_4444: + return 2; + case VG_sL_8: + return 1; + case VG_lRGBX_8888: + case VG_lRGBA_8888: + case VG_lRGBA_8888_PRE: + return 4; + case VG_lL_8: + return 1; + case VG_A_8: + return 1; + case VG_BW_1: + return 1; +#ifdef OPENVG_VERSION_1_1 + case VG_A_1: + break; + case VG_A_4: + break; +#endif + case VG_sXRGB_8888: + case VG_sARGB_8888: + case VG_sARGB_8888_PRE: + return 4; + case VG_sARGB_1555: + case VG_sARGB_4444: + return 2; + case VG_lXRGB_8888: + case VG_lARGB_8888: + case VG_lARGB_8888_PRE: + case VG_sBGRX_8888: + case VG_sBGRA_8888: + case VG_sBGRA_8888_PRE: + return 4; + case VG_sBGR_565: + case VG_sBGRA_5551: + case VG_sBGRA_4444: + return 2; + case VG_lBGRX_8888: + case VG_lBGRA_8888: + case VG_lBGRA_8888_PRE: + case VG_sXBGR_8888: + case VG_sABGR_8888: + case VG_sABGR_8888_PRE: + return 4; + case VG_sABGR_1555: + case VG_sABGR_4444: + return 2; + case VG_lXBGR_8888: + case VG_lABGR_8888: + case VG_lABGR_8888_PRE: + return 4; + default: + assert(!"Unknown ReadPixels format"); + break; + } + assert(!"Not implemented ReadPixels format"); + return 0; +} diff --git a/src/gallium/state_trackers/vega/vg_translate.h b/src/gallium/state_trackers/vega/vg_translate.h new file mode 100644 index 00000000000..70815bacbcb --- /dev/null +++ b/src/gallium/state_trackers/vega/vg_translate.h @@ -0,0 +1,49 @@ +/************************************************************************** + * + * 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 VG_TRANSLATE_H +#define VG_TRANSLATE_H + +#include "VG/openvg.h" +#include "vg_context.h" + +/*FIXME: we really should be using translate module + * but pipe_format can't express some of the VG formats + * (the premultiplied ones) so currently it won't work */ + +void _vega_pack_rgba_span_float(struct vg_context *ctx, + VGuint n, VGfloat rgba[][4], + VGImageFormat dstFormat, + void *dstAddr); +void _vega_unpack_float_span_rgba(struct vg_context *ctx, + VGuint n, + VGuint offset, + const void * data, + VGImageFormat dataFormat, + VGfloat rgba[][4]); +VGint _vega_size_for_format(VGImageFormat format); + +#endif diff --git a/src/gallium/state_trackers/vega/vgu.c b/src/gallium/state_trackers/vega/vgu.c new file mode 100644 index 00000000000..7dc51c5599c --- /dev/null +++ b/src/gallium/state_trackers/vega/vgu.c @@ -0,0 +1,450 @@ +/************************************************************************** + * + * 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 "VG/openvg.h" +#include "VG/vgu.h" + +#include "matrix.h" +#include "path.h" + +#include "util/u_debug.h" +#include "util/u_pointer.h" + +#include <math.h> +#include <assert.h> + +static VGboolean is_aligned_to(const void *ptr, VGbyte alignment) +{ + void *aligned = align_pointer(ptr, alignment); + return (ptr == aligned) ? VG_TRUE : VG_FALSE; +} + +static VGboolean is_aligned(const void *ptr) +{ + return is_aligned_to(ptr, 4); +} + +static void vgu_append_float_coords(VGPath path, + const VGubyte *cmds, + VGint num_cmds, + const VGfloat *coords, + VGint num_coords) +{ + VGubyte common_data[40 * sizeof(VGfloat)]; + struct path *p = (struct path *)path; + + vg_float_to_datatype(path_datatype(p), common_data, coords, num_coords); + vgAppendPathData(path, num_cmds, cmds, common_data); +} + +VGUErrorCode vguLine(VGPath path, + VGfloat x0, VGfloat y0, + VGfloat x1, VGfloat y1) +{ + static const VGubyte cmds[] = {VG_MOVE_TO_ABS, VG_LINE_TO_ABS}; + VGfloat coords[4]; + VGbitfield caps; + + if (path == VG_INVALID_HANDLE) { + return VGU_BAD_HANDLE_ERROR; + } + caps = vgGetPathCapabilities(path); + if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) { + return VGU_PATH_CAPABILITY_ERROR; + } + + coords[0] = x0; + coords[1] = y0; + coords[2] = x1; + coords[3] = y1; + + vgu_append_float_coords(path, cmds, 2, coords, 4); + + return VGU_NO_ERROR; +} + +VGUErrorCode vguPolygon(VGPath path, + const VGfloat * points, + VGint count, + VGboolean closed) +{ + VGubyte *cmds; + VGfloat *coords; + VGbitfield caps; + VGint i; + + if (path == VG_INVALID_HANDLE) { + return VGU_BAD_HANDLE_ERROR; + } + + if (!points || count <= 0 || !is_aligned(points)) { + return VGU_ILLEGAL_ARGUMENT_ERROR; + } + + caps = vgGetPathCapabilities(path); + if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) { + return VGU_PATH_CAPABILITY_ERROR; + } + + cmds = malloc(sizeof(VGubyte) * count + 1); + coords = malloc(sizeof(VGfloat) * count * 2); + + cmds[0] = VG_MOVE_TO_ABS; + coords[0] = points[0]; + coords[1] = points[1]; + for (i = 1; i < count; ++i) { + cmds[i] = VG_LINE_TO_ABS; + coords[2*i + 0] = points[2*i + 0]; + coords[2*i + 1] = points[2*i + 1]; + } + + if (closed) { + cmds[i] = VG_CLOSE_PATH; + ++i; + } + + vgu_append_float_coords(path, cmds, i, coords, 2*i); + + free(cmds); + free(coords); + + return VGU_NO_ERROR; +} + +VGUErrorCode vguRect(VGPath path, + VGfloat x, VGfloat y, + VGfloat width, VGfloat height) +{ + static const VGubyte cmds[] = {VG_MOVE_TO_ABS, + VG_HLINE_TO_REL, + VG_VLINE_TO_REL, + VG_HLINE_TO_REL, + VG_CLOSE_PATH + }; + VGfloat coords[5]; + VGbitfield caps; + + if (path == VG_INVALID_HANDLE) { + return VGU_BAD_HANDLE_ERROR; + } + caps = vgGetPathCapabilities(path); + if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) { + return VGU_PATH_CAPABILITY_ERROR; + } + if (width <= 0 || height <= 0) { + return VGU_ILLEGAL_ARGUMENT_ERROR; + } + + coords[0] = x; + coords[1] = y; + coords[2] = width; + coords[3] = height; + coords[4] = -width; + + vgu_append_float_coords(path, cmds, 5, coords, 5); + + return VGU_NO_ERROR; +} + +VGUErrorCode vguRoundRect(VGPath path, + VGfloat x, VGfloat y, + VGfloat width, + VGfloat height, + VGfloat arcWidth, + VGfloat arcHeight) +{ + static const VGubyte cmds[] = {VG_MOVE_TO_ABS, + VG_HLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_VLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_HLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_VLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_CLOSE_PATH + }; + VGfloat c[26]; + VGbitfield caps; + + if (path == VG_INVALID_HANDLE) { + return VGU_BAD_HANDLE_ERROR; + } + caps = vgGetPathCapabilities(path); + if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) { + return VGU_PATH_CAPABILITY_ERROR; + } + if (width <= 0 || height <= 0) { + return VGU_ILLEGAL_ARGUMENT_ERROR; + } + + c[0] = x + arcWidth/2; c[1] = y; + + c[2] = width - arcWidth; + + c[3] = arcWidth/2; c[4] = arcHeight/2; c[5] = 0; + c[6] = arcWidth/2; c[7] = arcHeight/2; + + c[8] = height - arcHeight; + + c[9] = arcWidth/2; c[10] = arcHeight/2; c[11] = 0; + c[12] = -arcWidth/2; c[13] = arcHeight/2; + + c[14] = -(width - arcWidth); + + c[15] = arcWidth/2; c[16] = arcHeight/2; c[17] = 0; + c[18] = -arcWidth/2; c[19] = -arcHeight/2; + + c[20] = -(height - arcHeight); + + c[21] = arcWidth/2; c[22] = arcHeight/2; c[23] = 0; + c[24] = arcWidth/2; c[25] = -arcHeight/2; + + vgu_append_float_coords(path, cmds, 10, c, 26); + + return VGU_NO_ERROR; +} + +VGUErrorCode vguEllipse(VGPath path, + VGfloat cx, VGfloat cy, + VGfloat width, + VGfloat height) +{ + static const VGubyte cmds[] = {VG_MOVE_TO_ABS, + VG_SCCWARC_TO_REL, + VG_SCCWARC_TO_REL, + VG_CLOSE_PATH + }; + VGfloat coords[12]; + VGbitfield caps; + + if (path == VG_INVALID_HANDLE) { + return VGU_BAD_HANDLE_ERROR; + } + caps = vgGetPathCapabilities(path); + if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) { + return VGU_PATH_CAPABILITY_ERROR; + } + if (width <= 0 || height <= 0) { + return VGU_ILLEGAL_ARGUMENT_ERROR; + } + + coords[0] = cx + width/2; coords[1] = cy; + + coords[2] = width/2; coords[3] = height/2; coords[4] = 0; + coords[5] = -width; coords[6] = 0; + + coords[7] = width/2; coords[8] = height/2; coords[9] = 0; + coords[10] = width; coords[11] = 0; + + vgu_append_float_coords(path, cmds, 4, coords, 11); + + return VGU_NO_ERROR; +} + +VGUErrorCode vguArc(VGPath path, + VGfloat x, VGfloat y, + VGfloat width, VGfloat height, + VGfloat startAngle, + VGfloat angleExtent, + VGUArcType arcType) +{ + VGubyte cmds[11]; + VGfloat coords[40]; + VGbitfield caps; + VGfloat last = startAngle + angleExtent; + VGint i, c = 0; + + if (path == VG_INVALID_HANDLE) { + return VGU_BAD_HANDLE_ERROR; + } + caps = vgGetPathCapabilities(path); + if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) { + return VGU_PATH_CAPABILITY_ERROR; + } + if (width <= 0 || height <= 0) { + return VGU_ILLEGAL_ARGUMENT_ERROR; + } + if (arcType != VGU_ARC_OPEN && + arcType != VGU_ARC_CHORD && + arcType != VGU_ARC_PIE) { + return VGU_ILLEGAL_ARGUMENT_ERROR; + } + + cmds[c] = VG_MOVE_TO_ABS; ++c; + coords[0] = x+cos(DEGREES_TO_RADIANS(startAngle))*width/2; + coords[1] = y+sin(DEGREES_TO_RADIANS(startAngle))*height/2; +#ifdef DEBUG_VGUARC + debug_printf("start [%f, %f]\n", coords[0], coords[1]); +#endif + i = 2; + if (angleExtent > 0) { + VGfloat angle = startAngle + 180; + while (angle < last) { + cmds[c] = VG_SCCWARC_TO_ABS; ++c; + coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0; + coords[i+3] = x + cos(DEGREES_TO_RADIANS(angle))*width/2; + coords[i+4] = y + sin(DEGREES_TO_RADIANS(angle))*height/2; +#ifdef DEBUG_VGUARC + debug_printf("1 [%f, %f]\n", coords[i+3], + coords[i+4]); +#endif + i += 5; + angle += 180; + } + cmds[c] = VG_SCCWARC_TO_ABS; ++c; + coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0; + coords[i+3] = x+cos(DEGREES_TO_RADIANS(last))*width/2; + coords[i+4] = y+sin(DEGREES_TO_RADIANS(last))*height/2; +#ifdef DEBUG_VGUARC + debug_printf("2 [%f, %f]\n", coords[i+3], + coords[i+4]); +#endif + i += 5; + } else { + VGfloat angle = startAngle - 180; + while (angle > last) { + cmds[c] = VG_SCWARC_TO_ABS; ++c; + coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0; + coords[i+3] = x + cos(DEGREES_TO_RADIANS(angle)) * width/2; + coords[i+4] = y + sin(DEGREES_TO_RADIANS(angle)) * height/2; +#ifdef DEBUG_VGUARC + debug_printf("3 [%f, %f]\n", coords[i+3], + coords[i+4]); +#endif + angle -= 180; + i += 5; + } + cmds[c] = VG_SCWARC_TO_ABS; ++c; + coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0; + coords[i+3] = x + cos(DEGREES_TO_RADIANS(last)) * width/2; + coords[i+4] = y + sin(DEGREES_TO_RADIANS(last)) * height/2; +#ifdef DEBUG_VGUARC + debug_printf("4 [%f, %f]\n", coords[i+3], + coords[i+4]); +#endif + i += 5; + } + + if (arcType == VGU_ARC_PIE) { + cmds[c] = VG_LINE_TO_ABS; ++c; + coords[i] = x; coords[i + 1] = y; + i += 2; + } + if (arcType == VGU_ARC_PIE || arcType == VGU_ARC_CHORD) { + cmds[c] = VG_CLOSE_PATH; + ++c; + } + + assert(c < 11); + + vgu_append_float_coords(path, cmds, c, coords, i); + + return VGU_NO_ERROR; +} + +VGUErrorCode vguComputeWarpQuadToSquare(VGfloat sx0, VGfloat sy0, + VGfloat sx1, VGfloat sy1, + VGfloat sx2, VGfloat sy2, + VGfloat sx3, VGfloat sy3, + VGfloat * matrix) +{ + struct matrix mat; + + if (!matrix || !is_aligned(matrix)) + return VGU_ILLEGAL_ARGUMENT_ERROR; + + if (!matrix_quad_to_square(sx0, sy0, + sx1, sy1, + sx2, sy2, + sx3, sy3, + &mat)) + return VGU_BAD_WARP_ERROR; + + if (!matrix_is_invertible(&mat)) + return VGU_BAD_WARP_ERROR; + + memcpy(matrix, mat.m, sizeof(VGfloat) * 9); + + return VGU_NO_ERROR; +} + +VGUErrorCode vguComputeWarpSquareToQuad(VGfloat dx0, VGfloat dy0, + VGfloat dx1, VGfloat dy1, + VGfloat dx2, VGfloat dy2, + VGfloat dx3, VGfloat dy3, + VGfloat * matrix) +{ + struct matrix mat; + + if (!matrix || !is_aligned(matrix)) + return VGU_ILLEGAL_ARGUMENT_ERROR; + + if (!matrix_square_to_quad(dx0, dy0, + dx1, dy1, + dx2, dy2, + dx3, dy3, + &mat)) + return VGU_BAD_WARP_ERROR; + + if (!matrix_is_invertible(&mat)) + return VGU_BAD_WARP_ERROR; + + memcpy(matrix, mat.m, sizeof(VGfloat) * 9); + + return VGU_NO_ERROR; +} + +VGUErrorCode vguComputeWarpQuadToQuad(VGfloat dx0, VGfloat dy0, + VGfloat dx1, VGfloat dy1, + VGfloat dx2, VGfloat dy2, + VGfloat dx3, VGfloat dy3, + VGfloat sx0, VGfloat sy0, + VGfloat sx1, VGfloat sy1, + VGfloat sx2, VGfloat sy2, + VGfloat sx3, VGfloat sy3, + VGfloat * matrix) +{ + struct matrix mat; + + if (!matrix || !is_aligned(matrix)) + return VGU_ILLEGAL_ARGUMENT_ERROR; + + if (!matrix_quad_to_quad(dx0, dy0, + dx1, dy1, + dx2, dy2, + dx3, dy3, + sx0, sy0, + sx1, sy1, + sx2, sy2, + sx3, sy3, + &mat)) + return VGU_BAD_WARP_ERROR; + + memcpy(matrix, mat.m, sizeof(VGfloat) * 9); + + return VGU_NO_ERROR; +} diff --git a/src/gallium/state_trackers/xorg/Makefile b/src/gallium/state_trackers/xorg/Makefile index a00ea3e2a4e..27a1990724d 100644 --- a/src/gallium/state_trackers/xorg/Makefile +++ b/src/gallium/state_trackers/xorg/Makefile @@ -1,29 +1,18 @@ -TARGET = libxorgtracker.a -CFILES = $(wildcard ./*.c) -OBJECTS = $(patsubst ./%.c,./%.o,$(CFILES)) -GALLIUMDIR = ../.. -TOP = ../../../.. - +TOP = ../../../.. include $(TOP)/configs/current -CFLAGS = -DHAVE_CONFIG_H \ - -g -Wall -Wimplicit-function-declaration -fPIC \ - $(shell pkg-config --cflags pixman-1 xorg-server libdrm xproto) \ - -I$(GALLIUMDIR)/include \ - -I$(GALLIUMDIR)/auxiliary \ - -I$(TOP)/src/mesa/drivers/dri/common \ - -I$(TOP)/src/mesa \ - -I$(TOP)/include \ - -I$(TOP)/src/egl/main - -############################################# - -.PHONY = all clean +LIBNAME = xorgtracker -all: $(TARGET) +LIBRARY_INCLUDES = \ + -DHAVE_CONFIG_H \ + $(shell pkg-config --cflags-only-I pixman-1 xorg-server libdrm xproto) \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/auxiliary \ + -I$(TOP)/include \ + -I$(TOP)/src/mesa \ + -I$(TOP)/src/mesa/drivers/dri/common \ + -I$(TOP)/src/mesa/main -$(TARGET): $(OBJECTS) - ar rcs $(TARGET) $(OBJECTS) +C_SOURCES = $(wildcard ./*.c) -clean: - rm -rf $(OBJECTS) $(TARGET) +include ../../Makefile.template diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c new file mode 100644 index 00000000000..255ae91f096 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xorg_composite.c @@ -0,0 +1,27 @@ +#include "xorg_composite.h" + + +boolean xorg_composite_accelerated(int op, + PicturePtr pSrcPicture, + PicturePtr pMaskPicture, + PicturePtr pDstPicture) +{ + return FALSE; +} + +boolean xorg_composite_bind_state(struct exa_context *exa, + int op, + PicturePtr pSrcPicture, + PicturePtr pMaskPicture, + PicturePtr pDstPicture) +{ + return FALSE; +} + +void xorg_composite(struct exa_context *exa, + struct exa_pixmap_priv *dst, + int srcX, int srcY, int maskX, int maskY, + int dstX, int dstY, int width, int height) +{ +} + diff --git a/src/gallium/state_trackers/xorg/xorg_composite.h b/src/gallium/state_trackers/xorg/xorg_composite.h new file mode 100644 index 00000000000..a52e0e6dff0 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xorg_composite.h @@ -0,0 +1,22 @@ +#ifndef XORG_COMPOSITE_H +#define XORG_COMPOSITE_H + +#include "xorg_exa.h" + +boolean xorg_composite_accelerated(int op, + PicturePtr pSrcPicture, + PicturePtr pMaskPicture, + PicturePtr pDstPicture); + +boolean xorg_composite_bind_state(struct exa_context *exa, + int op, + PicturePtr pSrcPicture, + PicturePtr pMaskPicture, + PicturePtr pDstPicture); + +void xorg_composite(struct exa_context *exa, + struct exa_pixmap_priv *dst, + int srcX, int srcY, int maskX, int maskY, + int dstX, int dstY, int width, int height); + +#endif diff --git a/src/gallium/state_trackers/xorg/xorg_crtc.c b/src/gallium/state_trackers/xorg/xorg_crtc.c index 7304113a659..2235961b031 100644 --- a/src/gallium/state_trackers/xorg/xorg_crtc.c +++ b/src/gallium/state_trackers/xorg/xorg_crtc.c @@ -171,7 +171,6 @@ crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) static void crtc_destroy(xf86CrtcPtr crtc) { - modesettingPtr ms = modesettingPTR(crtc->scrn); struct crtc_private *crtcp = crtc->driver_private; if (crtcp->cursor_buf) @@ -194,9 +193,10 @@ crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image) PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_GPU_READ, 64*64*4); - drm_api_hooks.handle_from_buffer(ms->screen, - crtcp->cursor_buf, - &crtcp->cursor_handle); + ms->api->handle_from_buffer(ms->api, + ms->screen, + crtcp->cursor_buf, + &crtcp->cursor_handle); } ptr = pipe_buffer_map(ms->screen, crtcp->cursor_buf, PIPE_BUFFER_USAGE_CPU_WRITE); diff --git a/src/gallium/state_trackers/xorg/xorg_dri2.c b/src/gallium/state_trackers/xorg/xorg_dri2.c index 401bd39dac0..ae3338ffeff 100644 --- a/src/gallium/state_trackers/xorg/xorg_dri2.c +++ b/src/gallium/state_trackers/xorg/xorg_dri2.c @@ -108,8 +108,8 @@ driCreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count) tex = ms->screen->texture_create(ms->screen, &template); } - drm_api_hooks.buffer_from_texture(tex, &buf, &stride); - drm_api_hooks.global_handle_from_buffer(ms->screen, buf, &handle); + ms->api->buffer_from_texture(ms->api, tex, &buf, &stride); + ms->api->global_handle_from_buffer(ms->api, ms->screen, buf, &handle); buffers[i].name = handle; buffers[i].attachment = attachments[i]; diff --git a/src/gallium/state_trackers/xorg/xorg_driver.c b/src/gallium/state_trackers/xorg/xorg_driver.c index 45e831f0c28..e01e5294b11 100644 --- a/src/gallium/state_trackers/xorg/xorg_driver.c +++ b/src/gallium/state_trackers/xorg/xorg_driver.c @@ -300,6 +300,7 @@ PreInit(ScrnInfoPtr pScrn, int flags) ms->PciInfo->dev, ms->PciInfo->func ); + ms->api = drm_api_create(); ms->fd = drmOpen(NULL, BusID); if (ms->fd < 0) @@ -476,7 +477,7 @@ ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } if (!ms->screen) { - ms->screen = drm_api_hooks.create_screen(ms->fd, NULL); + ms->screen = ms->api->create_screen(ms->api, ms->fd, NULL); if (!ms->screen) { FatalError("Could not init pipe_screen\n"); @@ -678,6 +679,8 @@ CloseScreen(int scrnIndex, ScreenPtr pScreen) if (ms->exa) xorg_exa_close(pScrn); + ms->api->destroy(ms->api); + ms->api = NULL; drmClose(ms->fd); ms->fd = -1; diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c index 79131743542..2c4291aa4ea 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.c +++ b/src/gallium/state_trackers/xorg/xorg_exa.c @@ -28,9 +28,14 @@ * */ -#include "xorg-server.h" -#include "xf86.h" +#include "xorg_exa.h" #include "xorg_tracker.h" +#include "xorg_composite.h" + +#include <xorg-server.h> +#include <xf86.h> +#include <picturestr.h> +#include <picture.h> #include "pipe/p_format.h" #include "pipe/p_context.h" @@ -39,24 +44,6 @@ #include "util/u_rect.h" -struct exa_entity -{ - ExaDriverPtr pExa; - struct pipe_context *ctx; - struct pipe_screen *scrn; -}; - -struct PixmapPriv -{ - int flags; - struct pipe_texture *tex; - unsigned int color; - struct pipe_surface *src_surf; /* for copies */ - - struct pipe_transfer *map_transfer; - unsigned map_count; -}; - /* * Helper functions */ @@ -113,8 +100,8 @@ ExaPrepareAccess(PixmapPtr pPix, int index) ScreenPtr pScreen = pPix->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; modesettingPtr ms = modesettingPTR(pScrn); - struct exa_entity *exa = ms->exa; - struct PixmapPriv *priv; + struct exa_context *exa = ms->exa; + struct exa_pixmap_priv *priv; priv = exaGetPixmapDriverPrivate(pPix); @@ -145,8 +132,8 @@ ExaFinishAccess(PixmapPtr pPix, int index) ScreenPtr pScreen = pPix->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; modesettingPtr ms = modesettingPTR(pScrn); - struct exa_entity *exa = ms->exa; - struct PixmapPriv *priv; + struct exa_context *exa = ms->exa; + struct exa_pixmap_priv *priv; priv = exaGetPixmapDriverPrivate(pPix); if (!priv) @@ -168,8 +155,8 @@ ExaDone(PixmapPtr pPixmap) { ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; modesettingPtr ms = modesettingPTR(pScrn); - struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap); - struct exa_entity *exa = ms->exa; + struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); + struct exa_context *exa = ms->exa; if (!priv) return; @@ -190,8 +177,8 @@ ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg) { ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; modesettingPtr ms = modesettingPTR(pScrn); - struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap); - struct exa_entity *exa = ms->exa; + struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); + struct exa_context *exa = ms->exa; if (1) return FALSE; @@ -221,8 +208,8 @@ ExaSolid(PixmapPtr pPixmap, int x0, int y0, int x1, int y1) { ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum]; modesettingPtr ms = modesettingPTR(pScrn); - struct exa_entity *exa = ms->exa; - struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap); + struct exa_context *exa = ms->exa; + struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); struct pipe_surface *surf = exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | @@ -240,9 +227,9 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, { ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; modesettingPtr ms = modesettingPTR(pScrn); - struct exa_entity *exa = ms->exa; - struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pDstPixmap); - struct PixmapPriv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap); + struct exa_context *exa = ms->exa; + struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap); + struct exa_pixmap_priv *src_priv = exaGetPixmapDriverPrivate(pSrcPixmap); if (1) return FALSE; @@ -279,8 +266,8 @@ ExaCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, { ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum]; modesettingPtr ms = modesettingPTR(pScrn); - struct exa_entity *exa = ms->exa; - struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pDstPixmap); + struct exa_context *exa = ms->exa; + struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDstPixmap); struct pipe_surface *surf = exa->scrn->get_tex_surface(exa->scrn, priv->tex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | @@ -296,13 +283,25 @@ ExaPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst) { - return FALSE; + ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; + modesettingPtr ms = modesettingPTR(pScrn); + struct exa_context *exa = ms->exa; + + return xorg_composite_bind_state(exa, op, pSrcPicture, pMaskPicture, + pDstPicture); } static void ExaComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY, int dstX, int dstY, int width, int height) { + ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; + modesettingPtr ms = modesettingPTR(pScrn); + struct exa_context *exa = ms->exa; + struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pDst); + + xorg_composite(exa, priv, srcX, srcY, maskX, maskY, + dstX, dstY, width, height); } static Bool @@ -310,15 +309,18 @@ ExaCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, PicturePtr pDstPicture) { - return FALSE; + return xorg_composite_accelerated(op, + pSrcPicture, + pMaskPicture, + pDstPicture); } static void * ExaCreatePixmap(ScreenPtr pScreen, int size, int align) { - struct PixmapPriv *priv; + struct exa_pixmap_priv *priv; - priv = xcalloc(1, sizeof(struct PixmapPriv)); + priv = xcalloc(1, sizeof(struct exa_pixmap_priv)); if (!priv) return NULL; @@ -328,7 +330,7 @@ ExaCreatePixmap(ScreenPtr pScreen, int size, int align) static void ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv) { - struct PixmapPriv *priv = (struct PixmapPriv *)dPriv; + struct exa_pixmap_priv *priv = (struct exa_pixmap_priv *)dPriv; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; modesettingPtr ms = modesettingPTR(pScrn); @@ -344,7 +346,7 @@ ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv) static Bool ExaPixmapIsOffscreen(PixmapPtr pPixmap) { - struct PixmapPriv *priv; + struct exa_pixmap_priv *priv; priv = exaGetPixmapDriverPrivate(pPixmap); @@ -363,7 +365,7 @@ xorg_exa_get_pixmap_handle(PixmapPtr pPixmap) ScreenPtr pScreen = pPixmap->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; modesettingPtr ms = modesettingPTR(pScrn); - struct PixmapPriv *priv; + struct exa_pixmap_priv *priv; struct pipe_buffer *buffer = NULL; unsigned handle; unsigned stride; @@ -380,8 +382,8 @@ xorg_exa_get_pixmap_handle(PixmapPtr pPixmap) return 0; } - drm_api_hooks.buffer_from_texture(priv->tex, &buffer, &stride); - drm_api_hooks.handle_from_buffer(ms->screen, buffer, &handle); + ms->api->buffer_from_texture(ms->api, priv->tex, &buffer, &stride); + ms->api->handle_from_buffer(ms->api, ms->screen, buffer, &handle); pipe_buffer_reference(&buffer, NULL); return handle; } @@ -393,9 +395,9 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, { ScreenPtr pScreen = pPixmap->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; - struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap); + struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); modesettingPtr ms = modesettingPTR(pScrn); - struct exa_entity *exa = ms->exa; + struct exa_context *exa = ms->exa; if (!priv) return FALSE; @@ -456,7 +458,7 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, struct pipe_texture * xorg_exa_get_texture(PixmapPtr pPixmap) { - struct PixmapPriv *priv = exaGetPixmapDriverPrivate(pPixmap); + struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); struct pipe_texture *tex = NULL; pipe_texture_reference(&tex, priv->tex); return tex; @@ -466,7 +468,7 @@ void xorg_exa_close(ScrnInfoPtr pScrn) { modesettingPtr ms = modesettingPTR(pScrn); - struct exa_entity *exa = ms->exa; + struct exa_context *exa = ms->exa; if (exa->ctx) exa->ctx->destroy(exa->ctx); @@ -480,10 +482,10 @@ void * xorg_exa_init(ScrnInfoPtr pScrn) { modesettingPtr ms = modesettingPTR(pScrn); - struct exa_entity *exa; + struct exa_context *exa; ExaDriverPtr pExa; - exa = xcalloc(1, sizeof(struct exa_entity)); + exa = xcalloc(1, sizeof(struct exa_context)); if (!exa) return NULL; @@ -527,7 +529,7 @@ xorg_exa_init(ScrnInfoPtr pScrn) } exa->scrn = ms->screen; - exa->ctx = drm_api_hooks.create_context(exa->scrn); + exa->ctx = ms->api->create_context(ms->api, exa->scrn); /* Share context with DRI */ ms->ctx = exa->ctx; diff --git a/src/gallium/state_trackers/xorg/xorg_exa.h b/src/gallium/state_trackers/xorg/xorg_exa.h new file mode 100644 index 00000000000..650997aec67 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xorg_exa.h @@ -0,0 +1,27 @@ +#ifndef XORG_EXA_H +#define XORG_EXA_H + +#include "xorg_tracker.h" + +struct exa_context +{ + ExaDriverPtr pExa; + struct pipe_context *ctx; + struct pipe_screen *scrn; +}; + + +struct exa_pixmap_priv +{ + int flags; + struct pipe_texture *tex; + unsigned int color; + struct pipe_surface *src_surf; /* for copies */ + + struct pipe_transfer *map_transfer; + unsigned map_count; +}; + + + +#endif diff --git a/src/gallium/state_trackers/xorg/xorg_tracker.h b/src/gallium/state_trackers/xorg/xorg_tracker.h index 82c3890dfbd..b4742bdbf56 100644 --- a/src/gallium/state_trackers/xorg/xorg_tracker.h +++ b/src/gallium/state_trackers/xorg/xorg_tracker.h @@ -31,11 +31,14 @@ #ifndef _XORG_TRACKER_H_ #define _XORG_TRACKER_H_ +#include <stdint.h> #include <errno.h> #include <drm.h> #include <xf86drm.h> #include <xf86drmMode.h> -#include "exa.h" +#include <xorg-server.h> +#include <xf86.h> +#include <exa.h> #include "pipe/p_screen.h" #include "state_tracker/drm_api.h" @@ -75,6 +78,7 @@ typedef struct _modesettingRec CreateScreenResourcesProcPtr createScreenResources; /* gallium */ + struct drm_api *api; struct pipe_screen *screen; struct pipe_context *ctx; diff --git a/src/gallium/winsys/drm/Makefile.template b/src/gallium/winsys/drm/Makefile.template index 9f92cb42072..985e5a861fc 100644 --- a/src/gallium/winsys/drm/Makefile.template +++ b/src/gallium/winsys/drm/Makefile.template @@ -118,7 +118,7 @@ clean: install: $(LIBNAME) $(INSTALL) -d $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR) - $(INSTALL) -m 755 $(LIBNAME) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR) + $(MINSTALL) -m 755 $(LIBNAME) $(DESTDIR)$(DRI_DRIVER_INSTALL_DIR) include depend diff --git a/src/gallium/winsys/drm/intel/SConscript b/src/gallium/winsys/drm/intel/SConscript new file mode 100644 index 00000000000..50d7b75ed68 --- /dev/null +++ b/src/gallium/winsys/drm/intel/SConscript @@ -0,0 +1,7 @@ +Import('*') + +SConscript(['gem/SConscript',]) + +if 'mesa' in env['statetrackers']: + + SConscript(['dri/SConscript']) diff --git a/src/gallium/winsys/drm/intel/dri/Makefile b/src/gallium/winsys/drm/intel/dri/Makefile index ac0891a6463..5e212b62a46 100644 --- a/src/gallium/winsys/drm/intel/dri/Makefile +++ b/src/gallium/winsys/drm/intel/dri/Makefile @@ -6,7 +6,9 @@ LIBNAME = i915_dri.so PIPE_DRIVERS = \ $(TOP)/src/gallium/state_trackers/dri/libdridrm.a \ $(TOP)/src/gallium/winsys/drm/intel/gem/libinteldrm.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(TOP)/src/gallium/drivers/identity/libidentity.a \ $(TOP)/src/gallium/drivers/i915simple/libi915simple.a diff --git a/src/gallium/winsys/drm/intel/dri/SConscript b/src/gallium/winsys/drm/intel/dri/SConscript new file mode 100644 index 00000000000..e14e96e32fd --- /dev/null +++ b/src/gallium/winsys/drm/intel/dri/SConscript @@ -0,0 +1,16 @@ +Import('*') + +env = drienv.Clone() + +drivers = [ + softpipe, + i915simple, + trace, + inteldrm +] + +env.SharedLibrary( + target ='i915_dri.so', + source = COMMON_GALLIUM_SOURCES, + LIBS = drivers + mesa + auxiliaries + env['LIBS'], +) diff --git a/src/gallium/winsys/drm/intel/gem/SConscript b/src/gallium/winsys/drm/intel/gem/SConscript new file mode 100644 index 00000000000..ea8a2e55f62 --- /dev/null +++ b/src/gallium/winsys/drm/intel/gem/SConscript @@ -0,0 +1,17 @@ +Import('*') + +env = drienv.Clone() + +inteldrm_sources = [ + 'intel_be_api.c', + 'intel_be_batchbuffer.c', + 'intel_be_context.c', + 'intel_be_device.c', +] + +inteldrm = env.ConvenienceLibrary( + target ='inteldrm', + source = inteldrm_sources, +) + +Export('inteldrm') diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_api.c b/src/gallium/winsys/drm/intel/gem/intel_be_api.c index f4ef7c2d88b..dd5f814da3c 100644 --- a/src/gallium/winsys/drm/intel/gem/intel_be_api.c +++ b/src/gallium/winsys/drm/intel/gem/intel_be_api.c @@ -1,15 +1,37 @@ #include "intel_be_api.h" #include "i915simple/i915_winsys.h" +#include "identity/id_drm.h" +#include "trace/tr_drm.h" -struct drm_api drm_api_hooks = +static void destroy(struct drm_api *api) +{ + +} + +struct drm_api intel_be_drm_api = { /* intel_be_context.c */ .create_context = intel_be_create_context, /* intel_be_device.c */ .create_screen = intel_be_create_screen, - .buffer_from_texture = i915_get_texture_buffer, + .buffer_from_texture = intel_be_get_texture_buffer, .buffer_from_handle = intel_be_buffer_from_handle, .handle_from_buffer = intel_be_handle_from_buffer, .global_handle_from_buffer = intel_be_global_handle_from_buffer, + .destroy = destroy, }; + +struct drm_api * +drm_api_create() +{ +#ifdef DEBUG +#if 0 + return identity_drm_create(&intel_be_drm_api); +#else + return trace_drm_create(&intel_be_drm_api); +#endif +#else + return &intel_be_drm_api; +#endif +} diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_api.h b/src/gallium/winsys/drm/intel/gem/intel_be_api.h index 1c622f3b978..f286b62eb8c 100644 --- a/src/gallium/winsys/drm/intel/gem/intel_be_api.h +++ b/src/gallium/winsys/drm/intel/gem/intel_be_api.h @@ -8,8 +8,11 @@ #include "intel_be_device.h" -struct pipe_screen *intel_be_create_screen(int drmFD, +extern struct drm_api intel_be_drm_api; + +struct pipe_screen *intel_be_create_screen(struct drm_api *api, int drmFD, struct drm_create_screen_arg *arg); -struct pipe_context *intel_be_create_context(struct pipe_screen *screen); +struct pipe_context *intel_be_create_context(struct drm_api *api, + struct pipe_screen *screen); #endif diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_context.c b/src/gallium/winsys/drm/intel/gem/intel_be_context.c index fe0b138fbea..db84f9af514 100644 --- a/src/gallium/winsys/drm/intel/gem/intel_be_context.c +++ b/src/gallium/winsys/drm/intel/gem/intel_be_context.c @@ -97,7 +97,7 @@ intel_be_init_context(struct intel_be_context *intel, struct intel_be_device *de } struct pipe_context * -intel_be_create_context(struct pipe_screen *screen) +intel_be_create_context(struct drm_api *api, struct pipe_screen *screen) { struct intel_be_context *intel; struct pipe_context *pipe; diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_device.c b/src/gallium/winsys/drm/intel/gem/intel_be_device.c index 907ac86637f..e3630f5d120 100644 --- a/src/gallium/winsys/drm/intel/gem/intel_be_device.c +++ b/src/gallium/winsys/drm/intel/gem/intel_be_device.c @@ -142,8 +142,27 @@ err: return NULL; } +boolean +intel_be_get_texture_buffer(struct drm_api *api, + struct pipe_texture *texture, + struct pipe_buffer **buffer, + unsigned *stride) +{ + struct intel_be_device *dev; + + if (!texture) + return FALSE; + + dev = intel_be_device(texture->screen->winsys); + if (dev->softpipe) + return softpipe_get_texture_buffer(texture, buffer, stride); + else + return i915_get_texture_buffer(texture, buffer, stride); +} + struct pipe_buffer * -intel_be_buffer_from_handle(struct pipe_screen *screen, +intel_be_buffer_from_handle(struct drm_api *api, + struct pipe_screen *screen, const char* name, unsigned handle) { struct intel_be_device *dev = intel_be_device(screen->winsys); @@ -174,7 +193,8 @@ err: } boolean -intel_be_handle_from_buffer(struct pipe_screen *screen, +intel_be_handle_from_buffer(struct drm_api *api, + struct pipe_screen *screen, struct pipe_buffer *buffer, unsigned *handle) { @@ -186,7 +206,8 @@ intel_be_handle_from_buffer(struct pipe_screen *screen, } boolean -intel_be_global_handle_from_buffer(struct pipe_screen *screen, +intel_be_global_handle_from_buffer(struct drm_api *api, + struct pipe_screen *screen, struct pipe_buffer *buffer, unsigned *handle) { @@ -296,6 +317,7 @@ intel_be_get_device_id(unsigned int *device_id) { char path[512]; FILE *file; + void *shutup_gcc; /* * FIXME: Fix this up to use a drm ioctl or whatever. @@ -307,13 +329,14 @@ intel_be_get_device_id(unsigned int *device_id) return; } - fgets(path, sizeof(path), file); + shutup_gcc = fgets(path, sizeof(path), file); sscanf(path, "%x", device_id); fclose(file); } struct pipe_screen * -intel_be_create_screen(int drmFD, struct drm_create_screen_arg *arg) +intel_be_create_screen(struct drm_api *api, int drmFD, + struct drm_create_screen_arg *arg) { struct intel_be_device *dev; struct pipe_screen *screen; @@ -339,7 +362,6 @@ intel_be_create_screen(int drmFD, struct drm_create_screen_arg *arg) if (dev->softpipe) { screen = softpipe_create_screen(&dev->base); - drm_api_hooks.buffer_from_texture = softpipe_get_texture_buffer; } else screen = i915_create_screen(&dev->base, deviceID); diff --git a/src/gallium/winsys/drm/intel/gem/intel_be_device.h b/src/gallium/winsys/drm/intel/gem/intel_be_device.h index b32637ece29..56d95bd7fe0 100644 --- a/src/gallium/winsys/drm/intel/gem/intel_be_device.h +++ b/src/gallium/winsys/drm/intel/gem/intel_be_device.h @@ -8,6 +8,8 @@ #include "drm.h" #include "intel_bufmgr.h" +struct drm_api; + /* * Device */ @@ -50,13 +52,23 @@ struct intel_be_buffer { unsigned flink; }; +/* + * Wrapper for driver get_texture_buffer functions. + */ +boolean +intel_be_get_texture_buffer(struct drm_api *api, + struct pipe_texture *texture, + struct pipe_buffer **buffer, + unsigned *stride); + /** * Create a be buffer from a drm bo handle. * * Takes a reference. */ struct pipe_buffer * -intel_be_buffer_from_handle(struct pipe_screen *screen, +intel_be_buffer_from_handle(struct drm_api *api, + struct pipe_screen *screen, const char* name, unsigned handle); /** @@ -65,7 +77,8 @@ intel_be_buffer_from_handle(struct pipe_screen *screen, * If buffer is destroyed handle may become invalid. */ boolean -intel_be_handle_from_buffer(struct pipe_screen *screen, +intel_be_handle_from_buffer(struct drm_api *api, + struct pipe_screen *screen, struct pipe_buffer *buffer, unsigned *handle); @@ -75,7 +88,8 @@ intel_be_handle_from_buffer(struct pipe_screen *screen, * If buffer is destroyed handle may become invalid. */ boolean -intel_be_global_handle_from_buffer(struct pipe_screen *screen, +intel_be_global_handle_from_buffer(struct drm_api *api, + struct pipe_screen *screen, struct pipe_buffer *buffer, unsigned *handle); diff --git a/src/gallium/winsys/drm/intel/xorg/Makefile b/src/gallium/winsys/drm/intel/xorg/Makefile index b1b6b9362b6..d51cca8d213 100644 --- a/src/gallium/winsys/drm/intel/xorg/Makefile +++ b/src/gallium/winsys/drm/intel/xorg/Makefile @@ -1,36 +1,38 @@ TARGET = modesetting_drv.so CFILES = $(wildcard ./*.c) OBJECTS = $(patsubst ./%.c,./%.o,$(CFILES)) -GALLIUMDIR = ../../../.. TOP = ../../../../../.. -include ${TOP}/configs/current +include $(TOP)/configs/current -CFLAGS = -DHAVE_CONFIG_H \ - -g -Wall -Wimplicit-function-declaration -fPIC \ - $(shell pkg-config --cflags pixman-1 xorg-server libdrm xproto) \ - -I../gem \ - -I${GALLIUMDIR}/include \ - -I${GALLIUMDIR}/drivers \ - -I${GALLIUMDIR}/auxiliary \ - -I${TOP}/src/mesa \ - -I$(TOP)/include \ - -I$(TOP)/src/egl/main +INCLUDES = \ + $(shell pkg-config --cflags-only-I pixman-1 xorg-server libdrm xproto) \ + -I../gem \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/src/gallium/auxiliary \ + -I$(TOP)/src/mesa \ + -I$(TOP)/include \ + -I$(TOP)/src/egl/main LIBS = \ - $(GALLIUMDIR)/state_trackers/xorg/libxorgtracker.a \ - $(GALLIUMDIR)/winsys/drm/intel/gem/libinteldrm.a \ + $(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a \ + $(TOP)/src/gallium/winsys/drm/intel/gem/libinteldrm.a \ $(TOP)/src/gallium/drivers/i915simple/libi915simple.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ $(GALLIUM_AUXILIARIES) +DRIVER_DEFINES = \ + -DHAVE_CONFIG_H + + ############################################# all default: $(TARGET) -$(TARGET): $(OBJECTS) Makefile $(GALLIUMDIR)/state_trackers/xorg/libxorgtracker.a $(LIBS) +$(TARGET): $(OBJECTS) Makefile $(TOP)/src/gallium/state_trackers/xorg/libxorgtracker.a $(LIBS) $(TOP)/bin/mklib -noprefix -o $@ \ $(OBJECTS) $(LIBS) $(shell pkg-config --libs libdrm) -ldrm_intel @@ -39,6 +41,16 @@ clean: install: $(INSTALL) -d $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR) - $(INSTALL) -m 755 $(TARGET) $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR) + $(MINSTALL) -m 755 $(TARGET) $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR) + + +############################################## + + +.c.o: + $(CC) -c $(CFLAGS) $(INCLUDES) $(DRIVER_DEFINES) $< -o $@ + + +############################################## .PHONY = all clean install diff --git a/src/gallium/winsys/drm/nouveau/Makefile b/src/gallium/winsys/drm/nouveau/Makefile index f8c81358544..6c9cbef26df 100644 --- a/src/gallium/winsys/drm/nouveau/Makefile +++ b/src/gallium/winsys/drm/nouveau/Makefile @@ -2,7 +2,7 @@ TOP = ../../../../.. include $(TOP)/configs/current -SUBDIRS = drm dri dri2 +SUBDIRS = drm $(GALLIUM_STATE_TRACKERS_DIRS) default install clean: @for dir in $(SUBDIRS) ; do \ diff --git a/src/gallium/winsys/drm/nouveau/dri/Makefile b/src/gallium/winsys/drm/nouveau/dri/Makefile index f7db6201fea..0937f68c34b 100644 --- a/src/gallium/winsys/drm/nouveau/dri/Makefile +++ b/src/gallium/winsys/drm/nouveau/dri/Makefile @@ -3,32 +3,25 @@ include $(TOP)/configs/current LIBNAME = nouveau_dri.so -MINIGLX_SOURCES = - PIPE_DRIVERS = \ + $(TOP)/src/gallium/state_trackers/dri/libdridrm.a \ $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \ $(TOP)/src/gallium/drivers/nv04/libnv04.a \ $(TOP)/src/gallium/drivers/nv10/libnv10.a \ $(TOP)/src/gallium/drivers/nv20/libnv20.a \ $(TOP)/src/gallium/drivers/nv30/libnv30.a \ $(TOP)/src/gallium/drivers/nv40/libnv40.a \ - $(TOP)/src/gallium/drivers/nv50/libnv50.a - -DRIVER_SOURCES = \ - nouveau_context.c \ - nouveau_screen.c \ - nouveau_swapbuffers.c \ - nouveau_lock.c + $(TOP)/src/gallium/drivers/nv50/libnv50.a \ + $(TOP)/src/gallium/drivers/nouveau/libnouveau.a + +DRIVER_SOURCES = C_SOURCES = \ $(COMMON_GALLIUM_SOURCES) \ $(DRIVER_SOURCES) -ASM_SOURCES = +include ../../Makefile.template -DRIVER_DEFINES = $(shell pkg-config libdrm_nouveau --cflags) DRI_LIB_DEPS += $(shell pkg-config libdrm_nouveau --libs) -include ../../Makefile.template - symlinks: diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_context.c b/src/gallium/winsys/drm/nouveau/dri/nouveau_context.c deleted file mode 100644 index deb6ffcff1c..00000000000 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_context.c +++ /dev/null @@ -1,118 +0,0 @@ -#include <main/glheader.h> -#include <glapi/glthread.h> -#include <GL/internal/glcore.h> -#include <utils.h> - -#include <state_tracker/st_public.h> -#include <state_tracker/st_context.h> -#include <state_tracker/drm_api.h> -#include <pipe/p_defines.h> -#include <pipe/p_context.h> -#include <pipe/p_screen.h> - -#include "nouveau_context.h" -#include "nouveau_screen.h" - -#include "nouveau_drmif.h" - -GLboolean -nouveau_context_create(const __GLcontextModes *glVis, - __DRIcontextPrivate *driContextPriv, - void *sharedContextPrivate) -{ - __DRIscreenPrivate *driScrnPriv = driContextPriv->driScreenPriv; - struct nouveau_screen *nv_screen = driScrnPriv->private; - struct nouveau_context *nv; - struct pipe_context *pipe; - struct st_context *st_share = NULL; - - if (sharedContextPrivate) - st_share = ((struct nouveau_context *)sharedContextPrivate)->st; - - nv = CALLOC_STRUCT(nouveau_context); - if (!nv) - return GL_FALSE; - - { - struct nouveau_device_priv *nvdev = - nouveau_device(nv_screen->device); - - nvdev->ctx = driContextPriv->hHWContext; - nvdev->lock = (drmLock *)&driScrnPriv->pSAREA->lock; - } - - pipe = drm_api_hooks.create_context(nv_screen->pscreen); - if (!pipe) { - FREE(nv); - return GL_FALSE; - } - pipe->priv = nv; - - driContextPriv->driverPrivate = nv; - nv->dri_screen = driScrnPriv; - - driParseConfigFiles(&nv->dri_option_cache, &nv_screen->option_cache, - nv->dri_screen->myNum, "nouveau"); - - nv->st = st_create_context(pipe, glVis, st_share); - return GL_TRUE; -} - -void -nouveau_context_destroy(__DRIcontextPrivate *driContextPriv) -{ - struct nouveau_context *nv = driContextPriv->driverPrivate; - - assert(nv); - - st_finish(nv->st); - st_destroy_context(nv->st); - - FREE(nv); -} - -GLboolean -nouveau_context_bind(__DRIcontextPrivate *driContextPriv, - __DRIdrawablePrivate *driDrawPriv, - __DRIdrawablePrivate *driReadPriv) -{ - struct nouveau_context *nv; - struct nouveau_framebuffer *draw, *read; - - if (!driContextPriv) { - st_make_current(NULL, NULL, NULL); - return GL_TRUE; - } - - nv = driContextPriv->driverPrivate; - draw = driDrawPriv->driverPrivate; - read = driReadPriv->driverPrivate; - - st_make_current(nv->st, draw->stfb, read->stfb); - - if ((nv->dri_drawable != driDrawPriv) || - (nv->last_stamp != driDrawPriv->lastStamp)) { - nv->dri_drawable = driDrawPriv; - st_resize_framebuffer(draw->stfb, driDrawPriv->w, - driDrawPriv->h); - nv->last_stamp = driDrawPriv->lastStamp; - } - - if (driDrawPriv != driReadPriv) { - st_resize_framebuffer(read->stfb, driReadPriv->w, - driReadPriv->h); - } - - return GL_TRUE; -} - -GLboolean -nouveau_context_unbind(__DRIcontextPrivate *driContextPriv) -{ - struct nouveau_context *nv = driContextPriv->driverPrivate; - (void)nv; - - st_flush(nv->st, 0, NULL); - return GL_TRUE; -} - diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_context.h b/src/gallium/winsys/drm/nouveau/dri/nouveau_context.h deleted file mode 100644 index 2779b092e64..00000000000 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_context.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef __NOUVEAU_CONTEXT_DRI_H__ -#define __NOUVEAU_CONTEXT_DRI_H__ - -#include <dri_util.h> -#include <xmlconfig.h> - -#include "nouveau/nouveau_winsys.h" - -#define NOUVEAU_ERR(fmt, args...) debug_printf("%s: "fmt, __func__, ##args) - -struct nouveau_framebuffer { - struct st_framebuffer *stfb; -}; - -struct nouveau_context { - struct st_context *st; - - /* DRI stuff */ - __DRIscreenPrivate *dri_screen; - __DRIdrawablePrivate *dri_drawable; - unsigned int last_stamp; - driOptionCache dri_option_cache; - drm_context_t drm_context; - drmLock drm_lock; - int locked; -}; - -extern GLboolean nouveau_context_create(const __GLcontextModes *, - __DRIcontextPrivate *, void *); -extern void nouveau_context_destroy(__DRIcontextPrivate *); -extern GLboolean nouveau_context_bind(__DRIcontextPrivate *, - __DRIdrawablePrivate *draw, - __DRIdrawablePrivate *read); -extern GLboolean nouveau_context_unbind(__DRIcontextPrivate *); - -extern void nouveau_contended_lock(struct nouveau_context *nv); -extern void LOCK_HARDWARE(struct nouveau_context *nv); -extern void UNLOCK_HARDWARE(struct nouveau_context *nv); - -#ifdef DEBUG -extern int __nouveau_debug; - -#define DEBUG_BO (1 << 0) - -#define DBG(flag, ...) do { \ - if (__nouveau_debug & (DEBUG_##flag)) \ - NOUVEAU_ERR(__VA_ARGS__); \ -} while(0) -#else -#define DBG(flag, ...) -#endif - -#endif diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_screen.c b/src/gallium/winsys/drm/nouveau/dri/nouveau_screen.c deleted file mode 100644 index 4e9b76a9090..00000000000 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_screen.c +++ /dev/null @@ -1,330 +0,0 @@ -#include <utils.h> -#include <vblank.h> -#include <xmlpool.h> - -#include <pipe/p_context.h> -#include <state_tracker/st_public.h> -#include <state_tracker/st_cb_fbo.h> -#include <state_tracker/drm_api.h> - -#include "nouveau_context.h" -#include "nouveau_screen.h" -#include "nouveau_swapbuffers.h" -#include "nouveau_dri.h" - -#include "nouveau_drm.h" -#include "nouveau_drmif.h" - -#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 12 -#error nouveau_drm.h version does not match expected version -#endif - -/* Extension stuff, enabling of extensions handled by Gallium's GL state - * tracker. But, we still need to define the entry points we want. - */ -#define need_GL_ARB_fragment_program -#define need_GL_ARB_multisample -#define need_GL_ARB_occlusion_query -#define need_GL_ARB_point_parameters -#define need_GL_ARB_shader_objects -#define need_GL_ARB_texture_compression -#define need_GL_ARB_vertex_program -#define need_GL_ARB_vertex_shader -#define need_GL_ARB_vertex_buffer_object -#define need_GL_EXT_compiled_vertex_array -#define need_GL_EXT_fog_coord -#define need_GL_EXT_secondary_color -#define need_GL_EXT_framebuffer_object -#define need_GL_VERSION_2_0 -#define need_GL_VERSION_2_1 -#include "extension_helper.h" - -const struct dri_extension card_extensions[] = -{ - { "GL_ARB_multisample", GL_ARB_multisample_functions }, - { "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions }, - { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions }, - { "GL_ARB_shader_objects", GL_ARB_shader_objects_functions }, - { "GL_ARB_shading_language_100", GL_VERSION_2_0_functions }, - { "GL_ARB_shading_language_120", GL_VERSION_2_1_functions }, - { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions }, - { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions }, - { "GL_ARB_vertex_shader", GL_ARB_vertex_shader_functions }, - { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions }, - { "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions }, - { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions }, - { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions }, - { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions }, - { NULL, 0 } -}; - -PUBLIC const char __driConfigOptions[] = -DRI_CONF_BEGIN -DRI_CONF_END; -static const GLuint __driNConfigOptions = 0; - -extern const struct dri_extension common_extensions[]; -extern const struct dri_extension nv40_extensions[]; - -static GLboolean -nouveau_create_buffer(__DRIscreenPrivate * driScrnPriv, - __DRIdrawablePrivate * driDrawPriv, - const __GLcontextModes *glVis, GLboolean pixmapBuffer) -{ - struct nouveau_framebuffer *nvfb; - enum pipe_format colour, depth, stencil; - - if (pixmapBuffer) - return GL_FALSE; - - nvfb = CALLOC_STRUCT(nouveau_framebuffer); - if (!nvfb) - return GL_FALSE; - - if (glVis->redBits == 5) - colour = PIPE_FORMAT_R5G6B5_UNORM; - else - colour = PIPE_FORMAT_A8R8G8B8_UNORM; - - if (glVis->depthBits == 16) - depth = PIPE_FORMAT_Z16_UNORM; - else if (glVis->depthBits == 24) - depth = PIPE_FORMAT_Z24S8_UNORM; - else - depth = PIPE_FORMAT_NONE; - - if (glVis->stencilBits == 8) - stencil = PIPE_FORMAT_Z24S8_UNORM; - else - stencil = PIPE_FORMAT_NONE; - - nvfb->stfb = st_create_framebuffer(glVis, colour, depth, stencil, - driDrawPriv->w, driDrawPriv->h, - (void*)nvfb); - if (!nvfb->stfb) { - free(nvfb); - return GL_FALSE; - } - - driDrawPriv->driverPrivate = (void *)nvfb; - return GL_TRUE; -} - -static void -nouveau_destroy_buffer(__DRIdrawablePrivate * driDrawPriv) -{ - struct nouveau_framebuffer *nvfb; - - nvfb = (struct nouveau_framebuffer *)driDrawPriv->driverPrivate; - st_unreference_framebuffer(nvfb->stfb); - free(nvfb); -} - -static __DRIconfig ** -nouveau_fill_in_modes(__DRIscreenPrivate *psp, - unsigned pixel_bits, unsigned depth_bits, - unsigned stencil_bits, GLboolean have_back_buffer) -{ - __DRIconfig **configs; - unsigned depth_buffer_factor; - unsigned back_buffer_factor; - GLenum fb_format; - GLenum fb_type; - - static const GLenum back_buffer_modes[] = { - GLX_NONE, GLX_SWAP_UNDEFINED_OML, - }; - - uint8_t depth_bits_array[3]; - uint8_t stencil_bits_array[3]; - uint8_t msaa_samples_array[1]; - - depth_bits_array[0] = 0; - depth_bits_array[1] = depth_bits; - depth_bits_array[2] = depth_bits; - - /* Just like with the accumulation buffer, always provide some modes - * with a stencil buffer. It will be a sw fallback, but some apps won't - * care about that. - */ - stencil_bits_array[0] = 0; - stencil_bits_array[1] = 0; - if (depth_bits == 24) - stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; - stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits; - - msaa_samples_array[0] = 0; - - depth_buffer_factor = - ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1; - back_buffer_factor = (have_back_buffer) ? 3 : 1; - - if (pixel_bits == 16) { - fb_format = GL_RGB; - fb_type = GL_UNSIGNED_SHORT_5_6_5; - } - else { - fb_format = GL_BGRA; - fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; - } - - configs = driCreateConfigs(fb_format, fb_type, - depth_bits_array, stencil_bits_array, - depth_buffer_factor, back_buffer_modes, - back_buffer_factor, msaa_samples_array, 1); - if (configs == NULL) { - fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", - __func__, __LINE__); - return NULL; - } - - return configs; -} - -static struct pipe_surface * -dri_surface_from_handle(struct pipe_screen *screen, - unsigned handle, - enum pipe_format format, - unsigned width, - unsigned height, - unsigned pitch) -{ - struct pipe_surface *surface = NULL; - struct pipe_texture *texture = NULL; - struct pipe_texture templat; - struct pipe_buffer *buf = NULL; - - buf = drm_api_hooks.buffer_from_handle(screen, "front buffer", handle); - if (!buf) - return NULL; - - memset(&templat, 0, sizeof(templat)); - templat.tex_usage = PIPE_TEXTURE_USAGE_PRIMARY | - NOUVEAU_TEXTURE_USAGE_LINEAR; - templat.target = PIPE_TEXTURE_2D; - templat.last_level = 0; - templat.depth[0] = 1; - templat.format = format; - templat.width[0] = width; - templat.height[0] = height; - pf_get_block(templat.format, &templat.block); - - texture = screen->texture_blanket(screen, - &templat, - &pitch, - buf); - - /* we don't need the buffer from this point on */ - pipe_buffer_reference(&buf, NULL); - - if (!texture) - return NULL; - - surface = screen->get_tex_surface(screen, texture, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_GPU_WRITE); - - /* we don't need the texture from this point on */ - pipe_texture_reference(&texture, NULL); - return surface; -} - -static const __DRIconfig ** -nouveau_screen_create(__DRIscreenPrivate *psp) -{ - struct nouveau_dri *nv_dri = psp->pDevPriv; - struct nouveau_screen *nv_screen; - static const __DRIversion ddx_expected = - { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL }; - static const __DRIversion dri_expected = { 4, 0, 0 }; - static const __DRIversion drm_expected = - { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL }; - - if (!driCheckDriDdxDrmVersions2("nouveau", - &psp->dri_version, &dri_expected, - &psp->ddx_version, &ddx_expected, - &psp->drm_version, &drm_expected)) { - return NULL; - } - - if (drm_expected.patch != psp->drm_version.patch) { - fprintf(stderr, "Incompatible DRM patch level.\n" - "Expected: %d\n" "Current : %d\n", - drm_expected.patch, psp->drm_version.patch); - return NULL; - } - - driInitExtensions(NULL, card_extensions, GL_FALSE); - - if (psp->devPrivSize != sizeof(struct nouveau_dri)) { - NOUVEAU_ERR("DRI struct mismatch between DDX/DRI\n"); - return NULL; - } - - nv_screen = CALLOC_STRUCT(nouveau_screen); - if (!nv_screen) - return NULL; - - nouveau_device_open_existing(&nv_screen->device, 0, psp->fd, 0); - - nv_screen->pscreen = drm_api_hooks.create_screen(psp->fd, NULL); - if (!nv_screen->pscreen) { - FREE(nv_screen); - return NULL; - } - nv_screen->pscreen->flush_frontbuffer = nouveau_flush_frontbuffer; - - { - enum pipe_format format; - - if (nv_dri->bpp == 16) - format = PIPE_FORMAT_R5G6B5_UNORM; - else - format = PIPE_FORMAT_A8R8G8B8_UNORM; - - nv_screen->fb = dri_surface_from_handle(nv_screen->pscreen, - nv_dri->front_offset, - format, - nv_dri->width, - nv_dri->height, - nv_dri->front_pitch * - nv_dri->bpp / 8); - } - - driParseOptionInfo(&nv_screen->option_cache, - __driConfigOptions, __driNConfigOptions); - - nv_screen->driScrnPriv = psp; - psp->private = (void *)nv_screen; - - return (const __DRIconfig **) - nouveau_fill_in_modes(psp, nv_dri->bpp, - (nv_dri->bpp == 16) ? 16 : 24, - (nv_dri->bpp == 16) ? 0 : 8, 1); -} - -static void -nouveau_screen_destroy(__DRIscreenPrivate *driScrnPriv) -{ - struct nouveau_screen *nv_screen = driScrnPriv->private; - - driScrnPriv->private = NULL; - FREE(nv_screen); -} - -const struct __DriverAPIRec -driDriverAPI = { - .InitScreen = nouveau_screen_create, - .DestroyScreen = nouveau_screen_destroy, - .CreateContext = nouveau_context_create, - .DestroyContext = nouveau_context_destroy, - .CreateBuffer = nouveau_create_buffer, - .DestroyBuffer = nouveau_destroy_buffer, - .SwapBuffers = nouveau_swap_buffers, - .MakeCurrent = nouveau_context_bind, - .UnbindContext = nouveau_context_unbind, - .CopySubBuffer = nouveau_copy_sub_buffer, - - .InitScreen2 = NULL, /* one day, I promise! */ -}; - diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_screen.h b/src/gallium/winsys/drm/nouveau/dri/nouveau_screen.h deleted file mode 100644 index ac078f3c638..00000000000 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_screen.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __NOUVEAU_SCREEN_DRI_H__ -#define __NOUVEAU_SCREEN_DRI_H__ - -#include "xmlconfig.h" - -struct nouveau_screen { - __DRIscreenPrivate *driScrnPriv; - driOptionCache option_cache; - - struct nouveau_device *device; - - struct pipe_screen *pscreen; - struct pipe_surface *fb; -}; - -#endif diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.c b/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.c deleted file mode 100644 index 9c841a0b2d0..00000000000 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.c +++ /dev/null @@ -1,115 +0,0 @@ -#include <main/glheader.h> -#include <glapi/glthread.h> -#include <GL/internal/glcore.h> - -#include <pipe/p_context.h> -#include <state_tracker/st_public.h> -#include <state_tracker/st_context.h> -#include <state_tracker/st_cb_fbo.h> - -#include "nouveau_context.h" -#include "nouveau_screen.h" -#include "nouveau_swapbuffers.h" - -#include "nouveau_pushbuf.h" - -void -nouveau_copy_buffer(__DRIdrawablePrivate *dPriv, struct pipe_surface *surf, - const drm_clip_rect_t *rect) -{ - struct nouveau_context *nv = dPriv->driContextPriv->driverPrivate; - struct nouveau_screen *nv_screen = nv->dri_screen->private; - struct pipe_context *pipe = nv->st->pipe; - drm_clip_rect_t *pbox; - int nbox, i; - - LOCK_HARDWARE(nv); - if (!dPriv->numClipRects) { - UNLOCK_HARDWARE(nv); - return; - } - pbox = dPriv->pClipRects; - nbox = dPriv->numClipRects; - - for (i = 0; i < nbox; i++, pbox++) { - int sx, sy, dx, dy, w, h; - - sx = pbox->x1 - dPriv->x; - sy = pbox->y1 - dPriv->y; - dx = pbox->x1; - dy = pbox->y1; - w = pbox->x2 - pbox->x1; - h = pbox->y2 - pbox->y1; - - pipe->surface_copy(pipe, nv_screen->fb, dx, dy, surf, - sx, sy, w, h); - } - - pipe->flush(pipe, 0, NULL); - UNLOCK_HARDWARE(nv); - - if (nv->last_stamp != dPriv->lastStamp) { - struct nouveau_framebuffer *nvfb = dPriv->driverPrivate; - st_resize_framebuffer(nvfb->stfb, dPriv->w, dPriv->h); - nv->last_stamp = dPriv->lastStamp; - } -} - -void -nouveau_copy_sub_buffer(__DRIdrawablePrivate *dPriv, int x, int y, int w, int h) -{ - struct nouveau_framebuffer *nvfb = dPriv->driverPrivate; - struct pipe_surface *surf; - - st_get_framebuffer_surface(nvfb->stfb, ST_SURFACE_BACK_LEFT, &surf); - if (surf) { - drm_clip_rect_t rect; - rect.x1 = x; - rect.y1 = y; - rect.x2 = x + w; - rect.y2 = y + h; - - st_notify_swapbuffers(nvfb->stfb); - nouveau_copy_buffer(dPriv, surf, &rect); - } -} - -void -nouveau_swap_buffers(__DRIdrawablePrivate *dPriv) -{ - struct nouveau_framebuffer *nvfb = dPriv->driverPrivate; - struct pipe_surface *surf; - - st_get_framebuffer_surface(nvfb->stfb, ST_SURFACE_BACK_LEFT, &surf); - if (surf) { - st_notify_swapbuffers(nvfb->stfb); - nouveau_copy_buffer(dPriv, surf, NULL); - } -} - -void -nouveau_flush_frontbuffer(struct pipe_screen *pscreen, struct pipe_surface *ps, - void *context_private) -{ - struct nouveau_context *nv = context_private; - __DRIdrawablePrivate *dPriv = nv->dri_drawable; - - nouveau_copy_buffer(dPriv, ps, NULL); -} - -void -nouveau_contended_lock(struct nouveau_context *nv) -{ - struct nouveau_context *nv_sub = (struct nouveau_context*)nv; - __DRIdrawablePrivate *dPriv = nv_sub->dri_drawable; - __DRIscreenPrivate *sPriv = nv_sub->dri_screen; - - /* If the window moved, may need to set a new cliprect now. - * - * NOTE: This releases and regains the hw lock, so all state - * checking must be done *after* this call: - */ - if (dPriv) - DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv); -} - diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.h b/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.h deleted file mode 100644 index 4ca9cc22831..00000000000 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __NOUVEAU_SWAPBUFFERS_H__ -#define __NOUVEAU_SWAPBUFFERS_H__ - -void nouveau_copy_buffer(__DRIdrawablePrivate *, struct pipe_surface *, - const drm_clip_rect_t *); -void nouveau_copy_sub_buffer(__DRIdrawablePrivate *, int x, int y, int w, int h); -void nouveau_swap_buffers(__DRIdrawablePrivate *); -void nouveau_flush_frontbuffer(struct pipe_screen *, struct pipe_surface *, - void *context_private); - -#endif diff --git a/src/gallium/winsys/drm/nouveau/dri2/Makefile b/src/gallium/winsys/drm/nouveau/dri2/Makefile deleted file mode 100644 index 377a80d5188..00000000000 --- a/src/gallium/winsys/drm/nouveau/dri2/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -TOP = ../../../../../.. -include $(TOP)/configs/current - -LIBNAME = nouveau_dri2.so - -PIPE_DRIVERS = \ - $(TOP)/src/gallium/state_trackers/dri/libdridrm.a \ - $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \ - $(TOP)/src/gallium/drivers/nv04/libnv04.a \ - $(TOP)/src/gallium/drivers/nv10/libnv10.a \ - $(TOP)/src/gallium/drivers/nv20/libnv20.a \ - $(TOP)/src/gallium/drivers/nv30/libnv30.a \ - $(TOP)/src/gallium/drivers/nv40/libnv40.a \ - $(TOP)/src/gallium/drivers/nv50/libnv50.a - -DRIVER_SOURCES = - -C_SOURCES = \ - $(COMMON_GALLIUM_SOURCES) \ - $(DRIVER_SOURCES) - -include ../../Makefile.template - -DRI_LIB_DEPS += $(shell pkg-config libdrm_nouveau --libs) - -symlinks: diff --git a/src/gallium/winsys/drm/nouveau/drm/Makefile b/src/gallium/winsys/drm/nouveau/drm/Makefile index 2da78d8690f..54c3b26c755 100644 --- a/src/gallium/winsys/drm/nouveau/drm/Makefile +++ b/src/gallium/winsys/drm/nouveau/drm/Makefile @@ -3,9 +3,7 @@ include $(TOP)/configs/current LIBNAME = nouveaudrm -C_SOURCES = nouveau_drm_api.c \ - nouveau_winsys_pipe.c \ - nouveau_winsys.c +C_SOURCES = nouveau_drm_api.c LIBRARY_INCLUDES = $(shell pkg-config libdrm libdrm_nouveau --cflags-only-I) LIBRARY_DEFINES = $(shell pkg-config libdrm libdrm_nouveau --cflags-only-other) diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_dri.h b/src/gallium/winsys/drm/nouveau/drm/nouveau_dri.h index 1207c2d609c..1207c2d609c 100644 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_dri.h +++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_dri.h diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c index a558fda1401..3167ccfdc16 100644 --- a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c +++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c @@ -1,20 +1,84 @@ +#include "pipe/p_context.h" +#include "pipe/p_state.h" #include "util/u_memory.h" #include "nouveau_drm_api.h" -#include "nouveau_winsys_pipe.h" #include "nouveau_drmif.h" #include "nouveau_channel.h" #include "nouveau_bo.h" +#include "nouveau/nouveau_winsys.h" +#include "nouveau/nouveau_screen.h" + +static struct pipe_surface * +dri_surface_from_handle(struct drm_api *api, struct pipe_screen *screen, + unsigned handle, + enum pipe_format format, + unsigned width, + unsigned height, + unsigned pitch) +{ + struct pipe_surface *surface = NULL; + struct pipe_texture *texture = NULL; + struct pipe_texture templat; + struct pipe_buffer *buf = NULL; + + buf = api->buffer_from_handle(api, screen, "front buffer", handle); + if (!buf) + return NULL; + + memset(&templat, 0, sizeof(templat)); + templat.tex_usage = PIPE_TEXTURE_USAGE_PRIMARY | + NOUVEAU_TEXTURE_USAGE_LINEAR; + templat.target = PIPE_TEXTURE_2D; + templat.last_level = 0; + templat.depth[0] = 1; + templat.format = format; + templat.width[0] = width; + templat.height[0] = height; + pf_get_block(templat.format, &templat.block); + + texture = screen->texture_blanket(screen, + &templat, + &pitch, + buf); + + /* we don't need the buffer from this point on */ + pipe_buffer_reference(&buf, NULL); + + if (!texture) + return NULL; + + surface = screen->get_tex_surface(screen, texture, 0, 0, 0, + PIPE_BUFFER_USAGE_GPU_READ | + PIPE_BUFFER_USAGE_GPU_WRITE); + + /* we don't need the texture from this point on */ + pipe_texture_reference(&texture, NULL); + return surface; +} + +static struct pipe_surface * +nouveau_dri1_front_surface(struct pipe_context *pipe) +{ + return nouveau_winsys_screen(pipe->screen)->front; +} + +static struct dri1_api nouveau_dri1_api = { + nouveau_dri1_front_surface, +}; + static struct pipe_screen * -nouveau_drm_create_screen(int fd, struct drm_create_screen_arg *arg) +nouveau_drm_create_screen(struct drm_api *api, int fd, + struct drm_create_screen_arg *arg) { - struct pipe_winsys *ws; + struct dri1_create_screen_arg *dri1 = (void *)arg; struct nouveau_winsys *nvws; + struct pipe_winsys *ws; struct nouveau_device *dev = NULL; struct pipe_screen *(*init)(struct pipe_winsys *, - struct nouveau_winsys *); + struct nouveau_device *); int ret; ret = nouveau_device_open_existing(&dev, 0, fd, 0); @@ -49,33 +113,53 @@ nouveau_drm_create_screen(int fd, struct drm_create_screen_arg *arg) return NULL; } - ws = nouveau_pipe_winsys_new(dev); - if (!ws) { + nvws = CALLOC_STRUCT(nouveau_winsys); + if (!nvws) { nouveau_device_close(&dev); return NULL; } + ws = &nvws->base; - nvws = nouveau_winsys_new(ws); - if (!nvws) { + nvws->pscreen = init(ws, dev); + if (!nvws->pscreen) { ws->destroy(ws); return NULL; } - nouveau_pipe_winsys(ws)->pscreen = init(ws, nvws); - if (!nouveau_pipe_winsys(ws)->pscreen) { - ws->destroy(ws); - return NULL; + if (arg->mode == DRM_CREATE_DRI1) { + struct nouveau_dri *nvdri = dri1->ddx_info; + enum pipe_format format; + + if (nvdri->bpp == 16) + format = PIPE_FORMAT_R5G6B5_UNORM; + else + format = PIPE_FORMAT_A8R8G8B8_UNORM; + + nvws->front = dri_surface_from_handle(api, nvws->pscreen, + nvdri->front_offset, + format, nvdri->width, + nvdri->height, + nvdri->front_pitch * + (nvdri->bpp / 8)); + if (!nvws->front) { + debug_printf("%s: error referencing front buffer\n", + __func__); + ws->destroy(ws); + return NULL; + } + + dri1->api = &nouveau_dri1_api; } - return nouveau_pipe_winsys(ws)->pscreen; + return nvws->pscreen; } static struct pipe_context * -nouveau_drm_create_context(struct pipe_screen *pscreen) +nouveau_drm_create_context(struct drm_api *api, struct pipe_screen *pscreen) { - struct nouveau_pipe_winsys *nvpws = nouveau_screen(pscreen); + struct nouveau_winsys *nvws = nouveau_winsys_screen(pscreen); struct pipe_context *(*init)(struct pipe_screen *, unsigned); - unsigned chipset = nvpws->channel->device->chipset; + unsigned chipset = nouveau_screen(pscreen)->device->chipset; int i; switch (chipset & 0xf0) { @@ -106,81 +190,80 @@ nouveau_drm_create_context(struct pipe_screen *pscreen) } /* Find a free slot for a pipe context, allocate a new one if needed */ - for (i = 0; i < nvpws->nr_pctx; i++) { - if (nvpws->pctx[i] == NULL) + for (i = 0; i < nvws->nr_pctx; i++) { + if (nvws->pctx[i] == NULL) break; } - if (i == nvpws->nr_pctx) { - nvpws->nr_pctx++; - nvpws->pctx = realloc(nvpws->pctx, - sizeof(*nvpws->pctx) * nvpws->nr_pctx); + if (i == nvws->nr_pctx) { + nvws->nr_pctx++; + nvws->pctx = realloc(nvws->pctx, + sizeof(*nvws->pctx) * nvws->nr_pctx); } - nvpws->pctx[i] = init(pscreen, i); - return nvpws->pctx[i]; + nvws->pctx[i] = init(pscreen, i); + return nvws->pctx[i]; } static boolean -nouveau_drm_pb_from_pt(struct pipe_texture *pt, struct pipe_buffer **ppb, - unsigned *stride) +nouveau_drm_pb_from_pt(struct drm_api *api, struct pipe_texture *pt, + struct pipe_buffer **ppb, unsigned *stride) { return false; } static struct pipe_buffer * -nouveau_drm_pb_from_handle(struct pipe_screen *pscreen, const char *name, - unsigned handle) +nouveau_drm_pb_from_handle(struct drm_api *api, struct pipe_screen *pscreen, + const char *name, unsigned handle) { - struct nouveau_pipe_winsys *nvpws = nouveau_screen(pscreen); - struct nouveau_device *dev = nvpws->channel->device; - struct nouveau_pipe_buffer *nvpb; + struct nouveau_device *dev = nouveau_screen(pscreen)->device; + struct pipe_buffer *pb; int ret; - nvpb = CALLOC_STRUCT(nouveau_pipe_buffer); - if (!nvpb) + pb = CALLOC(1, sizeof(struct pipe_buffer) + sizeof(struct nouveau_bo*)); + if (!pb) return NULL; - ret = nouveau_bo_handle_ref(dev, handle, &nvpb->bo); + ret = nouveau_bo_handle_ref(dev, handle, (struct nouveau_bo**)(pb+1)); if (ret) { debug_printf("%s: ref name 0x%08x failed with %d\n", __func__, handle, ret); - FREE(nvpb); + FREE(pb); return NULL; } - pipe_reference_init(&nvpb->base.reference, 1); - nvpb->base.screen = pscreen; - nvpb->base.alignment = 0; - nvpb->base.usage = PIPE_BUFFER_USAGE_GPU_READ_WRITE | - PIPE_BUFFER_USAGE_CPU_READ_WRITE; - nvpb->base.size = nvpb->bo->size; - return &nvpb->base; + pipe_reference_init(&pb->reference, 1); + pb->screen = pscreen; + pb->alignment = 0; + pb->usage = PIPE_BUFFER_USAGE_GPU_READ_WRITE | + PIPE_BUFFER_USAGE_CPU_READ_WRITE; + pb->size = nouveau_bo(pb)->size; + return pb; } static boolean -nouveau_drm_handle_from_pb(struct pipe_screen *pscreen, struct pipe_buffer *pb, - unsigned *handle) +nouveau_drm_handle_from_pb(struct drm_api *api, struct pipe_screen *pscreen, + struct pipe_buffer *pb, unsigned *handle) { - struct nouveau_pipe_buffer *nvpb = nouveau_pipe_buffer(pb); + struct nouveau_bo *bo = nouveau_bo(pb); - if (!nvpb) + if (!bo) return FALSE; - *handle = nvpb->bo->handle; + *handle = bo->handle; return TRUE; } static boolean -nouveau_drm_name_from_pb(struct pipe_screen *pscreen, struct pipe_buffer *pb, - unsigned *handle) +nouveau_drm_name_from_pb(struct drm_api *api, struct pipe_screen *pscreen, + struct pipe_buffer *pb, unsigned *handle) { - struct nouveau_pipe_buffer *nvpb = nouveau_pipe_buffer(pb); + struct nouveau_bo *bo = nouveau_bo(pb); - if (!nvpb) + if (!bo) return FALSE; - return nouveau_bo_handle_get(nvpb->bo, handle) == 0; + return nouveau_bo_handle_get(bo, handle) == 0; } struct drm_api drm_api_hooks = { @@ -192,3 +275,8 @@ struct drm_api drm_api_hooks = { .global_handle_from_buffer = nouveau_drm_name_from_pb, }; +struct drm_api * +drm_api_create() { + return &drm_api_hooks; +} + diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h index 2782c83c0e7..e61e0e0957a 100644 --- a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h +++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h @@ -1,5 +1,34 @@ #ifndef __NOUVEAU_DRM_API_H__ #define __NOUVEAU_DRM_API_H__ + #include "state_tracker/drm_api.h" +#include "state_tracker/dri1_api.h" + +#include "pipe/internal/p_winsys_screen.h" + +#include "nouveau_dri.h" + +struct nouveau_winsys { + struct pipe_winsys base; + + struct pipe_screen *pscreen; + + unsigned nr_pctx; + struct pipe_context **pctx; + + struct pipe_surface *front; +}; + +static INLINE struct nouveau_winsys * +nouveau_winsys(struct pipe_winsys *ws) +{ + return (struct nouveau_winsys *)ws; +} + +static INLINE struct nouveau_winsys * +nouveau_winsys_screen(struct pipe_screen *pscreen) +{ + return nouveau_winsys(pscreen->winsys); +} #endif diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys.c b/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys.c deleted file mode 100644 index e3175fd7753..00000000000 --- a/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys.c +++ /dev/null @@ -1,94 +0,0 @@ -#include "util/u_memory.h" - -#include "nouveau_winsys_pipe.h" - -static int -nouveau_pipe_notifier_alloc(struct nouveau_winsys *nvws, int count, - struct nouveau_notifier **notify) -{ - struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(nvws->ws); - - return nouveau_notifier_alloc(nvpws->channel, nvpws->next_handle++, - count, notify); -} - -static int -nouveau_pipe_grobj_alloc(struct nouveau_winsys *nvws, int grclass, - struct nouveau_grobj **grobj) -{ - struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(nvws->ws); - struct nouveau_channel *chan = nvpws->channel; - int ret; - - ret = nouveau_grobj_alloc(chan, nvpws->next_handle++, grclass, grobj); - if (ret) - return ret; - - BEGIN_RING(chan, *grobj, 0x0000, 1); - OUT_RING (chan, (*grobj)->handle); - (*grobj)->bound = NOUVEAU_GROBJ_BOUND_EXPLICIT; - return 0; -} - -static int -nouveau_pipe_push_reloc(struct nouveau_winsys *nvws, void *ptr, - struct pipe_buffer *buf, uint32_t data, - uint32_t flags, uint32_t vor, uint32_t tor) -{ - struct nouveau_bo *bo = nouveau_pipe_buffer(buf)->bo; - - return nouveau_pushbuf_emit_reloc(nvws->channel, ptr, bo, - data, flags, vor, tor); -} - -static int -nouveau_pipe_push_flush(struct nouveau_winsys *nvws, unsigned size, - struct pipe_fence_handle **fence) -{ - if (fence) - *fence = NULL; - - return nouveau_pushbuf_flush(nvws->channel, size); -} - -static struct nouveau_bo * -nouveau_pipe_get_bo(struct pipe_buffer *pb) -{ - return nouveau_pipe_buffer(pb)->bo; -} - -struct nouveau_winsys * -nouveau_winsys_new(struct pipe_winsys *ws) -{ - struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(ws); - struct nouveau_winsys *nvws; - - nvws = CALLOC_STRUCT(nouveau_winsys); - if (!nvws) - return NULL; - - nvws->ws = ws; - nvws->channel = nvpws->channel; - - nvws->res_init = nouveau_resource_init; - nvws->res_alloc = nouveau_resource_alloc; - nvws->res_free = nouveau_resource_free; - - nvws->push_reloc = nouveau_pipe_push_reloc; - nvws->push_flush = nouveau_pipe_push_flush; - - nvws->grobj_alloc = nouveau_pipe_grobj_alloc; - nvws->grobj_free = nouveau_grobj_free; - - nvws->notifier_alloc = nouveau_pipe_notifier_alloc; - nvws->notifier_free = nouveau_notifier_free; - nvws->notifier_reset = nouveau_notifier_reset; - nvws->notifier_status = nouveau_notifier_status; - nvws->notifier_retval = nouveau_notifier_return_val; - nvws->notifier_wait = nouveau_notifier_wait_status; - - nvws->get_bo = nouveau_pipe_get_bo; - - return nvws; -} - diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys_pipe.c b/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys_pipe.c deleted file mode 100644 index 9e03a9f5dba..00000000000 --- a/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys_pipe.c +++ /dev/null @@ -1,204 +0,0 @@ -#include "pipe/internal/p_winsys_screen.h" -#include <pipe/p_defines.h> -#include <pipe/p_inlines.h> -#include <util/u_memory.h> - -#include "nouveau_winsys_pipe.h" - -#include "nouveau_drmif.h" -#include "nouveau_bo.h" - -static const char * -nouveau_get_name(struct pipe_winsys *pws) -{ - return "Nouveau/DRI"; -} - -static uint32_t -nouveau_flags_from_usage(struct pipe_winsys *ws, unsigned usage) -{ - struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(ws); - struct pipe_screen *pscreen = nvpws->pscreen; - uint32_t flags = NOUVEAU_BO_LOCAL; - - if (usage & NOUVEAU_BUFFER_USAGE_TRANSFER) - flags |= NOUVEAU_BO_GART; - - if (usage & PIPE_BUFFER_USAGE_PIXEL) { - if (usage & NOUVEAU_BUFFER_USAGE_TEXTURE) - flags |= NOUVEAU_BO_GART; - if (!(usage & PIPE_BUFFER_USAGE_CPU_READ_WRITE)) - flags |= NOUVEAU_BO_VRAM; - - switch (nvpws->channel->device->chipset & 0xf0) { - case 0x50: - case 0x80: - case 0x90: - flags |= NOUVEAU_BO_TILED; - if (usage & NOUVEAU_BUFFER_USAGE_ZETA) - flags |= NOUVEAU_BO_ZTILE; - break; - default: - break; - } - } - - if (usage & PIPE_BUFFER_USAGE_VERTEX) { - if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_VTXBUF)) - flags |= NOUVEAU_BO_GART; - } - - if (usage & PIPE_BUFFER_USAGE_INDEX) { - if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF)) - flags |= NOUVEAU_BO_GART; - } - - return flags; -} - -static struct pipe_buffer * -nouveau_pipe_bo_create(struct pipe_winsys *ws, unsigned alignment, - unsigned usage, unsigned size) -{ - struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(ws); - struct nouveau_device *dev = nvpws->channel->device; - struct nouveau_pipe_buffer *nvbuf; - uint32_t flags; - - nvbuf = CALLOC_STRUCT(nouveau_pipe_buffer); - if (!nvbuf) - return NULL; - pipe_reference_init(&nvbuf->base.reference, 1); - nvbuf->base.alignment = alignment; - nvbuf->base.usage = usage; - nvbuf->base.size = size; - - flags = nouveau_flags_from_usage(ws, usage); - if (nouveau_bo_new(dev, flags, alignment, size, &nvbuf->bo)) { - FREE(nvbuf); - return NULL; - } - - return &nvbuf->base; -} - -static struct pipe_buffer * -nouveau_pipe_bo_user_create(struct pipe_winsys *ws, void *ptr, unsigned bytes) -{ - struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(ws); - struct nouveau_device *dev = nvpws->channel->device; - struct nouveau_pipe_buffer *nvbuf; - - nvbuf = CALLOC_STRUCT(nouveau_pipe_buffer); - if (!nvbuf) - return NULL; - pipe_reference_init(&nvbuf->base.reference, 1); - nvbuf->base.size = bytes; - - if (nouveau_bo_user(dev, ptr, bytes, &nvbuf->bo)) { - FREE(nvbuf); - return NULL; - } - - return &nvbuf->base; -} - -static void -nouveau_pipe_bo_del(struct pipe_buffer *buf) -{ - struct nouveau_pipe_buffer *nvbuf = nouveau_pipe_buffer(buf); - - nouveau_bo_ref(NULL, &nvbuf->bo); - FREE(nvbuf); -} - -static void * -nouveau_pipe_bo_map(struct pipe_winsys *pws, struct pipe_buffer *buf, - unsigned flags) -{ - struct nouveau_pipe_buffer *nvbuf = nouveau_pipe_buffer(buf); - uint32_t map_flags = 0; - - if (flags & PIPE_BUFFER_USAGE_CPU_READ) - map_flags |= NOUVEAU_BO_RD; - if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) - map_flags |= NOUVEAU_BO_WR; - - if (nouveau_bo_map(nvbuf->bo, map_flags)) - return NULL; - return nvbuf->bo->map; -} - -static void -nouveau_pipe_bo_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf) -{ - struct nouveau_pipe_buffer *nvbuf = nouveau_pipe_buffer(buf); - - nouveau_bo_unmap(nvbuf->bo); -} - -static void -nouveau_pipe_fence_reference(struct pipe_winsys *ws, - struct pipe_fence_handle **ptr, - struct pipe_fence_handle *pfence) -{ - *ptr = pfence; -} - -static int -nouveau_pipe_fence_signalled(struct pipe_winsys *ws, - struct pipe_fence_handle *pfence, unsigned flag) -{ - return 0; -} - -static int -nouveau_pipe_fence_finish(struct pipe_winsys *ws, - struct pipe_fence_handle *pfence, unsigned flag) -{ - return 0; -} - -static void -nouveau_destroy(struct pipe_winsys *ws) -{ - struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(ws); - - nouveau_device_close(&nvpws->channel->device); - FREE(nvpws); -} - -struct pipe_winsys * -nouveau_pipe_winsys_new(struct nouveau_device *dev) -{ - struct nouveau_pipe_winsys *nvpws; - int ret; - - nvpws = CALLOC_STRUCT(nouveau_pipe_winsys); - if (!nvpws) - return NULL; - - ret = nouveau_channel_alloc(dev, 0xbeef0201, 0xbeef0202, - &nvpws->channel); - if (ret) { - debug_printf("%s: error opening GPU channel: %d\n", - __func__, ret); - FREE(nvpws); - return NULL; - } - nvpws->next_handle = 0x77000000; - - nvpws->base.buffer_create = nouveau_pipe_bo_create; - nvpws->base.buffer_destroy = nouveau_pipe_bo_del; - nvpws->base.user_buffer_create = nouveau_pipe_bo_user_create; - nvpws->base.buffer_map = nouveau_pipe_bo_map; - nvpws->base.buffer_unmap = nouveau_pipe_bo_unmap; - - nvpws->base.fence_reference = nouveau_pipe_fence_reference; - nvpws->base.fence_signalled = nouveau_pipe_fence_signalled; - nvpws->base.fence_finish = nouveau_pipe_fence_finish; - - nvpws->base.get_name = nouveau_get_name; - nvpws->base.destroy = nouveau_destroy; - return &nvpws->base; -} diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys_pipe.h b/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys_pipe.h deleted file mode 100644 index 10e1e269e8c..00000000000 --- a/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys_pipe.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef NOUVEAU_PIPE_WINSYS_H -#define NOUVEAU_PIPE_WINSYS_H - -#include "pipe/internal/p_winsys_screen.h" -#include "pipe/p_context.h" - -#include "nouveau/nouveau_winsys.h" - -#include "nouveau_device.h" - -struct nouveau_pipe_buffer { - struct pipe_buffer base; - struct nouveau_bo *bo; -}; - -static INLINE struct nouveau_pipe_buffer * -nouveau_pipe_buffer(struct pipe_buffer *buf) -{ - return (struct nouveau_pipe_buffer *)buf; -} - -struct nouveau_pipe_winsys { - struct pipe_winsys base; - - struct pipe_screen *pscreen; - - struct nouveau_channel *channel; - uint32_t next_handle; - - unsigned nr_pctx; - struct pipe_context **pctx; -}; - -static INLINE struct nouveau_pipe_winsys * -nouveau_pipe_winsys(struct pipe_winsys *ws) -{ - return (struct nouveau_pipe_winsys *)ws; -} - -static INLINE struct nouveau_pipe_winsys * -nouveau_screen(struct pipe_screen *pscreen) -{ - return nouveau_pipe_winsys(pscreen->winsys); -} - -struct pipe_winsys * -nouveau_pipe_winsys_new(struct nouveau_device *); - -struct nouveau_winsys * -nouveau_winsys_new(struct pipe_winsys *ws); - -#endif diff --git a/src/gallium/winsys/drm/radeon/SConscript b/src/gallium/winsys/drm/radeon/SConscript index 8f99055b2f7..b2dfd504d42 100644 --- a/src/gallium/winsys/drm/radeon/SConscript +++ b/src/gallium/winsys/drm/radeon/SConscript @@ -4,4 +4,4 @@ SConscript(['core/SConscript',]) if 'mesa' in env['statetrackers']: - SConscript(['dri2/SConscript']) + SConscript(['dri/SConscript']) diff --git a/src/gallium/winsys/drm/radeon/core/SConscript b/src/gallium/winsys/drm/radeon/core/SConscript index 578174e32ba..2ad68e403fe 100644 --- a/src/gallium/winsys/drm/radeon/core/SConscript +++ b/src/gallium/winsys/drm/radeon/core/SConscript @@ -11,7 +11,9 @@ radeon_sources = [ env.Append(CPPPATH = '#/src/gallium/drivers/r300') -env.ConvenienceLibrary( +radeonwinsys = env.ConvenienceLibrary( target ='radeonwinsys', source = radeon_sources, ) + +Export('radeonwinsys') diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c index a15487352b2..775bda8308f 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.c @@ -1,8 +1,8 @@ -/* +/* * Copyright © 2008 Jérôme Glisse * 2009 Corbin Simpson * 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 @@ -10,14 +10,14 @@ * 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 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 THE COPYRIGHT HOLDERS, AUTHORS * 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 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. * * The above copyright notice and this permission notice (including the @@ -72,6 +72,7 @@ static struct pipe_buffer *radeon_buffer_create(struct pipe_winsys *ws, alignment, domain, 0); if (radeon_buffer->bo == NULL) { FREE(radeon_buffer); + return NULL; } return &radeon_buffer->base; } @@ -93,6 +94,29 @@ static struct pipe_buffer *radeon_buffer_user_create(struct pipe_winsys *ws, return &radeon_buffer->base; } +static struct pipe_buffer *radeon_surface_buffer_create(struct pipe_winsys *ws, + unsigned width, + unsigned height, + enum pipe_format format, + unsigned usage, + unsigned *stride) +{ + struct pipe_format_block block; + unsigned nblocksx, nblocksy, size; + + pf_get_block(format, &block); + + nblocksx = pf_get_nblocksx(&block, width); + nblocksy = pf_get_nblocksy(&block, height); + + /* Radeons enjoy things in multiples of 32. */ + /* XXX this can be 32 when POT */ + *stride = (nblocksx * block.size + 63) & ~63; + size = *stride * nblocksy; + + return radeon_buffer_create(ws, 64, usage, size); +} + static void radeon_buffer_del(struct pipe_buffer *buffer) { struct radeon_pipe_buffer *radeon_buffer = @@ -118,6 +142,8 @@ static void *radeon_buffer_map(struct pipe_winsys *ws, write = 1; } + radeon_bo_wait(radeon_buffer->bo); + if (radeon_bo_map(radeon_buffer->bo, write)) return NULL; return radeon_buffer->bo->ptr; @@ -175,15 +201,17 @@ struct radeon_winsys* radeon_pipe_winsys(int fd) return NULL; } + radeon_ws->priv->fd = fd; radeon_ws->priv->bom = radeon_bo_manager_gem_ctor(fd); radeon_ws->base.flush_frontbuffer = radeon_flush_frontbuffer; radeon_ws->base.buffer_create = radeon_buffer_create; - radeon_ws->base.buffer_destroy = radeon_buffer_del; radeon_ws->base.user_buffer_create = radeon_buffer_user_create; + radeon_ws->base.surface_buffer_create = radeon_surface_buffer_create; radeon_ws->base.buffer_map = radeon_buffer_map; radeon_ws->base.buffer_unmap = radeon_buffer_unmap; + radeon_ws->base.buffer_destroy = radeon_buffer_del; radeon_ws->base.fence_reference = radeon_fence_reference; radeon_ws->base.fence_signalled = radeon_fence_signalled; diff --git a/src/gallium/winsys/drm/radeon/core/radeon_buffer.h b/src/gallium/winsys/drm/radeon/core/radeon_buffer.h index ca8bbb3c117..f5153b06af5 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_buffer.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_buffer.h @@ -1,7 +1,7 @@ -/* +/* * Copyright © 2008 Jérôme Glisse * 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 @@ -9,14 +9,14 @@ * 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 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 THE COPYRIGHT HOLDERS, AUTHORS * 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 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. * * The above copyright notice and this permission notice (including the @@ -48,19 +48,19 @@ struct radeon_pipe_buffer { struct pipe_buffer base; struct radeon_bo *bo; + boolean flinked; + uint32_t flink; }; #define RADEON_MAX_BOS 24 struct radeon_winsys_priv { + /* DRM FD */ + int fd; + /* Radeon BO manager. */ struct radeon_bo_manager* bom; - /* Radeon BO space checker. */ - struct radeon_cs_space_check sc[RADEON_MAX_BOS]; - /* Current BO count. */ - unsigned bo_count; - /* Radeon CS manager. */ struct radeon_cs_manager* csm; diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm.c b/src/gallium/winsys/drm/radeon/core/radeon_drm.c index 428d3f65a16..8d818cf8301 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_drm.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_drm.c @@ -1,7 +1,7 @@ -/* +/* * Copyright © 2009 Corbin Simpson * 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 @@ -9,14 +9,14 @@ * 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 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 THE COPYRIGHT HOLDERS, AUTHORS * 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 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. * * The above copyright notice and this permission notice (including the @@ -31,7 +31,8 @@ #include "radeon_drm.h" /* Create a pipe_screen. */ -struct pipe_screen* radeon_create_screen(int drmFB, +struct pipe_screen* radeon_create_screen(struct drm_api* api, + int drmFB, struct drm_create_screen_arg *arg) { struct radeon_winsys* winsys = radeon_pipe_winsys(drmFB); @@ -46,25 +47,30 @@ struct pipe_screen* radeon_create_screen(int drmFB, } /* Create a pipe_context. */ -struct pipe_context* radeon_create_context(struct pipe_screen* screen) +struct pipe_context* radeon_create_context(struct drm_api* api, + struct pipe_screen* screen) { if (getenv("RADEON_SOFTPIPE")) { return radeon_create_softpipe(screen->winsys); } else { - return r300_create_context(screen, screen->winsys); + return r300_create_context(screen, + (struct r300_winsys*)screen->winsys); } } -boolean radeon_buffer_from_texture(struct pipe_texture* texture, +boolean radeon_buffer_from_texture(struct drm_api* api, + struct pipe_texture* texture, struct pipe_buffer** buffer, unsigned* stride) { - return FALSE; + /* XXX fix this */ + return r300_get_texture_buffer(texture, buffer, stride); } /* Create a buffer from a handle. */ /* XXX what's up with name? */ -struct pipe_buffer* radeon_buffer_from_handle(struct pipe_screen* screen, +struct pipe_buffer* radeon_buffer_from_handle(struct drm_api* api, + struct pipe_screen* screen, const char* name, unsigned handle) { @@ -91,7 +97,8 @@ struct pipe_buffer* radeon_buffer_from_handle(struct pipe_screen* screen, return &radeon_buffer->base; } -boolean radeon_handle_from_buffer(struct pipe_screen* screen, +boolean radeon_handle_from_buffer(struct drm_api* api, + struct pipe_screen* screen, struct pipe_buffer* buffer, unsigned* handle) { @@ -101,23 +108,50 @@ boolean radeon_handle_from_buffer(struct pipe_screen* screen, return TRUE; } -boolean radeon_global_handle_from_buffer(struct pipe_screen* screen, +boolean radeon_global_handle_from_buffer(struct drm_api* api, + struct pipe_screen* screen, struct pipe_buffer* buffer, unsigned* handle) { - /* XXX WTF is the difference here? global? */ + int retval, fd; + struct drm_gem_flink flink; struct radeon_pipe_buffer* radeon_buffer = (struct radeon_pipe_buffer*)buffer; - *handle = radeon_buffer->bo->handle; + + if (!radeon_buffer->flinked) { + fd = ((struct radeon_winsys*)screen->winsys)->priv->fd; + + flink.handle = radeon_buffer->bo->handle; + + retval = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); + if (retval) { + debug_printf("radeon: DRM_IOCTL_GEM_FLINK failed, error %d\n", + retval); + return FALSE; + } + + radeon_buffer->flink = flink.name; + radeon_buffer->flinked = TRUE; + } + + *handle = radeon_buffer->flink; return TRUE; } struct drm_api drm_api_hooks = { .create_screen = radeon_create_screen, .create_context = radeon_create_context, - /* XXX fix this */ - .buffer_from_texture = r300_get_texture_buffer, + .buffer_from_texture = radeon_buffer_from_texture, .buffer_from_handle = radeon_buffer_from_handle, .handle_from_buffer = radeon_handle_from_buffer, .global_handle_from_buffer = radeon_global_handle_from_buffer, }; + +struct drm_api* drm_api_create() +{ +#ifdef DEBUG + return trace_drm_create(&drm_api_hooks); +#else + return &drm_api_hooks; +#endif +} diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm.h b/src/gallium/winsys/drm/radeon/core/radeon_drm.h index 049f9984dba..88a5c82b284 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_drm.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_drm.h @@ -30,8 +30,13 @@ #ifndef RADEON_DRM_H #define RADEON_DRM_H +#include <sys/ioctl.h> + +#include "xf86drm.h" + #include "pipe/p_screen.h" +#include "trace/tr_drm.h" #include "util/u_memory.h" #include "state_tracker/drm_api.h" @@ -40,25 +45,35 @@ #include "radeon_r300.h" #include "radeon_winsys_softpipe.h" -struct pipe_screen* radeon_create_screen(int drmFB, +/* XXX */ +#include "r300_screen.h" + +struct pipe_screen* radeon_create_screen(struct drm_api* api, + int drmFB, struct drm_create_screen_arg *arg); -struct pipe_context* radeon_create_context(struct pipe_screen* screen); +struct pipe_context* radeon_create_context(struct drm_api* api, + struct pipe_screen* screen); -boolean radeon_buffer_from_texture(struct pipe_texture* texture, +boolean radeon_buffer_from_texture(struct drm_api* api, + struct pipe_texture* texture, struct pipe_buffer** buffer, unsigned* stride); -struct pipe_buffer* radeon_buffer_from_handle(struct pipe_screen* screen, +struct pipe_buffer* radeon_buffer_from_handle(struct drm_api* api, + struct pipe_screen* screen, const char* name, unsigned handle); -boolean radeon_handle_from_buffer(struct pipe_screen* screen, +boolean radeon_handle_from_buffer(struct drm_api* api, + struct pipe_screen* screen, struct pipe_buffer* buffer, unsigned* handle); -boolean radeon_global_handle_from_buffer(struct pipe_screen* screen, +boolean radeon_global_handle_from_buffer(struct drm_api* api, + struct pipe_screen* screen, struct pipe_buffer* buffer, unsigned* handle); +void radeon_destroy_drm_api(struct drm_api* api); #endif diff --git a/src/gallium/winsys/drm/radeon/core/radeon_r300.c b/src/gallium/winsys/drm/radeon/core/radeon_r300.c index da233203d7d..4e9a2ddd161 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_r300.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_r300.c @@ -22,54 +22,30 @@ #include "radeon_r300.h" -static void radeon_r300_add_buffer(struct r300_winsys* winsys, - struct pipe_buffer* pbuffer, - uint32_t rd, - uint32_t wd) +static boolean radeon_r300_add_buffer(struct r300_winsys* winsys, + struct pipe_buffer* pbuffer, + uint32_t rd, + uint32_t wd) { - int i; struct radeon_winsys_priv* priv = (struct radeon_winsys_priv*)winsys->radeon_winsys; - struct radeon_cs_space_check* sc = priv->sc; struct radeon_bo* bo = ((struct radeon_pipe_buffer*)pbuffer)->bo; - /* Check to see if this BO is already in line for validation; - * find a slot for it otherwise. */ - for (i = 0; i < RADEON_MAX_BOS; i++) { - if (sc[i].bo == bo) { - return; - } else if (sc[i].bo == NULL) { - sc[i].bo = bo; - sc[i].read_domains = rd; - sc[i].write_domain = wd; - priv->bo_count = i + 1; - return; - } - } - - assert(FALSE && "Oh God too many BOs!"); + radeon_cs_space_add_persistent_bo(priv->cs, bo, rd, wd); + return TRUE; } static boolean radeon_r300_validate(struct r300_winsys* winsys) { - int retval; struct radeon_winsys_priv* priv = (struct radeon_winsys_priv*)winsys->radeon_winsys; - struct radeon_cs_space_check* sc = priv->sc; - - retval = radeon_cs_space_check(priv->cs, sc, priv->bo_count); - if (retval == RADEON_CS_SPACE_OP_TO_BIG) { - /* We might as well HCF, since this is not going to fit in the card, - * period. */ - exit(1); - } else if (retval == RADEON_CS_SPACE_FLUSH) { - /* We must flush before more rendering can commence. */ - return TRUE; + if (radeon_cs_space_check(priv->cs) < 0) { + return FALSE; } /* Things are fine, we can proceed as normal. */ - return FALSE; + return TRUE; } static boolean radeon_r300_check_cs(struct r300_winsys* winsys, int size) @@ -108,9 +84,15 @@ static void radeon_r300_write_cs_reloc(struct r300_winsys* winsys, { struct radeon_winsys_priv* priv = (struct radeon_winsys_priv*)winsys->radeon_winsys; + int retval = 0; - radeon_cs_write_reloc(priv->cs, + retval = radeon_cs_write_reloc(priv->cs, ((struct radeon_pipe_buffer*)pbuffer)->bo, rd, wd, flags); + + if (retval) { + debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n", + pbuffer, rd, wd, flags); + } } static void radeon_r300_end_cs(struct r300_winsys* winsys, @@ -128,57 +110,56 @@ static void radeon_r300_flush_cs(struct r300_winsys* winsys) { struct radeon_winsys_priv* priv = (struct radeon_winsys_priv*)winsys->radeon_winsys; - int retval = 0; + int retval; + /* Emit the CS. */ retval = radeon_cs_emit(priv->cs); if (retval) { debug_printf("radeon: Bad CS, dumping...\n"); radeon_cs_print(priv->cs, stderr); } + + /* Clean out BOs. */ + radeon_cs_space_reset_bos(priv->cs); + + /* Reset CS. + * Someday, when we care about performance, we should really find a way + * to rotate between two or three CS objects so that the GPU can be + * spinning through one CS while another one is being filled. */ radeon_cs_erase(priv->cs); } /* Helper function to do the ioctls needed for setup and init. */ static void do_ioctls(struct r300_winsys* winsys, int fd) { - struct drm_radeon_gem_info info; - drm_radeon_getparam_t gp; - int target; + struct drm_radeon_gem_info gem_info = {0}; + struct drm_radeon_info info = {0}; + int target = 0; int retval; - gp.value = ⌖ - - /* First, get the number of pixel pipes */ - gp.param = RADEON_PARAM_NUM_GB_PIPES; - retval = drmCommandWriteRead(fd, DRM_RADEON_GETPARAM, &gp, sizeof(gp)); - if (retval) { - fprintf(stderr, "%s: Failed to get GB pipe count, error number %d\n", - __FUNCTION__, retval); - exit(1); - } - winsys->gb_pipes = target; + info.value = ⌖ - /* Then, get PCI ID */ - gp.param = RADEON_PARAM_DEVICE_ID; - retval = drmCommandWriteRead(fd, DRM_RADEON_GETPARAM, &gp, sizeof(gp)); + /* First, get PCI ID */ + info.request = RADEON_INFO_DEVICE_ID; + retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)); if (retval) { - fprintf(stderr, "%s: Failed to get PCI ID, error number %d\n", - __FUNCTION__, retval); + fprintf(stderr, "%s: Failed to get PCI ID, " + "error number %d\n", __FUNCTION__, retval); exit(1); } winsys->pci_id = target; - /* Finally, retrieve MM info */ + /* Then, retrieve MM info */ retval = drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO, - &info, sizeof(info)); + &gem_info, sizeof(gem_info)); if (retval) { fprintf(stderr, "%s: Failed to get MM info, error number %d\n", __FUNCTION__, retval); exit(1); } - winsys->gart_size = info.gart_size; + winsys->gart_size = gem_info.gart_size; /* XXX */ - winsys->vram_size = info.vram_visible; + winsys->vram_size = gem_info.vram_visible; } struct r300_winsys* diff --git a/src/gallium/winsys/drm/radeon/core/radeon_r300.h b/src/gallium/winsys/drm/radeon/core/radeon_r300.h index 5c373cd0848..741c1371889 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_r300.h +++ b/src/gallium/winsys/drm/radeon/core/radeon_r300.h @@ -20,6 +20,9 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#ifndef RADEON_R300_H +#define RADEON_R300_H + /* XXX WTF is this! I shouldn't have to include those first three! FUCK! */ #include <stdint.h> #include <stdlib.h> @@ -31,5 +34,9 @@ #include "radeon_buffer.h" +struct radeon_winsys; + struct r300_winsys* radeon_create_r300_winsys(int fd, struct radeon_winsys* old_winsys); + +#endif /* RADEON_R300_H */ diff --git a/src/gallium/winsys/drm/radeon/dri/Makefile b/src/gallium/winsys/drm/radeon/dri/Makefile index c218ee9d010..a9889444de8 100644 --- a/src/gallium/winsys/drm/radeon/dri/Makefile +++ b/src/gallium/winsys/drm/radeon/dri/Makefile @@ -10,6 +10,7 @@ PIPE_DRIVERS = \ $(TOP)/src/gallium/state_trackers/dri/libdridrm.a \ $(TOP)/src/gallium/winsys/drm/radeon/core/libradeonwinsys.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ $(TOP)/src/gallium/drivers/r300/libr300.a C_SOURCES = \ diff --git a/src/gallium/winsys/drm/radeon/dri/SConscript b/src/gallium/winsys/drm/radeon/dri/SConscript index f2cdee97d92..aea987a3aca 100644 --- a/src/gallium/winsys/drm/radeon/dri/SConscript +++ b/src/gallium/winsys/drm/radeon/dri/SConscript @@ -2,7 +2,10 @@ Import('*') env = drienv.Clone() +env.ParseConfig('pkg-config --cflags --libs libdrm_radeon') + drivers = [ + trace, softpipe, r300 ] @@ -10,5 +13,5 @@ drivers = [ env.SharedLibrary( target ='radeon_dri.so', source = COMMON_GALLIUM_SOURCES, - LIBS = drivers + mesa + auxiliaries + env['LIBS'], + LIBS = st_dri + radeonwinsys + mesa + drivers + auxiliaries + env['LIBS'], ) diff --git a/src/gallium/winsys/drm/radeon/egl/Makefile b/src/gallium/winsys/drm/radeon/egl/Makefile index d989b3aa935..6a1448d1b9b 100644 --- a/src/gallium/winsys/drm/radeon/egl/Makefile +++ b/src/gallium/winsys/drm/radeon/egl/Makefile @@ -8,6 +8,7 @@ PIPE_DRIVERS = \ $(TOP)/src/gallium/state_trackers/egl/libegldrm.a \ $(GALLIUMDIR)/winsys/drm/radeon/core/libradeonwinsys.a \ $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \ + $(TOP)/src/gallium/drivers/trace/libtrace.a \ $(TOP)/src/gallium/drivers/r300/libr300.a DRIVER_SOURCES = diff --git a/src/gallium/winsys/drm/radeon/xorg/Makefile b/src/gallium/winsys/drm/radeon/xorg/Makefile index 6ffd4a3a541..0241625f69b 100644 --- a/src/gallium/winsys/drm/radeon/xorg/Makefile +++ b/src/gallium/winsys/drm/radeon/xorg/Makefile @@ -37,6 +37,6 @@ clean: install: $(INSTALL) -d $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR) - $(INSTALL) -m 755 $(TARGET) $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR) + $(MINSTALL) -m 755 $(TARGET) $(DESTDIR)/$(XORG_DRIVER_INSTALL_DIR) .PHONY = all clean install diff --git a/src/gallium/winsys/egl_xlib/Makefile b/src/gallium/winsys/egl_xlib/Makefile index 8646ee3b527..a33a50ec22b 100644 --- a/src/gallium/winsys/egl_xlib/Makefile +++ b/src/gallium/winsys/egl_xlib/Makefile @@ -74,7 +74,7 @@ depend: $(ALL_SOURCES) install: default $(INSTALL) -d $(INSTALL_DIR)/$(LIB_DIR) @if [ -e $(TOP)/$(LIB_DIR) ]; then \ - $(INSTALL) $(TOP)/$(LIB_DIR)/$(DRIVER_NAME) $(INSTALL_DIR)/$(LIB_DIR); \ + $(MINSTALL) $(TOP)/$(LIB_DIR)/$(DRIVER_NAME) $(INSTALL_DIR)/$(LIB_DIR); \ fi diff --git a/src/gallium/winsys/egl_xlib/egl_xlib.c b/src/gallium/winsys/egl_xlib/egl_xlib.c index b52f427e4a7..e1ddcae97ba 100644 --- a/src/gallium/winsys/egl_xlib/egl_xlib.c +++ b/src/gallium/winsys/egl_xlib/egl_xlib.c @@ -345,7 +345,7 @@ xlib_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, return EGL_NO_CONTEXT; /* let EGL lib init the common stuff */ - if (!_eglInitContext(drv, dpy, &ctx->Base, config, attrib_list)) { + if (!_eglInitContext(drv, &ctx->Base, conf, attrib_list)) { free(ctx); return EGL_NO_CONTEXT; } @@ -370,7 +370,7 @@ xlib_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, return EGL_NO_CONTEXT; } - _eglSaveContext(&ctx->Base); + _eglLinkContext(&ctx->Base, _eglLookupDisplay(dpy)); return _eglGetContextHandle(&ctx->Base); } @@ -381,10 +381,8 @@ xlib_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx) { struct xlib_egl_context *context = lookup_context(ctx); if (context) { - if (context->Base.IsBound) { - context->Base.DeletePending = EGL_TRUE; - } - else { + _eglUnlinkContext(&context->Base); + if (!context->Base.IsBound) { /* API-dependent clean-up */ switch (context->Base.ClientAPI) { case EGL_OPENGL_ES_API: @@ -491,13 +489,13 @@ xlib_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, return EGL_NO_SURFACE; /* Let EGL lib init the common stuff */ - if (!_eglInitSurface(drv, dpy, &surf->Base, EGL_WINDOW_BIT, - config, attrib_list)) { + if (!_eglInitSurface(drv, &surf->Base, EGL_WINDOW_BIT, + conf, attrib_list)) { free(surf); return EGL_NO_SURFACE; } - _eglSaveSurface(&surf->Base); + _eglLinkSurface(&surf->Base, disp); /* * Now init the Xlib and gallium stuff @@ -534,11 +532,8 @@ xlib_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) { struct xlib_egl_surface *surf = lookup_surface(surface); if (surf) { - _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface); - if (surf->Base.IsBound) { - surf->Base.DeletePending = EGL_TRUE; - } - else { + _eglUnlinkSurface(&surf->Base); + if (!surf->Base.IsBound) { XFreeGC(surf->Dpy, surf->Gc); st_unreference_framebuffer(surf->Framebuffer); free(surf); @@ -588,7 +583,9 @@ find_supported_apis(void) EGLint mask = 0; void *handle; - handle = dlopen(NULL, 0); + handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL); + if(!handle) + return mask; if (dlsym(handle, "st_api_OpenGL_ES1")) mask |= EGL_OPENGL_ES_BIT; diff --git a/src/gallium/winsys/gdi/SConscript b/src/gallium/winsys/gdi/SConscript index aabab95f3a8..86eb9ef55ed 100644 --- a/src/gallium/winsys/gdi/SConscript +++ b/src/gallium/winsys/gdi/SConscript @@ -15,6 +15,7 @@ if env['platform'] == 'windows': 'gdi32', 'user32', 'kernel32', + 'ws2_32', ]) sources = [ diff --git a/src/gallium/winsys/xlib/Makefile b/src/gallium/winsys/xlib/Makefile index 04309e67eea..522f6dc5aee 100644 --- a/src/gallium/winsys/xlib/Makefile +++ b/src/gallium/winsys/xlib/Makefile @@ -90,7 +90,7 @@ install: default $(INSTALL) -d $(INSTALL_DIR)/$(LIB_DIR) $(INSTALL) -m 644 $(TOP)/include/GL/*.h $(INSTALL_DIR)/include/GL @if [ -e $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) ]; then \ - $(INSTALL) $(TOP)/$(LIB_DIR)/libGL* $(INSTALL_DIR)/$(LIB_DIR); \ + $(MINSTALL) $(TOP)/$(LIB_DIR)/libGL* $(INSTALL_DIR)/$(LIB_DIR); \ fi |