diff options
Diffstat (limited to 'src/gallium/auxiliary/draw')
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pipe_vbuf.c | 95 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt.h | 2 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt_emit.c | 67 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt_fetch_emit.c | 69 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c | 104 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c | 2 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_vbuf.h | 16 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_vs_aos.c | 43 |
8 files changed, 208 insertions, 190 deletions
diff --git a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c index 9153bc2f865..12325d30d61 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_vbuf.c +++ b/src/gallium/auxiliary/draw/draw_pipe_vbuf.c @@ -29,12 +29,12 @@ * \file * Vertex buffer drawing stage. * - * \author Jos� Fonseca <[email protected]> + * \author Jose Fonseca <[email protected]> * \author Keith Whitwell <[email protected]> */ -#include "pipe/p_debug.h" +#include "util/u_debug.h" #include "util/u_math.h" #include "util/u_memory.h" @@ -93,7 +93,6 @@ vbuf_stage( struct draw_stage *stage ) } -static void vbuf_flush_indices( struct vbuf_stage *vbuf ); static void vbuf_flush_vertices( struct vbuf_stage *vbuf ); static void vbuf_alloc_vertices( struct vbuf_stage *vbuf ); @@ -109,13 +108,12 @@ overflow( void *map, void *ptr, unsigned bytes, unsigned bufsz ) static INLINE void check_space( struct vbuf_stage *vbuf, unsigned nr ) { - if (vbuf->nr_vertices + nr > vbuf->max_vertices ) { - vbuf_flush_vertices(vbuf); - vbuf_alloc_vertices(vbuf); + if (vbuf->nr_vertices + nr > vbuf->max_vertices || + vbuf->nr_indices + nr > vbuf->max_indices) + { + vbuf_flush_vertices( vbuf ); + vbuf_alloc_vertices( vbuf ); } - - if (vbuf->nr_indices + nr > vbuf->max_indices ) - vbuf_flush_indices(vbuf); } @@ -202,7 +200,7 @@ vbuf_point( struct draw_stage *stage, * will be flushed if needed and a new one allocated. */ static void -vbuf_set_prim( struct vbuf_stage *vbuf, uint prim ) +vbuf_start_prim( struct vbuf_stage *vbuf, uint prim ) { struct translate_key hw_key; unsigned dst_offset; @@ -217,11 +215,7 @@ vbuf_set_prim( struct vbuf_stage *vbuf, uint prim ) * state change. */ vbuf->vinfo = vbuf->render->get_vertex_info(vbuf->render); - - if (vbuf->vertex_size != vbuf->vinfo->size * sizeof(float)) { - vbuf_flush_vertices(vbuf); - vbuf->vertex_size = vbuf->vinfo->size * sizeof(float); - } + vbuf->vertex_size = vbuf->vinfo->size * sizeof(float); /* Translate from pipeline vertices to hw vertices. */ @@ -294,8 +288,8 @@ vbuf_set_prim( struct vbuf_stage *vbuf, uint prim ) /* Allocate new buffer? */ - if (!vbuf->vertices) - vbuf_alloc_vertices(vbuf); + assert(vbuf->vertices == NULL); + vbuf_alloc_vertices(vbuf); } @@ -305,9 +299,9 @@ vbuf_first_tri( struct draw_stage *stage, { struct vbuf_stage *vbuf = vbuf_stage( stage ); - vbuf_flush_indices( vbuf ); + vbuf_flush_vertices( vbuf ); + vbuf_start_prim(vbuf, PIPE_PRIM_TRIANGLES); stage->tri = vbuf_tri; - vbuf_set_prim(vbuf, PIPE_PRIM_TRIANGLES); stage->tri( stage, prim ); } @@ -318,9 +312,9 @@ vbuf_first_line( struct draw_stage *stage, { struct vbuf_stage *vbuf = vbuf_stage( stage ); - vbuf_flush_indices( vbuf ); + vbuf_flush_vertices( vbuf ); + vbuf_start_prim(vbuf, PIPE_PRIM_LINES); stage->line = vbuf_line; - vbuf_set_prim(vbuf, PIPE_PRIM_LINES); stage->line( stage, prim ); } @@ -331,53 +325,42 @@ vbuf_first_point( struct draw_stage *stage, { struct vbuf_stage *vbuf = vbuf_stage( stage ); - vbuf_flush_indices( vbuf ); + vbuf_flush_vertices(vbuf); + vbuf_start_prim(vbuf, PIPE_PRIM_POINTS); stage->point = vbuf_point; - vbuf_set_prim(vbuf, PIPE_PRIM_POINTS); stage->point( stage, prim ); } -static void -vbuf_flush_indices( struct vbuf_stage *vbuf ) -{ - if(!vbuf->nr_indices) - return; - - assert((uint) (vbuf->vertex_ptr - vbuf->vertices) == - vbuf->nr_vertices * vbuf->vertex_size / sizeof(unsigned)); - - vbuf->render->draw(vbuf->render, vbuf->indices, vbuf->nr_indices); - - vbuf->nr_indices = 0; -} - /** * Flush existing vertex buffer and allocate a new one. - * - * XXX: We separate flush-on-index-full and flush-on-vb-full, but may - * raise issues uploading vertices if the hardware wants to flush when - * we flush. */ static void vbuf_flush_vertices( struct vbuf_stage *vbuf ) { - if(vbuf->vertices) { - vbuf_flush_indices(vbuf); - + if(vbuf->vertices) { + + vbuf->render->unmap_vertices( vbuf->render, 0, vbuf->nr_vertices - 1 ); + + if (vbuf->nr_indices) + { + vbuf->render->draw(vbuf->render, + vbuf->indices, + vbuf->nr_indices ); + + vbuf->nr_indices = 0; + } + /* Reset temporary vertices ids */ if(vbuf->nr_vertices) draw_reset_vertex_ids( vbuf->stage.draw ); /* Free the vertex buffer */ - vbuf->render->release_vertices(vbuf->render, - vbuf->vertices, - vbuf->vertex_size, - vbuf->nr_vertices); + vbuf->render->release_vertices( vbuf->render ); + vbuf->max_vertices = vbuf->nr_vertices = 0; vbuf->vertex_ptr = vbuf->vertices = NULL; - } } @@ -402,9 +385,12 @@ vbuf_alloc_vertices( struct vbuf_stage *vbuf ) * and it will flush itself if necessary to do so. If this does * fail, we are basically without usable hardware. */ - vbuf->vertices = (uint *) vbuf->render->allocate_vertices(vbuf->render, - (ushort) vbuf->vertex_size, - (ushort) vbuf->max_vertices); + vbuf->render->allocate_vertices(vbuf->render, + (ushort) vbuf->vertex_size, + (ushort) vbuf->max_vertices); + + vbuf->vertices = (uint *) vbuf->render->map_vertices( vbuf->render ); + vbuf->vertex_ptr = vbuf->vertices; } @@ -415,14 +401,11 @@ vbuf_flush( struct draw_stage *stage, unsigned flags ) { struct vbuf_stage *vbuf = vbuf_stage( stage ); - vbuf_flush_indices( vbuf ); + vbuf_flush_vertices( vbuf ); stage->point = vbuf_first_point; stage->line = vbuf_first_line; stage->tri = vbuf_first_tri; - - if (flags & DRAW_FLUSH_BACKEND) - vbuf_flush_vertices( vbuf ); } diff --git a/src/gallium/auxiliary/draw/draw_pt.h b/src/gallium/auxiliary/draw/draw_pt.h index c02f229110a..aecaeee5b9e 100644 --- a/src/gallium/auxiliary/draw/draw_pt.h +++ b/src/gallium/auxiliary/draw/draw_pt.h @@ -173,9 +173,7 @@ void draw_pt_emit( struct pt_emit *emit, void draw_pt_emit_linear( struct pt_emit *emit, const float (*vertex_data)[4], - unsigned vertex_count, unsigned stride, - unsigned start, unsigned count ); void draw_pt_emit_destroy( struct pt_emit *emit ); diff --git a/src/gallium/auxiliary/draw/draw_pt_emit.c b/src/gallium/auxiliary/draw/draw_pt_emit.c index 232dfdaed2d..064e16c295c 100644 --- a/src/gallium/auxiliary/draw/draw_pt_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_emit.c @@ -165,6 +165,9 @@ void draw_pt_emit( struct pt_emit *emit, */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); + if (vertex_count == 0) + return; + if (vertex_count >= UNDEFINED_VERTEX_ID) { assert(0); return; @@ -178,9 +181,11 @@ void draw_pt_emit( struct pt_emit *emit, return; } - hw_verts = render->allocate_vertices(render, - (ushort)translate->key.output_stride, - (ushort)vertex_count); + render->allocate_vertices(render, + (ushort)translate->key.output_stride, + (ushort)vertex_count); + + hw_verts = render->map_vertices( render ); if (!hw_verts) { assert(0); return; @@ -201,22 +206,21 @@ void draw_pt_emit( struct pt_emit *emit, vertex_count, hw_verts ); + render->unmap_vertices( render, + 0, + vertex_count - 1 ); + render->draw(render, elts, count); - render->release_vertices(render, - hw_verts, - translate->key.output_stride, - vertex_count); + render->release_vertices(render); } void draw_pt_emit_linear(struct pt_emit *emit, const float (*vertex_data)[4], - unsigned vertex_count, unsigned stride, - unsigned start, unsigned count) { struct draw_context *draw = emit->draw; @@ -231,26 +235,23 @@ void draw_pt_emit_linear(struct pt_emit *emit, */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); - if (count >= UNDEFINED_VERTEX_ID) { - assert(0); - return; - } + if (count >= UNDEFINED_VERTEX_ID) + goto fail; /* XXX: and work out some way to coordinate the render primitive * between vbuf.c and here... */ - if (!draw->render->set_primitive(draw->render, emit->prim)) { - assert(0); - return; - } + if (!draw->render->set_primitive(draw->render, emit->prim)) + goto fail; - hw_verts = render->allocate_vertices(render, - (ushort)translate->key.output_stride, - (ushort)count); - if (!hw_verts) { - assert(0); - return; - } + if (!render->allocate_vertices(render, + (ushort)translate->key.output_stride, + (ushort)count)) + goto fail; + + hw_verts = render->map_vertices( render ); + if (!hw_verts) + goto fail; translate->set_buffer(translate, 0, vertex_data, stride); @@ -261,12 +262,12 @@ void draw_pt_emit_linear(struct pt_emit *emit, translate->run(translate, 0, - vertex_count, + count, hw_verts); if (0) { unsigned i; - for (i = 0; i < vertex_count; i++) { + for (i = 0; i < count; i++) { debug_printf("\n\n%s vertex %d:\n", __FUNCTION__, i); draw_dump_emitted_vertex( emit->vinfo, (const uint8_t *)hw_verts + @@ -274,13 +275,17 @@ void draw_pt_emit_linear(struct pt_emit *emit, } } + render->unmap_vertices( render, 0, count - 1 ); + + render->draw_arrays(render, 0, count); + + render->release_vertices(render); - render->draw_arrays(render, start, count); + return; - render->release_vertices(render, - hw_verts, - translate->key.output_stride, - vertex_count); +fail: + assert(0); + return; } struct pt_emit *draw_pt_emit_create( struct draw_context *draw ) diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c index dcb7744b177..6b7d02a19bc 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_emit.c @@ -234,9 +234,11 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle, return; } - hw_verts = draw->render->allocate_vertices( draw->render, - (ushort)feme->translate->key.output_stride, - (ushort)fetch_count ); + draw->render->allocate_vertices( draw->render, + (ushort)feme->translate->key.output_stride, + (ushort)fetch_count ); + + hw_verts = draw->render->map_vertices( draw->render ); if (!hw_verts) { assert(0); return; @@ -259,6 +261,10 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle, } } + draw->render->unmap_vertices( draw->render, + 0, + (ushort)(fetch_count - 1) ); + /* XXX: Draw arrays path to avoid re-emitting index list again and * again. */ @@ -268,10 +274,7 @@ static void fetch_emit_run( struct draw_pt_middle_end *middle, /* Done -- that was easy, wasn't it: */ - draw->render->release_vertices( draw->render, - hw_verts, - feme->translate->key.output_stride, - fetch_count ); + draw->render->release_vertices( draw->render ); } @@ -288,18 +291,17 @@ static void fetch_emit_run_linear( struct draw_pt_middle_end *middle, */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); - if (count >= UNDEFINED_VERTEX_ID) { - assert(0); - return; - } + if (count >= UNDEFINED_VERTEX_ID) + goto fail; - hw_verts = draw->render->allocate_vertices( draw->render, - (ushort)feme->translate->key.output_stride, - (ushort)count ); - if (!hw_verts) { - assert(0); - return; - } + if (!draw->render->allocate_vertices( draw->render, + (ushort)feme->translate->key.output_stride, + (ushort)count )) + goto fail; + + hw_verts = draw->render->map_vertices( draw->render ); + if (!hw_verts) + goto fail; /* Single routine to fetch vertices and emit HW verts. */ @@ -317,20 +319,21 @@ static void fetch_emit_run_linear( struct draw_pt_middle_end *middle, } } + draw->render->unmap_vertices( draw->render, 0, count - 1 ); + /* XXX: Draw arrays path to avoid re-emitting index list again and * again. */ - draw->render->draw_arrays( draw->render, - 0, /*start*/ - count ); + draw->render->draw_arrays( draw->render, 0, count ); /* Done -- that was easy, wasn't it: */ - draw->render->release_vertices( draw->render, - hw_verts, - feme->translate->key.output_stride, - count ); + draw->render->release_vertices( draw->render ); + return; +fail: + assert(0); + return; } @@ -351,9 +354,12 @@ static boolean fetch_emit_run_linear_elts( struct draw_pt_middle_end *middle, if (count >= UNDEFINED_VERTEX_ID) return FALSE; - hw_verts = draw->render->allocate_vertices( draw->render, - (ushort)feme->translate->key.output_stride, - (ushort)count ); + if (!draw->render->allocate_vertices( draw->render, + (ushort)feme->translate->key.output_stride, + (ushort)count )) + return FALSE; + + hw_verts = draw->render->map_vertices( draw->render ); if (!hw_verts) return FALSE; @@ -364,6 +370,8 @@ static boolean fetch_emit_run_linear_elts( struct draw_pt_middle_end *middle, count, hw_verts ); + draw->render->unmap_vertices( draw->render, 0, (ushort)(count - 1) ); + /* XXX: Draw arrays path to avoid re-emitting index list again and * again. */ @@ -373,10 +381,7 @@ static boolean fetch_emit_run_linear_elts( struct draw_pt_middle_end *middle, /* Done -- that was easy, wasn't it: */ - draw->render->release_vertices( draw->render, - hw_verts, - feme->translate->key.output_stride, - count ); + draw->render->release_vertices( draw->render ); return TRUE; } diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c index 84ffe3296af..cd9cd4b53fd 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c @@ -234,19 +234,17 @@ static void fse_run_linear( struct draw_pt_middle_end *middle, */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); - if (count >= UNDEFINED_VERTEX_ID) { - assert(0); - return; - } + if (count >= UNDEFINED_VERTEX_ID) + goto fail; - hw_verts = draw->render->allocate_vertices( draw->render, - (ushort)fse->key.output_stride, - (ushort)count ); + if (!draw->render->allocate_vertices( draw->render, + (ushort)fse->key.output_stride, + (ushort)count )) + goto fail; - if (!hw_verts) { - assert(0); - return; - } + hw_verts = draw->render->map_vertices( draw->render ); + if (!hw_verts) + goto fail; /* Single routine to fetch vertices, run shader and emit HW verts. * Clipping is done elsewhere -- either by the API or on hardware, @@ -256,13 +254,7 @@ static void fse_run_linear( struct draw_pt_middle_end *middle, start, count, hw_verts ); - /* Draw arrays path to avoid re-emitting index list again and - * again. - */ - draw->render->draw_arrays( draw->render, - 0, - count ); - + if (0) { unsigned i; for (i = 0; i < count; i++) { @@ -274,12 +266,24 @@ static void fse_run_linear( struct draw_pt_middle_end *middle, (const uint8_t *)hw_verts + fse->key.output_stride * i ); } } + + draw->render->unmap_vertices( draw->render, 0, (ushort)(count - 1) ); + /* Draw arrays path to avoid re-emitting index list again and + * again. + */ + draw->render->draw_arrays( draw->render, + 0, + count ); + + + draw->render->release_vertices( draw->render ); + + return; - draw->render->release_vertices( draw->render, - hw_verts, - fse->key.output_stride, - count ); +fail: + assert(0); + return; } @@ -298,18 +302,17 @@ fse_run(struct draw_pt_middle_end *middle, */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); - if (fetch_count >= UNDEFINED_VERTEX_ID) { - assert(0); - return; - } + if (fetch_count >= UNDEFINED_VERTEX_ID) + goto fail; - hw_verts = draw->render->allocate_vertices( draw->render, - (ushort)fse->key.output_stride, - (ushort)fetch_count ); - if (!hw_verts) { - assert(0); - return; - } + if (!draw->render->allocate_vertices( draw->render, + (ushort)fse->key.output_stride, + (ushort)fetch_count )) + goto fail; + + hw_verts = draw->render->map_vertices( draw->render ); + if (!hw_verts) + goto fail; /* Single routine to fetch vertices, run shader and emit HW verts. @@ -319,9 +322,6 @@ fse_run(struct draw_pt_middle_end *middle, fetch_count, hw_verts ); - draw->render->draw( draw->render, - draw_elts, - draw_count ); if (0) { unsigned i; @@ -333,12 +333,19 @@ fse_run(struct draw_pt_middle_end *middle, } } + draw->render->unmap_vertices( draw->render, 0, (ushort)(fetch_count - 1) ); + + draw->render->draw( draw->render, + draw_elts, + draw_count ); + - draw->render->release_vertices( draw->render, - hw_verts, - fse->key.output_stride, - fetch_count ); + draw->render->release_vertices( draw->render ); + return; +fail: + assert(0); + return; } @@ -360,13 +367,14 @@ static boolean fse_run_linear_elts( struct draw_pt_middle_end *middle, if (count >= UNDEFINED_VERTEX_ID) return FALSE; - hw_verts = draw->render->allocate_vertices( draw->render, - (ushort)fse->key.output_stride, - (ushort)count ); + if (!draw->render->allocate_vertices( draw->render, + (ushort)fse->key.output_stride, + (ushort)count )) + return FALSE; - if (!hw_verts) { + hw_verts = draw->render->map_vertices( draw->render ); + if (!hw_verts) return FALSE; - } /* Single routine to fetch vertices, run shader and emit HW verts. * Clipping is done elsewhere -- either by the API or on hardware, @@ -382,11 +390,9 @@ static boolean fse_run_linear_elts( struct draw_pt_middle_end *middle, draw_count ); + draw->render->unmap_vertices( draw->render, 0, (ushort)(count - 1) ); - draw->render->release_vertices( draw->render, - hw_verts, - fse->key.output_stride, - count ); + draw->render->release_vertices( draw->render ); return TRUE; } diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c index ec3b41c320a..38f9b604d37 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c @@ -251,9 +251,7 @@ static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle, else { draw_pt_emit_linear( fpme->emit, (const float (*)[4])pipeline_verts->data, - count, fpme->vertex_size, - 0, /*start*/ count ); } diff --git a/src/gallium/auxiliary/draw/draw_vbuf.h b/src/gallium/auxiliary/draw/draw_vbuf.h index a1c4c14445b..cccd3bf4358 100644 --- a/src/gallium/auxiliary/draw/draw_vbuf.h +++ b/src/gallium/auxiliary/draw/draw_vbuf.h @@ -80,9 +80,14 @@ struct vbuf_render { * Hardware renderers will use ttm memory, others will just malloc * something. */ - void *(*allocate_vertices)( struct vbuf_render *, - ushort vertex_size, - ushort nr_vertices ); + boolean (*allocate_vertices)( struct vbuf_render *, + ushort vertex_size, + ushort nr_vertices ); + + void *(*map_vertices)( struct vbuf_render * ); + void (*unmap_vertices)( struct vbuf_render *, + ushort min_index, + ushort max_index ); /** * Notify the renderer of the current primitive when it changes. @@ -109,10 +114,7 @@ struct vbuf_render { /** * Called when vbuf is done with this set of vertices: */ - void (*release_vertices)( struct vbuf_render *, - void *vertices, - unsigned vertex_size, - unsigned vertices_used ); + void (*release_vertices)( struct vbuf_render * ); void (*destroy)( struct vbuf_render * ); }; diff --git a/src/gallium/auxiliary/draw/draw_vs_aos.c b/src/gallium/auxiliary/draw/draw_vs_aos.c index 0c693a4a65c..1fb69ef81ad 100644 --- a/src/gallium/auxiliary/draw/draw_vs_aos.c +++ b/src/gallium/auxiliary/draw/draw_vs_aos.c @@ -32,7 +32,7 @@ #include "util/u_memory.h" #include "util/u_math.h" #include "pipe/p_shader_tokens.h" -#include "pipe/p_debug.h" +#include "util/u_debug.h" #include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_util.h" #include "tgsi/tgsi_exec.h" @@ -284,6 +284,15 @@ void aos_release_xmm_reg( struct aos_compilation *cp, } +static void aos_soft_release_xmm( struct aos_compilation *cp, + struct x86_reg reg ) +{ + if (reg.file == file_XMM) { + assert(cp->xmm[reg.idx].last_used == cp->insn_counter); + cp->xmm[reg.idx].last_used = cp->insn_counter - 1; + } +} + /* Mark an xmm reg as holding the current copy of a shader reg. @@ -584,10 +593,12 @@ static struct x86_reg fetch_src( struct aos_compilation *cp, sse_mulps(cp->func, dst, tmp); aos_release_xmm_reg(cp, tmp.idx); + aos_soft_release_xmm(cp, imm_swz); } else if (negs) { struct x86_reg imm_negs = aos_get_internal_xmm(cp, IMM_NEGS); sse_mulps(cp->func, dst, imm_negs); + aos_soft_release_xmm(cp, imm_negs); } @@ -603,8 +614,10 @@ static struct x86_reg fetch_src( struct aos_compilation *cp, sse_maxps(cp->func, dst, tmp); aos_release_xmm_reg(cp, tmp.idx); + aos_soft_release_xmm(cp, neg); } + aos_soft_release_xmm(cp, arg0); return dst; } @@ -1559,7 +1572,6 @@ static boolean emit_RCP( struct aos_compilation *cp, const struct tgsi_full_inst */ static boolean emit_RSQ( struct aos_compilation *cp, const struct tgsi_full_instruction *op ) { - if (0) { struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); struct x86_reg r = aos_get_xmm_reg(cp); @@ -1568,21 +1580,30 @@ static boolean emit_RSQ( struct aos_compilation *cp, const struct tgsi_full_inst return TRUE; } else { - struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); - struct x86_reg r = aos_get_xmm_reg(cp); + struct x86_reg arg0 = fetch_src(cp, &op->FullSrcRegisters[0]); + struct x86_reg r = aos_get_xmm_reg(cp); struct x86_reg neg_half = get_reg_ptr( cp, AOS_FILE_INTERNAL, IMM_RSQ ); struct x86_reg one_point_five = x86_make_disp( neg_half, 4 ); struct x86_reg src = get_xmm_writable( cp, arg0 ); - - sse_rsqrtss( cp->func, r, src ); /* rsqrtss(a) */ - sse_mulss( cp->func, src, neg_half ); /* -.5 * a */ - sse_mulss( cp->func, src, r ); /* -.5 * a * r */ - sse_mulss( cp->func, src, r ); /* -.5 * a * r * r */ - sse_addss( cp->func, src, one_point_five ); /* 1.5 - .5 * a * r * r */ - sse_mulss( cp->func, r, src ); /* r * (1.5 - .5 * a * r * r) */ + struct x86_reg neg = aos_get_internal(cp, IMM_NEGS); + struct x86_reg tmp = aos_get_xmm_reg(cp); + + sse_movaps(cp->func, tmp, src); + sse_mulps(cp->func, tmp, neg); + sse_maxps(cp->func, tmp, src); + + sse_rsqrtss( cp->func, r, tmp ); /* rsqrtss(a) */ + sse_mulss( cp->func, tmp, neg_half ); /* -.5 * a */ + sse_mulss( cp->func, tmp, r ); /* -.5 * a * r */ + sse_mulss( cp->func, tmp, r ); /* -.5 * a * r * r */ + sse_addss( cp->func, tmp, one_point_five ); /* 1.5 - .5 * a * r * r */ + sse_mulss( cp->func, r, tmp ); /* r * (1.5 - .5 * a * r * r) */ store_scalar_dest(cp, &op->FullDstRegisters[0], r); + + aos_release_xmm_reg(cp, tmp.idx); + return TRUE; } } |