diff options
Diffstat (limited to 'src/gallium/drivers')
373 files changed, 9922 insertions, 23880 deletions
diff --git a/src/gallium/drivers/cell/common.h b/src/gallium/drivers/cell/common.h index d5f5c7bbba..7f2b33c2dc 100644 --- a/src/gallium/drivers/cell/common.h +++ b/src/gallium/drivers/cell/common.h @@ -36,7 +36,7 @@ #include "pipe/p_compiler.h" #include "pipe/p_format.h" #include "pipe/p_state.h" - +#include <stdio.h> /** The standard assert macro doesn't seem to work reliably */ #define ASSERT(x) \ @@ -49,7 +49,6 @@ } - #define JOIN(x, y) JOIN_AGAIN(x, y) #define JOIN_AGAIN(x, y) x ## y @@ -358,6 +357,7 @@ struct cell_spu_function_info /** This is the object passed to spe_create_thread() */ +PIPE_ALIGN_TYPE(16, struct cell_init_info { unsigned id; @@ -370,7 +370,7 @@ struct cell_init_info uint *buffer_status; /**< points at cell_context->buffer_status */ struct cell_spu_function_info *spu_functions; -} ALIGN16_ATTRIB; +}); #endif /* CELL_COMMON_H */ diff --git a/src/gallium/drivers/cell/ppu/cell_clear.c b/src/gallium/drivers/cell/ppu/cell_clear.c index 3a3f968a49..246fe21054 100644 --- a/src/gallium/drivers/cell/ppu/cell_clear.c +++ b/src/gallium/drivers/cell/ppu/cell_clear.c @@ -33,7 +33,7 @@ #include <stdio.h> #include <assert.h> #include <stdint.h> -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_pack_color.h" #include "cell/common.h" diff --git a/src/gallium/drivers/cell/ppu/cell_context.c b/src/gallium/drivers/cell/ppu/cell_context.c index ebb7a7acc4..5bff9869fd 100644 --- a/src/gallium/drivers/cell/ppu/cell_context.c +++ b/src/gallium/drivers/cell/ppu/cell_context.c @@ -36,7 +36,7 @@ #include "pipe/p_defines.h" #include "pipe/p_format.h" #include "util/u_memory.h" -#include "pipe/internal/p_winsys_screen.h" +#include "util/u_simple_screen.h" #include "pipe/p_screen.h" #include "draw/draw_context.h" @@ -124,7 +124,7 @@ cell_is_buffer_referenced( struct pipe_context *pipe, struct pipe_context * cell_create_context(struct pipe_screen *screen, - struct cell_winsys *cws) + void *priv ) { struct cell_context *cell; uint i; @@ -136,9 +136,10 @@ cell_create_context(struct pipe_screen *screen, memset(cell, 0, sizeof(*cell)); - cell->winsys = cws; + cell->winsys = NULL; /* XXX: fixme - get this from screen? */ cell->pipe.winsys = screen->winsys; cell->pipe.screen = screen; + cell->pipe.priv = priv; cell->pipe.destroy = cell_destroy_context; cell->pipe.clear = cell_clear; diff --git a/src/gallium/drivers/cell/ppu/cell_context.h b/src/gallium/drivers/cell/ppu/cell_context.h index 5c3188e7f9..905cd5db39 100644 --- a/src/gallium/drivers/cell/ppu/cell_context.h +++ b/src/gallium/drivers/cell/ppu/cell_context.h @@ -89,7 +89,7 @@ struct cell_buffer_node; */ struct cell_buffer_list { - struct cell_fence fence ALIGN16_ATTRIB; + PIPE_ALIGN_VAR(16) struct cell_fence fence; struct cell_buffer_node *head; }; @@ -115,7 +115,7 @@ struct cell_context struct pipe_blend_color blend_color; struct pipe_clip_state clip; - struct pipe_constant_buffer constants[2]; + struct pipe_buffer *constants[2]; struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple poly_stipple; struct pipe_scissor_state scissor; @@ -150,18 +150,18 @@ struct cell_context /** Mapped constant buffers */ void *mapped_constants[PIPE_SHADER_TYPES]; - struct cell_spu_function_info spu_functions ALIGN16_ATTRIB; + PIPE_ALIGN_VAR(16) struct cell_spu_function_info spu_functions; uint num_cells, num_spus; /** Buffers for command batches, vertex/index data */ uint buffer_size[CELL_NUM_BUFFERS]; - ubyte buffer[CELL_NUM_BUFFERS][CELL_BUFFER_SIZE] ALIGN16_ATTRIB; + PIPE_ALIGN_VAR(16) ubyte buffer[CELL_NUM_BUFFERS][CELL_BUFFER_SIZE]; int cur_batch; /**< which buffer is being filled w/ commands */ /** [4] to ensure 16-byte alignment for each status word */ - uint buffer_status[CELL_MAX_SPUS][CELL_NUM_BUFFERS][4] ALIGN16_ATTRIB; + PIPE_ALIGN_VAR(16) uint buffer_status[CELL_MAX_SPUS][CELL_NUM_BUFFERS][4]; /** Associated with each command/batch buffer is a list of pipe_buffers @@ -188,8 +188,9 @@ cell_context(struct pipe_context *pipe) } -extern struct pipe_context * -cell_create_context(struct pipe_screen *screen, struct cell_winsys *cws); +struct pipe_context * +cell_create_context(struct pipe_screen *screen, + void *priv ); extern void cell_vertex_shader_queue_flush(struct draw_context *draw); diff --git a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c index 3fa8b975d3..bffd0fac6f 100644 --- a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c +++ b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c @@ -33,8 +33,8 @@ #include "pipe/p_defines.h" #include "pipe/p_context.h" -#include "pipe/internal/p_winsys_screen.h" -#include "pipe/p_inlines.h" +#include "util/u_simple_screen.h" +#include "util/u_inlines.h" #include "cell_context.h" #include "cell_draw_arrays.h" @@ -51,17 +51,17 @@ cell_map_constant_buffers(struct cell_context *sp) struct pipe_winsys *ws = sp->pipe.winsys; uint i; for (i = 0; i < 2; i++) { - if (sp->constants[i].buffer && sp->constants[i].buffer->size) { - sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i].buffer, + if (sp->constants[i] && sp->constants[i]->size) { + sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i], PIPE_BUFFER_USAGE_CPU_READ); cell_flush_buffer_range(sp, sp->mapped_constants[i], - sp->constants[i].buffer->size); + sp->constants[i]->size); } } - draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_VERTEX, + draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_VERTEX, 0, sp->mapped_constants[PIPE_SHADER_VERTEX], - sp->constants[PIPE_SHADER_VERTEX].buffer->size); + sp->constants[PIPE_SHADER_VERTEX]->size); } static void @@ -70,8 +70,8 @@ cell_unmap_constant_buffers(struct cell_context *sp) struct pipe_winsys *ws = sp->pipe.winsys; uint i; for (i = 0; i < 2; i++) { - if (sp->constants[i].buffer && sp->constants[i].buffer->size) - ws->buffer_unmap(ws, sp->constants[i].buffer); + if (sp->constants[i] && sp->constants[i]->size) + ws->buffer_unmap(ws, sp->constants[i]); sp->mapped_constants[i] = NULL; } } diff --git a/src/gallium/drivers/cell/ppu/cell_fence.c b/src/gallium/drivers/cell/ppu/cell_fence.c index 13125a9fa3..e10071529a 100644 --- a/src/gallium/drivers/cell/ppu/cell_fence.c +++ b/src/gallium/drivers/cell/ppu/cell_fence.c @@ -27,7 +27,7 @@ #include <unistd.h> #include "util/u_memory.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "cell_context.h" #include "cell_batch.h" #include "cell_fence.h" diff --git a/src/gallium/drivers/cell/ppu/cell_gen_fragment.c b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c index 66d4b3b6a3..0dab34075d 100644 --- a/src/gallium/drivers/cell/ppu/cell_gen_fragment.c +++ b/src/gallium/drivers/cell/ppu/cell_gen_fragment.c @@ -408,7 +408,7 @@ gen_blend(const struct pipe_blend_state *blend, int one_reg = -1; int constR_reg = -1, constG_reg = -1, constB_reg = -1, constA_reg = -1; - ASSERT(blend->blend_enable); + ASSERT(blend->rt[0].blend_enable); /* packed RGBA -> float colors */ unpack_colors(f, color_format, fbRGBA_reg, @@ -420,7 +420,7 @@ gen_blend(const struct pipe_blend_state *blend, * because in some cases (like PIPE_BLENDFACTOR_ONE and * PIPE_BLENDFACTOR_ZERO) we can avoid doing unnecessary math. */ - switch (blend->rgb_src_factor) { + switch (blend->rt[0].rgb_src_factor) { case PIPE_BLENDFACTOR_ONE: /* factors = (1,1,1), so term = (R,G,B) */ spe_move(f, term1R_reg, fragR_reg); @@ -574,7 +574,7 @@ gen_blend(const struct pipe_blend_state *blend, * the full term A*factor, not just the factor itself, because * in many cases we can avoid doing unnecessary multiplies. */ - switch (blend->alpha_src_factor) { + switch (blend->rt[0].alpha_src_factor) { case PIPE_BLENDFACTOR_ZERO: /* factor = 0, so term = 0 */ spe_load_float(f, term1A_reg, 0.0f); @@ -648,7 +648,7 @@ gen_blend(const struct pipe_blend_state *blend, * the full term (Rfb,Gfb,Bfb)*(factor), not just the factor itself, because * in many cases we can avoid doing unnecessary multiplies. */ - switch (blend->rgb_dst_factor) { + switch (blend->rt[0].rgb_dst_factor) { case PIPE_BLENDFACTOR_ONE: /* factors = (1,1,1), so term = (Rfb,Gfb,Bfb) */ spe_move(f, term2R_reg, fbR_reg); @@ -786,7 +786,7 @@ gen_blend(const struct pipe_blend_state *blend, * the full term Afb*factor, not just the factor itself, because * in many cases we can avoid doing unnecessary multiplies. */ - switch (blend->alpha_dst_factor) { + switch (blend->rt[0].alpha_dst_factor) { case PIPE_BLENDFACTOR_ONE: /* factor = 1, so term = Afb */ spe_move(f, term2A_reg, fbA_reg); @@ -858,7 +858,7 @@ gen_blend(const struct pipe_blend_state *blend, /* * Combine Src/Dest RGB terms as per the blend equation. */ - switch (blend->rgb_func) { + switch (blend->rt[0].rgb_func) { case PIPE_BLEND_ADD: spe_fa(f, fragR_reg, term1R_reg, term2R_reg); spe_fa(f, fragG_reg, term1G_reg, term2G_reg); @@ -891,7 +891,7 @@ gen_blend(const struct pipe_blend_state *blend, /* * Combine Src/Dest A term */ - switch (blend->alpha_func) { + switch (blend->rt[0].alpha_func) { case PIPE_BLEND_ADD: spe_fa(f, fragA_reg, term1A_reg, term2A_reg); break; @@ -2118,7 +2118,7 @@ cell_gen_fragment_function(struct cell_context *cell, spe_comment(f, 0, "Fetch quad colors from tile"); spe_lqx(f, fbRGBA_reg, color_tile_reg, quad_offset_reg); - if (blend->blend_enable) { + if (blend->rt[0].blend_enable) { spe_comment(f, 0, "Perform blending"); gen_blend(blend, blend_color, f, color_format, fragR_reg, fragG_reg, fragB_reg, fragA_reg, fbRGBA_reg); @@ -2143,9 +2143,9 @@ cell_gen_fragment_function(struct cell_context *cell, gen_logicop(blend, f, rgba_reg, fbRGBA_reg); } - if (blend->colormask != PIPE_MASK_RGBA) { + if (blend->rt[0].colormask != PIPE_MASK_RGBA) { spe_comment(f, 0, "Compute color mask"); - gen_colormask(f, blend->colormask, color_format, rgba_reg, fbRGBA_reg); + gen_colormask(f, blend->rt[0].colormask, color_format, rgba_reg, fbRGBA_reg); } /* Mix fragment colors with framebuffer colors using the quad/pixel mask: diff --git a/src/gallium/drivers/cell/ppu/cell_pipe_state.c b/src/gallium/drivers/cell/ppu/cell_pipe_state.c index c18a5d0635..3259c58687 100644 --- a/src/gallium/drivers/cell/ppu/cell_pipe_state.c +++ b/src/gallium/drivers/cell/ppu/cell_pipe_state.c @@ -31,7 +31,7 @@ */ #include "util/u_memory.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "draw/draw_context.h" #include "cell_context.h" #include "cell_flush.h" diff --git a/src/gallium/drivers/cell/ppu/cell_screen.c b/src/gallium/drivers/cell/ppu/cell_screen.c index d185c6b849..7681e3411e 100644 --- a/src/gallium/drivers/cell/ppu/cell_screen.c +++ b/src/gallium/drivers/cell/ppu/cell_screen.c @@ -28,7 +28,7 @@ #include "util/u_memory.h" #include "util/u_simple_screen.h" -#include "pipe/internal/p_winsys_screen.h" +#include "util/u_simple_screen.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" @@ -86,6 +86,12 @@ cell_get_param(struct pipe_screen *screen, int param) return 0; /* XXX to do */ case PIPE_CAP_TGSI_CONT_SUPPORTED: return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 0; default: return 0; } @@ -168,6 +174,7 @@ cell_create_screen(struct pipe_winsys *winsys) screen->get_param = cell_get_param; screen->get_paramf = cell_get_paramf; screen->is_format_supported = cell_is_format_supported; + screen->context_create = cell_create_context; cell_init_screen_texture_funcs(screen); u_simple_screen_init(screen); diff --git a/src/gallium/drivers/cell/ppu/cell_state.h b/src/gallium/drivers/cell/ppu/cell_state.h index b193170f9c..7adedcde57 100644 --- a/src/gallium/drivers/cell/ppu/cell_state.h +++ b/src/gallium/drivers/cell/ppu/cell_state.h @@ -50,7 +50,7 @@ extern void -cell_update_derived( struct cell_context *softpipe ); +cell_update_derived( struct cell_context *cell ); extern void diff --git a/src/gallium/drivers/cell/ppu/cell_state_emit.c b/src/gallium/drivers/cell/ppu/cell_state_emit.c index 5b87286d4c..282f05ba08 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_emit.c +++ b/src/gallium/drivers/cell/ppu/cell_state_emit.c @@ -25,7 +25,7 @@ * **************************************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_math.h" #include "cell_context.h" @@ -240,12 +240,12 @@ cell_emit_state(struct cell_context *cell) if (cell->dirty & (CELL_NEW_FS_CONSTANTS)) { const uint shader = PIPE_SHADER_FRAGMENT; - const uint num_const = cell->constants[shader].buffer->size / sizeof(float); + const uint num_const = cell->constants[shader]->size / sizeof(float); uint i, j; float *buf = cell_batch_alloc16(cell, ROUNDUP16(32 + num_const * sizeof(float))); uint32_t *ibuf = (uint32_t *) buf; const float *constants = pipe_buffer_map(cell->pipe.screen, - cell->constants[shader].buffer, + cell->constants[shader], PIPE_BUFFER_USAGE_CPU_READ); ibuf[0] = CELL_CMD_STATE_FS_CONSTANTS; ibuf[4] = num_const; @@ -253,7 +253,7 @@ cell_emit_state(struct cell_context *cell) for (i = 0; i < num_const; i++) { buf[j++] = constants[i]; } - pipe_buffer_unmap(cell->pipe.screen, cell->constants[shader].buffer); + pipe_buffer_unmap(cell->pipe.screen, cell->constants[shader]); } if (cell->dirty & (CELL_NEW_FRAMEBUFFER | diff --git a/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c b/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c index d97c22b2ef..21af7ed1c3 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c +++ b/src/gallium/drivers/cell/ppu/cell_state_per_fragment.c @@ -999,23 +999,23 @@ cell_generate_alpha_blend(struct cell_blend_state *cb) /* Does the selected blend mode make use of the source / destination * color (RGB) blend factors? */ - boolean need_color_factor = b->blend_enable - && (b->rgb_func != PIPE_BLEND_MIN) - && (b->rgb_func != PIPE_BLEND_MAX); + boolean need_color_factor = b->rt[0].blend_enable + && (b->rt[0].rgb_func != PIPE_BLEND_MIN) + && (b->rt[0].rgb_func != PIPE_BLEND_MAX); /* Does the selected blend mode make use of the source / destination * alpha blend factors? */ - boolean need_alpha_factor = b->blend_enable - && (b->alpha_func != PIPE_BLEND_MIN) - && (b->alpha_func != PIPE_BLEND_MAX); + boolean need_alpha_factor = b->rt[0].blend_enable + && (b->rt[0].alpha_func != PIPE_BLEND_MIN) + && (b->rt[0].alpha_func != PIPE_BLEND_MAX); - if (b->blend_enable) { - sF[0] = b->rgb_src_factor; + if (b->rt[0].blend_enable) { + sF[0] = b->rt[0].rgb_src_factor; sF[1] = sF[0]; sF[2] = sF[0]; - switch (b->alpha_src_factor & 0x0f) { + switch (b->rt[0].alpha_src_factor & 0x0f) { case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: sF[3] = PIPE_BLENDFACTOR_ONE; break; @@ -1023,30 +1023,30 @@ cell_generate_alpha_blend(struct cell_blend_state *cb) case PIPE_BLENDFACTOR_DST_COLOR: case PIPE_BLENDFACTOR_CONST_COLOR: case PIPE_BLENDFACTOR_SRC1_COLOR: - sF[3] = b->alpha_src_factor + 1; + sF[3] = b->rt[0].alpha_src_factor + 1; break; default: - sF[3] = b->alpha_src_factor; + sF[3] = b->rt[0].alpha_src_factor; } - dF[0] = b->rgb_dst_factor; + dF[0] = b->rt[0].rgb_dst_factor; dF[1] = dF[0]; dF[2] = dF[0]; - switch (b->alpha_dst_factor & 0x0f) { + switch (b->rt[0].alpha_dst_factor & 0x0f) { case PIPE_BLENDFACTOR_SRC_COLOR: case PIPE_BLENDFACTOR_DST_COLOR: case PIPE_BLENDFACTOR_CONST_COLOR: case PIPE_BLENDFACTOR_SRC1_COLOR: - dF[3] = b->alpha_dst_factor + 1; + dF[3] = b->rt[0].alpha_dst_factor + 1; break; default: - dF[3] = b->alpha_dst_factor; + dF[3] = b->rt[0].alpha_dst_factor; } - func[0] = b->rgb_func; + func[0] = b->rt[0].rgb_func; func[1] = func[0]; func[2] = func[0]; - func[3] = b->alpha_func; + func[3] = b->rt[0].alpha_func; } else { sF[0] = PIPE_BLENDFACTOR_ONE; sF[1] = PIPE_BLENDFACTOR_ONE; @@ -1067,7 +1067,7 @@ cell_generate_alpha_blend(struct cell_blend_state *cb) /* If alpha writing is enabled and the alpha blend mode requires use of * the alpha factor, calculate the alpha factor. */ - if (((b->colormask & 8) != 0) && need_alpha_factor) { + if (((b->rt[0].colormask & 8) != 0) && need_alpha_factor) { src_factor[3] = emit_alpha_factor_calculation(f, sF[3], const_color[3], frag[3], pixel[3]); @@ -1091,8 +1091,8 @@ cell_generate_alpha_blend(struct cell_blend_state *cb) src_factor[2] = dst_factor[3]; } else if (need_color_factor) { emit_color_factor_calculation(f, - b->rgb_src_factor, - b->colormask, + b->rt[0].rgb_src_factor, + b->rt[0].colormask, frag, pixel, const_color, src_factor); } @@ -1111,15 +1111,15 @@ cell_generate_alpha_blend(struct cell_blend_state *cb) dst_factor[2] = src_factor[2]; } else if (need_color_factor) { emit_color_factor_calculation(f, - b->rgb_dst_factor, - b->colormask, + b->rt[0].rgb_dst_factor, + b->rt[0].colormask, frag, pixel, const_color, dst_factor); } for (i = 0; i < 4; ++i) { - if ((b->colormask & (1U << i)) != 0) { + if ((b->rt[0].colormask & (1U << i)) != 0) { emit_blend_calculation(f, func[i], sF[i], dF[i], frag[i], src_factor[i], @@ -1216,7 +1216,7 @@ cell_generate_logic_op(struct spe_function *f, /* Short-circuit the noop and invert cases. */ - if ((logic_op == PIPE_LOGICOP_NOOP) || (blend->colormask == 0)) { + if ((logic_op == PIPE_LOGICOP_NOOP) || (blend->rt[0].colormask == 0)) { spe_bi(f, 0, 0, 0); return; } else if (logic_op == PIPE_LOGICOP_INVERT) { diff --git a/src/gallium/drivers/cell/ppu/cell_state_shader.c b/src/gallium/drivers/cell/ppu/cell_state_shader.c index 6568c784fe..9b2f86fdfb 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_shader.c +++ b/src/gallium/drivers/cell/ppu/cell_state_shader.c @@ -27,8 +27,8 @@ #include "pipe/p_defines.h" #include "util/u_memory.h" -#include "pipe/p_inlines.h" -#include "pipe/internal/p_winsys_screen.h" +#include "util/u_inlines.h" +#include "util/u_simple_screen.h" #include "draw/draw_context.h" #include "tgsi/tgsi_parse.h" @@ -183,7 +183,7 @@ cell_delete_vs_state(struct pipe_context *pipe, void *vs) static void cell_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - const struct pipe_constant_buffer *buf) + struct pipe_buffer *buf) { struct cell_context *cell = cell_context(pipe); @@ -193,7 +193,7 @@ cell_set_constant_buffer(struct pipe_context *pipe, draw_flush(cell->draw); /* note: reference counting */ - pipe_buffer_reference(&cell->constants[shader].buffer, buf->buffer); + pipe_buffer_reference(&cell->constants[shader], buf); if (shader == PIPE_SHADER_VERTEX) cell->dirty |= CELL_NEW_VS_CONSTANTS; diff --git a/src/gallium/drivers/cell/ppu/cell_texture.c b/src/gallium/drivers/cell/ppu/cell_texture.c index 998944f77a..fad290dfa0 100644 --- a/src/gallium/drivers/cell/ppu/cell_texture.c +++ b/src/gallium/drivers/cell/ppu/cell_texture.c @@ -33,8 +33,8 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" -#include "pipe/p_inlines.h" -#include "pipe/internal/p_winsys_screen.h" +#include "util/u_inlines.h" +#include "util/u_simple_screen.h" #include "util/u_format.h" #include "util/u_math.h" diff --git a/src/gallium/drivers/cell/ppu/cell_vertex_shader.c b/src/gallium/drivers/cell/ppu/cell_vertex_shader.c index 403cf6d50f..cf8cd41159 100644 --- a/src/gallium/drivers/cell/ppu/cell_vertex_shader.c +++ b/src/gallium/drivers/cell/ppu/cell_vertex_shader.c @@ -31,7 +31,7 @@ #include "pipe/p_defines.h" #include "pipe/p_context.h" -#include "pipe/internal/p_winsys_screen.h" +#include "util/u_simple_screen.h" #include "util/u_math.h" #include "cell_context.h" diff --git a/src/gallium/drivers/cell/ppu/cell_winsys.h b/src/gallium/drivers/cell/ppu/cell_winsys.h index ae2af5696b..e227e065ff 100644 --- a/src/gallium/drivers/cell/ppu/cell_winsys.h +++ b/src/gallium/drivers/cell/ppu/cell_winsys.h @@ -38,13 +38,10 @@ */ struct cell_winsys { - uint preferredFormat; + uint dummy; }; -extern struct cell_winsys * -cell_get_winsys(uint format); - #endif diff --git a/src/gallium/drivers/cell/spu/spu_command.c b/src/gallium/drivers/cell/spu/spu_command.c index 12b855a3db..55bd85bde2 100644 --- a/src/gallium/drivers/cell/spu/spu_command.c +++ b/src/gallium/drivers/cell/spu/spu_command.c @@ -53,8 +53,7 @@ struct spu_vs_context draw; /** * Buffers containing dynamically generated SPU code: */ -static unsigned char attribute_fetch_code_buffer[136 * PIPE_MAX_ATTRIBS] - ALIGN16_ATTRIB; +PIPE_ALIGN_VAR(16) static unsigned char attribute_fetch_code_buffer[136 * PIPE_MAX_ATTRIBS]; @@ -543,7 +542,7 @@ cmd_batch(uint opcode) { const uint buf = (opcode >> 8) & 0xff; uint size = (opcode >> 16); - qword buffer[CELL_BUFFER_SIZE / 16] ALIGN16_ATTRIB; + PIPE_ALIGN_VAR(16) qword buffer[CELL_BUFFER_SIZE / 16]; const unsigned usize = ROUNDUP16(size) / sizeof(buffer[0]); uint pos; diff --git a/src/gallium/drivers/cell/spu/spu_exec.c b/src/gallium/drivers/cell/spu/spu_exec.c index d86d8e09a5..d2166a4901 100644 --- a/src/gallium/drivers/cell/spu/spu_exec.c +++ b/src/gallium/drivers/cell/spu/spu_exec.c @@ -1839,10 +1839,11 @@ spu_exec_machine_run( struct spu_exec_machine *mach ) /* execute declarations (interpolants) */ if( mach->Processor == TGSI_PROCESSOR_FRAGMENT ) { for (i = 0; i < mach->NumDeclarations; i++) { + PIPE_ALIGN_VAR(16) union { struct tgsi_full_declaration decl; qword buffer[ROUNDUP16(sizeof(struct tgsi_full_declaration)) / 16]; - } d ALIGN16_ATTRIB; + } d; unsigned ea = (unsigned) (mach->Declarations + pc); spu_dcache_fetch_unaligned(d.buffer, ea, sizeof(d.decl)); @@ -1853,10 +1854,11 @@ spu_exec_machine_run( struct spu_exec_machine *mach ) /* execute instructions, until pc is set to -1 */ while (pc != -1) { + PIPE_ALIGN_VAR(16) union { struct tgsi_full_instruction inst; qword buffer[ROUNDUP16(sizeof(struct tgsi_full_instruction)) / 16]; - } i ALIGN16_ATTRIB; + } i; unsigned ea = (unsigned) (mach->Instructions + pc); spu_dcache_fetch_unaligned(i.buffer, ea, sizeof(i.inst)); diff --git a/src/gallium/drivers/cell/spu/spu_exec.h b/src/gallium/drivers/cell/spu/spu_exec.h index 8605679940..0ca92af248 100644 --- a/src/gallium/drivers/cell/spu/spu_exec.h +++ b/src/gallium/drivers/cell/spu/spu_exec.h @@ -98,9 +98,9 @@ struct spu_exec_machine * 4 internal temporaries * 1 address */ + PIPE_ALIGN_VAR(16) struct spu_exec_vector Temps[TGSI_EXEC_NUM_TEMPS - + TGSI_EXEC_NUM_TEMP_EXTRAS + 1] - ALIGN16_ATTRIB; + + TGSI_EXEC_NUM_TEMP_EXTRAS + 1]; struct spu_exec_vector *Addrs; diff --git a/src/gallium/drivers/cell/spu/spu_funcs.c b/src/gallium/drivers/cell/spu/spu_funcs.c index ff3d609d25..98919c43ff 100644 --- a/src/gallium/drivers/cell/spu/spu_funcs.c +++ b/src/gallium/drivers/cell/spu/spu_funcs.c @@ -144,7 +144,7 @@ export_func(struct cell_spu_function_info *spu_functions, void return_function_info(void) { - struct cell_spu_function_info funcs ALIGN16_ATTRIB; + PIPE_ALIGN_VAR(16) struct cell_spu_function_info funcs; int tag = TAG_MISC; ASSERT(sizeof(funcs) == 256); /* must be multiple of 16 bytes */ diff --git a/src/gallium/drivers/cell/spu/spu_main.h b/src/gallium/drivers/cell/spu/spu_main.h index 33767e7c51..a9d72f84d5 100644 --- a/src/gallium/drivers/cell/spu/spu_main.h +++ b/src/gallium/drivers/cell/spu/spu_main.h @@ -93,50 +93,64 @@ typedef vector unsigned int (*spu_fragment_program_func)(vector float *inputs, vector float *constants); +PIPE_ALIGN_TYPE(16, struct spu_framebuffer { void *color_start; /**< addr of color surface in main memory */ void *depth_start; /**< addr of depth surface in main memory */ enum pipe_format color_format; enum pipe_format depth_format; - uint width, height; /**< size in pixels */ - uint width_tiles, height_tiles; /**< width and height in tiles */ + uint width; /**< width in pixels */ + uint height; /**< height in pixels */ + uint width_tiles; /**< width in tiles */ + uint height_tiles; /**< width in tiles */ uint color_clear_value; uint depth_clear_value; uint zsize; /**< 0, 2 or 4 bytes per Z */ float zscale; /**< 65535.0, 2^24-1 or 2^32-1 */ -} ALIGN16_ATTRIB; +}); /** per-texture level info */ +PIPE_ALIGN_TYPE(16, struct spu_texture_level { void *start; - ushort width, height, depth; + ushort width; + ushort height; + ushort depth; ushort tiles_per_row; uint bytes_per_image; /** texcoord scale factors */ - vector float scale_s, scale_t, scale_r; + vector float scale_s; + vector float scale_t; + vector float scale_r; /** texcoord masks (if REPEAT then size-1, else ~0) */ - vector signed int mask_s, mask_t, mask_r; + vector signed int mask_s; + vector signed int mask_t; + vector signed int mask_r; /** texcoord clamp limits */ - vector signed int max_s, max_t, max_r; -} ALIGN16_ATTRIB; + vector signed int max_s; + vector signed int max_t; + vector signed int max_r; +}); +PIPE_ALIGN_TYPE(16, struct spu_texture { struct spu_texture_level level[CELL_MAX_TEXTURE_LEVELS]; uint max_level; uint target; /**< PIPE_TEXTURE_x */ -} ALIGN16_ATTRIB; +}); /** * All SPU global/context state will be in a singleton object of this type: */ +PIPE_ALIGN_TYPE(16, struct spu_global { /** One-time init/constant info */ @@ -155,18 +169,19 @@ struct spu_global struct vertex_info vertex_info; /** Current color and Z tiles */ - tile_t ctile ALIGN16_ATTRIB; - tile_t ztile ALIGN16_ATTRIB; + PIPE_ALIGN_VAR(16) tile_t ctile; + PIPE_ALIGN_VAR(16) tile_t ztile; /** Read depth/stencil tiles? */ boolean read_depth_stencil; /** Current tiles' status */ - ubyte cur_ctile_status, cur_ztile_status; + ubyte cur_ctile_status; + ubyte cur_ztile_status; /** Status of all tiles in framebuffer */ - ubyte ctile_status[CELL_MAX_HEIGHT/TILE_SIZE][CELL_MAX_WIDTH/TILE_SIZE] ALIGN16_ATTRIB; - ubyte ztile_status[CELL_MAX_HEIGHT/TILE_SIZE][CELL_MAX_WIDTH/TILE_SIZE] ALIGN16_ATTRIB; + PIPE_ALIGN_VAR(16) ubyte ctile_status[CELL_MAX_HEIGHT/TILE_SIZE][CELL_MAX_WIDTH/TILE_SIZE]; + PIPE_ALIGN_VAR(16) ubyte ztile_status[CELL_MAX_HEIGHT/TILE_SIZE][CELL_MAX_WIDTH/TILE_SIZE]; /** Current fragment ops machine code, at 8-byte boundary */ uint *fragment_ops_code; @@ -175,7 +190,7 @@ struct spu_global spu_fragment_ops_func fragment_ops[2]; /** Current fragment program machine code, at 8-byte boundary */ - uint fragment_program_code[SPU_MAX_FRAGMENT_PROGRAM_INSTS] ALIGN8_ATTRIB; + PIPE_ALIGN_VAR(8) uint fragment_program_code[SPU_MAX_FRAGMENT_PROGRAM_INSTS]; /** Current fragment ops function */ spu_fragment_program_func fragment_program; @@ -187,7 +202,7 @@ struct spu_global /** Fragment program constants */ vector float constants[4 * CELL_MAX_CONSTANTS]; -} ALIGN16_ATTRIB; +}); extern struct spu_global spu; diff --git a/src/gallium/drivers/cell/spu/spu_per_fragment_op.c b/src/gallium/drivers/cell/spu/spu_per_fragment_op.c index eba9f95cf1..5328374080 100644 --- a/src/gallium/drivers/cell/spu/spu_per_fragment_op.c +++ b/src/gallium/drivers/cell/spu/spu_per_fragment_op.c @@ -207,9 +207,9 @@ spu_fallback_fragment_ops(uint x, uint y, * If we'll need the current framebuffer/tile colors for blending * or logicop or colormask, fetch them now. */ - if (spu.blend.blend_enable || + if (spu.blend.rt[0].blend_enable || spu.blend.logicop_enable || - spu.blend.colormask != 0xf) { + spu.blend.rt[0].colormask != 0xf) { #if LINEAR_QUAD_LAYOUT /* See comments/diagram below */ fbc0 = colorTile->ui[y][x*2+0]; @@ -228,7 +228,7 @@ spu_fallback_fragment_ops(uint x, uint y, /* * Do blending */ - if (spu.blend.blend_enable) { + if (spu.blend.rt[0].blend_enable) { /* blending terms, misc regs */ vector float term1r, term1g, term1b, term1a; vector float term2r, term2g, term2b, term2a; @@ -261,7 +261,7 @@ spu_fallback_fragment_ops(uint x, uint y, /* * Compute Src RGB terms (fragment color * factor) */ - switch (spu.blend.rgb_src_factor) { + switch (spu.blend.rt[0].rgb_src_factor) { case PIPE_BLENDFACTOR_ONE: term1r = fragR; term1g = fragG; @@ -310,7 +310,7 @@ spu_fallback_fragment_ops(uint x, uint y, /* * Compute Src Alpha term (fragment alpha * factor) */ - switch (spu.blend.alpha_src_factor) { + switch (spu.blend.rt[0].alpha_src_factor) { case PIPE_BLENDFACTOR_ONE: term1a = fragA; break; @@ -338,7 +338,7 @@ spu_fallback_fragment_ops(uint x, uint y, /* * Compute Dest RGB terms (framebuffer color * factor) */ - switch (spu.blend.rgb_dst_factor) { + switch (spu.blend.rt[0].rgb_dst_factor) { case PIPE_BLENDFACTOR_ONE: term2r = fbRGBA[0]; term2g = fbRGBA[1]; @@ -394,7 +394,7 @@ spu_fallback_fragment_ops(uint x, uint y, /* * Compute Dest Alpha term (framebuffer alpha * factor) */ - switch (spu.blend.alpha_dst_factor) { + switch (spu.blend.rt[0].alpha_dst_factor) { case PIPE_BLENDFACTOR_ONE: term2a = fbRGBA[3]; break; @@ -427,7 +427,7 @@ spu_fallback_fragment_ops(uint x, uint y, /* * Combine Src/Dest RGB terms */ - switch (spu.blend.rgb_func) { + switch (spu.blend.rt[0].rgb_func) { case PIPE_BLEND_ADD: fragR = spu_add(term1r, term2r); fragG = spu_add(term1g, term2g); @@ -460,7 +460,7 @@ spu_fallback_fragment_ops(uint x, uint y, /* * Combine Src/Dest A term */ - switch (spu.blend.alpha_func) { + switch (spu.blend.rt[0].alpha_func) { case PIPE_BLEND_ADD: fragA = spu_add(term1a, term2a); break; @@ -527,29 +527,29 @@ spu_fallback_fragment_ops(uint x, uint y, /* * Do color masking */ - if (spu.blend.colormask != 0xf) { + if (spu.blend.rt[0].colormask != 0xf) { uint cmask = 0x0; /* each byte corresponds to a color channel */ /* Form bitmask depending on color buffer format and colormask bits */ switch (spu.fb.color_format) { case PIPE_FORMAT_A8R8G8B8_UNORM: - if (spu.blend.colormask & PIPE_MASK_R) + if (spu.blend.rt[0].colormask & PIPE_MASK_R) cmask |= 0x00ff0000; /* red */ - if (spu.blend.colormask & PIPE_MASK_G) + if (spu.blend.rt[0].colormask & PIPE_MASK_G) cmask |= 0x0000ff00; /* green */ - if (spu.blend.colormask & PIPE_MASK_B) + if (spu.blend.rt[0].colormask & PIPE_MASK_B) cmask |= 0x000000ff; /* blue */ - if (spu.blend.colormask & PIPE_MASK_A) + if (spu.blend.rt[0].colormask & PIPE_MASK_A) cmask |= 0xff000000; /* alpha */ break; case PIPE_FORMAT_B8G8R8A8_UNORM: - if (spu.blend.colormask & PIPE_MASK_R) + if (spu.blend.rt[0].colormask & PIPE_MASK_R) cmask |= 0x0000ff00; /* red */ - if (spu.blend.colormask & PIPE_MASK_G) + if (spu.blend.rt[0].colormask & PIPE_MASK_G) cmask |= 0x00ff0000; /* green */ - if (spu.blend.colormask & PIPE_MASK_B) + if (spu.blend.rt[0].colormask & PIPE_MASK_B) cmask |= 0xff000000; /* blue */ - if (spu.blend.colormask & PIPE_MASK_A) + if (spu.blend.rt[0].colormask & PIPE_MASK_A) cmask |= 0x000000ff; /* alpha */ break; default: diff --git a/src/gallium/drivers/cell/spu/spu_render.c b/src/gallium/drivers/cell/spu/spu_render.c index 5ffb7073ab..14987e3c3a 100644 --- a/src/gallium/drivers/cell/spu/spu_render.c +++ b/src/gallium/drivers/cell/spu/spu_render.c @@ -169,7 +169,7 @@ void cmd_render(const struct cell_command_render *render, uint *pos_incr) { /* we'll DMA into these buffers */ - ubyte vertex_data[CELL_BUFFER_SIZE] ALIGN16_ATTRIB; + PIPE_ALIGN_VAR(16) ubyte vertex_data[CELL_BUFFER_SIZE]; const uint vertex_size = render->vertex_size; /* in bytes */ /*const*/ uint total_vertex_bytes = render->num_verts * vertex_size; uint index_bytes; diff --git a/src/gallium/drivers/cell/spu/spu_vertex_fetch.c b/src/gallium/drivers/cell/spu/spu_vertex_fetch.c index 03375d84a5..087963960d 100644 --- a/src/gallium/drivers/cell/spu/spu_vertex_fetch.c +++ b/src/gallium/drivers/cell/spu/spu_vertex_fetch.c @@ -43,7 +43,8 @@ typedef void (*spu_fetch_func)(qword *out, const qword *in, const qword *shuffle_data); -static const qword fetch_shuffle_data[5] ALIGN16_ATTRIB = { +PIPE_ALIGN_VAR(16) static const qword +fetch_shuffle_data[5] = { /* Shuffle used by CVT_64_FLOAT */ { @@ -110,7 +111,7 @@ static void generic_vertex_fetch(struct spu_vs_context *draw, unsigned idx; const unsigned bytes_per_entry = draw->vertex_fetch.size[attr]; const unsigned quads_per_entry = (bytes_per_entry + 15) / 16; - qword in[2 * 4] ALIGN16_ATTRIB; + PIPE_ALIGN_VAR(16) qword in[2 * 4]; /* Fetch four attributes for four vertices. diff --git a/src/gallium/drivers/cell/spu/spu_vertex_shader.c b/src/gallium/drivers/cell/spu/spu_vertex_shader.c index fbe5b34d39..3e9804bf8e 100644 --- a/src/gallium/drivers/cell/spu/spu_vertex_shader.c +++ b/src/gallium/drivers/cell/spu/spu_vertex_shader.c @@ -107,8 +107,8 @@ run_vertex_program(struct spu_vs_context *draw, struct spu_exec_machine *machine = &draw->machine; unsigned int j; - ALIGN16_DECL(struct spu_exec_vector, inputs, PIPE_MAX_ATTRIBS); - ALIGN16_DECL(struct spu_exec_vector, outputs, PIPE_MAX_ATTRIBS); + PIPE_ALIGN_VAR(16) struct spu_exec_vector inputs[PIPE_MAX_ATTRIBS]; + PIPE_ALIGN_VAR(16) struct spu_exec_vector outputs[PIPE_MAX_ATTRIBS]; const float *scale = draw->viewport.scale; const float *trans = draw->viewport.translate; @@ -119,8 +119,8 @@ run_vertex_program(struct spu_vs_context *draw, ASSERT_ALIGN16(draw->constants); machine->Consts = (float (*)[4]) draw->constants; - machine->Inputs = ALIGN16_ASSIGN(inputs); - machine->Outputs = ALIGN16_ASSIGN(outputs); + machine->Inputs = inputs; + machine->Outputs = outputs; spu_vertex_fetch( draw, machine, elts, count ); @@ -132,8 +132,9 @@ run_vertex_program(struct spu_vs_context *draw, for (j = 0; j < count; j++) { unsigned slot; float x, y, z, w; + PIPE_ALIGN_VAR(16) unsigned char buffer[sizeof(struct vertex_header) - + MAX_VERTEX_SIZE] ALIGN16_ATTRIB; + + MAX_VERTEX_SIZE]; struct vertex_header *const tmpOut = (struct vertex_header *) buffer; const unsigned vert_size = ROUNDUP16(sizeof(struct vertex_header) @@ -186,8 +187,8 @@ run_vertex_program(struct spu_vs_context *draw, } -unsigned char immediates[(sizeof(float) * 4 * TGSI_EXEC_NUM_IMMEDIATES) + 32] - ALIGN16_ATTRIB; +PIPE_ALIGN_VAR(16) unsigned char +immediates[(sizeof(float) * 4 * TGSI_EXEC_NUM_IMMEDIATES) + 32]); void diff --git a/src/gallium/drivers/failover/fo_context.c b/src/gallium/drivers/failover/fo_context.c index 46e4338d98..2ccc5d3e60 100644 --- a/src/gallium/drivers/failover/fo_context.c +++ b/src/gallium/drivers/failover/fo_context.c @@ -27,7 +27,7 @@ #include "pipe/p_defines.h" -#include "pipe/internal/p_winsys_screen.h" +#include "util/u_simple_screen.h" #include "util/u_memory.h" #include "pipe/p_context.h" diff --git a/src/gallium/drivers/failover/fo_context.h b/src/gallium/drivers/failover/fo_context.h index 149393712a..191a44c3df 100644 --- a/src/gallium/drivers/failover/fo_context.h +++ b/src/gallium/drivers/failover/fo_context.h @@ -125,7 +125,7 @@ failover_context( struct pipe_context *pipe ) void failover_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - const struct pipe_constant_buffer *buf); + struct pipe_buffer *buf); #endif /* FO_CONTEXT_H */ diff --git a/src/gallium/drivers/failover/fo_state.c b/src/gallium/drivers/failover/fo_state.c index 3f5f556032..c189d1d82c 100644 --- a/src/gallium/drivers/failover/fo_state.c +++ b/src/gallium/drivers/failover/fo_state.c @@ -28,6 +28,8 @@ /* Authors: Keith Whitwell <keith@tungstengraphics.com> */ +#include "util/u_inlines.h" + #include "fo_context.h" @@ -495,7 +497,7 @@ failover_set_vertex_elements(struct pipe_context *pipe, void failover_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - const struct pipe_constant_buffer *buf) + struct pipe_buffer *buf) { struct failover_context *failover = failover_context(pipe); diff --git a/src/gallium/drivers/i915/i915_buffer.c b/src/gallium/drivers/i915/i915_buffer.c index 669964770d..0f76a59e93 100644 --- a/src/gallium/drivers/i915/i915_buffer.c +++ b/src/gallium/drivers/i915/i915_buffer.c @@ -23,6 +23,7 @@ * **************************************************************************/ +#include "util/u_inlines.h" #include "util/u_memory.h" #include "i915_screen.h" #include "i915_buffer.h" diff --git a/src/gallium/drivers/i915/i915_clear.c b/src/gallium/drivers/i915/i915_clear.c index 90530f2826..0d0859f8f3 100644 --- a/src/gallium/drivers/i915/i915_clear.c +++ b/src/gallium/drivers/i915/i915_clear.c @@ -32,7 +32,6 @@ #include "util/u_clear.h" #include "i915_context.h" -#include "i915_state.h" /** diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c index 89feeade75..3d45a22b7e 100644 --- a/src/gallium/drivers/i915/i915_context.c +++ b/src/gallium/drivers/i915/i915_context.c @@ -29,13 +29,10 @@ #include "i915_state.h" #include "i915_screen.h" #include "i915_batch.h" -#include "i915_texture.h" -#include "i915_reg.h" #include "draw/draw_context.h" #include "pipe/p_defines.h" -#include "pipe/internal/p_winsys_screen.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_memory.h" #include "pipe/p_screen.h" @@ -84,7 +81,7 @@ i915_draw_range_elements(struct pipe_context *pipe, } - draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, + draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0, i915->current.constants[PIPE_SHADER_VERTEX], (i915->current.num_user_constants[PIPE_SHADER_VERTEX] * 4 * sizeof(float))); @@ -186,7 +183,7 @@ static void i915_destroy(struct pipe_context *pipe) } struct pipe_context * -i915_create_context(struct pipe_screen *screen) +i915_create_context(struct pipe_screen *screen, void *priv) { struct i915_context *i915; @@ -197,6 +194,7 @@ i915_create_context(struct pipe_screen *screen) i915->iws = i915_screen(screen)->iws; i915->base.winsys = NULL; i915->base.screen = screen; + i915->base.priv = priv; i915->base.destroy = i915_destroy; diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h index 234b441ce6..1479d2201a 100644 --- a/src/gallium/drivers/i915/i915_context.h +++ b/src/gallium/drivers/i915/i915_context.h @@ -167,7 +167,7 @@ struct i915_depth_stencil_state { }; struct i915_rasterizer_state { - int light_twoside : 1; + unsigned light_twoside : 1; unsigned st; enum interp_mode color_interp; @@ -233,7 +233,8 @@ struct i915_context struct pipe_blend_color blend_color; struct pipe_clip_state clip; - struct pipe_constant_buffer constants[PIPE_SHADER_TYPES]; + /* XXX unneded */ + struct pipe_buffer *constants[PIPE_SHADER_TYPES]; struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple poly_stipple; struct pipe_scissor_state scissor; @@ -333,6 +334,11 @@ void i915_init_flush_functions( struct i915_context *i915 ); void i915_init_string_functions( struct i915_context *i915 ); +/************************************************************************ + * i915_context.c + */ +struct pipe_context *i915_create_context(struct pipe_screen *screen, + void *priv); /*********************************************************************** diff --git a/src/gallium/drivers/i915/i915_debug.c b/src/gallium/drivers/i915/i915_debug.c index c6e6d6fd31..237654d26b 100644 --- a/src/gallium/drivers/i915/i915_debug.c +++ b/src/gallium/drivers/i915/i915_debug.c @@ -29,7 +29,6 @@ #include "i915_context.h" #include "i915_debug.h" #include "i915_batch.h" -#include "pipe/internal/p_winsys_screen.h" #include "util/u_debug.h" diff --git a/src/gallium/drivers/i915/i915_debug.h b/src/gallium/drivers/i915/i915_debug.h index dd9b86e17b..8f7484797d 100644 --- a/src/gallium/drivers/i915/i915_debug.h +++ b/src/gallium/drivers/i915/i915_debug.h @@ -72,7 +72,7 @@ void i915_print_ureg(const char *msg, unsigned ureg); #if defined(DEBUG) && defined(FILE_DEBUG_FLAG) -#include "pipe/internal/p_winsys_screen.h" +#include "util/u_simple_screen.h" static INLINE void I915_DBG( diff --git a/src/gallium/drivers/i915/i915_debug_fp.c b/src/gallium/drivers/i915/i915_debug_fp.c index 9c5b117b6d..066e7392d1 100644 --- a/src/gallium/drivers/i915/i915_debug_fp.c +++ b/src/gallium/drivers/i915/i915_debug_fp.c @@ -28,8 +28,8 @@ #include "i915_reg.h" #include "i915_debug.h" -#include "pipe/internal/p_winsys_screen.h" -#include "util/u_memory.h" +#include "util/u_simple_screen.h" +#include "util/u_debug.h" static void diff --git a/src/gallium/drivers/i915/i915_prim_vbuf.c b/src/gallium/drivers/i915/i915_prim_vbuf.c index 6b832140a8..cad4109ee6 100644 --- a/src/gallium/drivers/i915/i915_prim_vbuf.c +++ b/src/gallium/drivers/i915/i915_prim_vbuf.c @@ -41,7 +41,7 @@ #include "draw/draw_context.h" #include "draw/draw_vbuf.h" #include "util/u_debug.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_fifo.h" diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c index d4ee8f5339..c450854c98 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -26,7 +26,7 @@ **************************************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_string.h" @@ -117,6 +117,12 @@ i915_get_param(struct pipe_screen *screen, int param) return 8; /* max 128x128x128 */ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: return 11; /* max 1024x1024 */ + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 0; default: return 0; } @@ -288,6 +294,8 @@ i915_create_screen(struct intel_winsys *iws, uint pci_id) is->base.get_paramf = i915_get_paramf; is->base.is_format_supported = i915_is_format_supported; + is->base.context_create = i915_create_context; + is->base.fence_reference = i915_fence_reference; is->base.fence_signalled = i915_fence_signalled; is->base.fence_finish = i915_fence_finish; diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c index 5f5b6f8e18..beb26e996a 100644 --- a/src/gallium/drivers/i915/i915_state.c +++ b/src/gallium/drivers/i915/i915_state.c @@ -30,15 +30,13 @@ #include "draw/draw_context.h" -#include "pipe/internal/p_winsys_screen.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_math.h" #include "util/u_memory.h" #include "tgsi/tgsi_parse.h" #include "i915_context.h" #include "i915_reg.h" -#include "i915_state.h" #include "i915_state_inlines.h" #include "i915_fpc.h" @@ -105,13 +103,13 @@ i915_create_blend_state(struct pipe_context *pipe, struct i915_blend_state *cso_data = CALLOC_STRUCT( i915_blend_state ); { - unsigned eqRGB = blend->rgb_func; - unsigned srcRGB = blend->rgb_src_factor; - unsigned dstRGB = blend->rgb_dst_factor; + unsigned eqRGB = blend->rt[0].rgb_func; + unsigned srcRGB = blend->rt[0].rgb_src_factor; + unsigned dstRGB = blend->rt[0].rgb_dst_factor; - unsigned eqA = blend->alpha_func; - unsigned srcA = blend->alpha_src_factor; - unsigned dstA = blend->alpha_dst_factor; + unsigned eqA = blend->rt[0].alpha_func; + unsigned srcA = blend->rt[0].alpha_src_factor; + unsigned dstA = blend->rt[0].alpha_dst_factor; /* Special handling for MIN/MAX filter modes handled at * state_tracker level. @@ -148,22 +146,22 @@ i915_create_blend_state(struct pipe_context *pipe, if (blend->dither) cso_data->LIS5 |= S5_COLOR_DITHER_ENABLE; - if ((blend->colormask & PIPE_MASK_R) == 0) + if ((blend->rt[0].colormask & PIPE_MASK_R) == 0) cso_data->LIS5 |= S5_WRITEDISABLE_RED; - if ((blend->colormask & PIPE_MASK_G) == 0) + if ((blend->rt[0].colormask & PIPE_MASK_G) == 0) cso_data->LIS5 |= S5_WRITEDISABLE_GREEN; - if ((blend->colormask & PIPE_MASK_B) == 0) + if ((blend->rt[0].colormask & PIPE_MASK_B) == 0) cso_data->LIS5 |= S5_WRITEDISABLE_BLUE; - if ((blend->colormask & PIPE_MASK_A) == 0) + if ((blend->rt[0].colormask & PIPE_MASK_A) == 0) cso_data->LIS5 |= S5_WRITEDISABLE_ALPHA; - if (blend->blend_enable) { - unsigned funcRGB = blend->rgb_func; - unsigned srcRGB = blend->rgb_src_factor; - unsigned dstRGB = blend->rgb_dst_factor; + if (blend->rt[0].blend_enable) { + unsigned funcRGB = blend->rt[0].rgb_func; + unsigned srcRGB = blend->rt[0].rgb_src_factor; + unsigned dstRGB = blend->rt[0].rgb_dst_factor; cso_data->LIS6 |= (S6_CBUF_BLEND_ENABLE | SRC_BLND_FACT(i915_translate_blend_factor(srcRGB)) | @@ -518,7 +516,7 @@ static void i915_delete_vs_state(struct pipe_context *pipe, void *shader) static void i915_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - const struct pipe_constant_buffer *buf) + struct pipe_buffer *buf) { struct i915_context *i915 = i915_context(pipe); struct pipe_screen *screen = pipe->screen; @@ -538,13 +536,13 @@ static void i915_set_constant_buffer(struct pipe_context *pipe, */ if (buf) { void *mapped; - if (buf->buffer && buf->buffer->size && - (mapped = pipe_buffer_map(screen, buf->buffer, + if (buf->size && + (mapped = pipe_buffer_map(screen, buf, PIPE_BUFFER_USAGE_CPU_READ))) { - memcpy(i915->current.constants[shader], mapped, buf->buffer->size); - pipe_buffer_unmap(screen, buf->buffer); + memcpy(i915->current.constants[shader], mapped, buf->size); + pipe_buffer_unmap(screen, buf); i915->current.num_user_constants[shader] - = buf->buffer->size / (4 * sizeof(float)); + = buf->size / (4 * sizeof(float)); } else { i915->current.num_user_constants[shader] = 0; diff --git a/src/gallium/drivers/i915/i915_state_derived.c b/src/gallium/drivers/i915/i915_state_derived.c index 03dd5091a6..f5b0e9f011 100644 --- a/src/gallium/drivers/i915/i915_state_derived.c +++ b/src/gallium/drivers/i915/i915_state_derived.c @@ -33,7 +33,6 @@ #include "i915_context.h" #include "i915_state.h" #include "i915_reg.h" -#include "i915_fpc.h" diff --git a/src/gallium/drivers/i915/i915_state_inlines.h b/src/gallium/drivers/i915/i915_state_inlines.h index 378de8f9c4..b589117fbf 100644 --- a/src/gallium/drivers/i915/i915_state_inlines.h +++ b/src/gallium/drivers/i915/i915_state_inlines.h @@ -30,6 +30,7 @@ #include "pipe/p_compiler.h" #include "pipe/p_defines.h" +#include "util/u_debug.h" #include "i915_reg.h" diff --git a/src/gallium/drivers/i915/i915_state_sampler.c b/src/gallium/drivers/i915/i915_state_sampler.c index cbac4175c8..e5c6d87215 100644 --- a/src/gallium/drivers/i915/i915_state_sampler.c +++ b/src/gallium/drivers/i915/i915_state_sampler.c @@ -27,7 +27,6 @@ #include "pipe/p_context.h" #include "pipe/p_state.h" -#include "util/u_memory.h" #include "i915_state_inlines.h" #include "i915_context.h" diff --git a/src/gallium/drivers/i915/i915_surface.c b/src/gallium/drivers/i915/i915_surface.c index c693eb30e8..1ff6b9f4c6 100644 --- a/src/gallium/drivers/i915/i915_surface.c +++ b/src/gallium/drivers/i915/i915_surface.c @@ -27,14 +27,8 @@ #include "i915_context.h" #include "i915_blit.h" -#include "i915_state.h" #include "pipe/p_defines.h" -#include "pipe/p_inlines.h" -#include "pipe/p_inlines.h" -#include "pipe/internal/p_winsys_screen.h" #include "util/u_format.h" -#include "util/u_tile.h" -#include "util/u_rect.h" /* Assumes all values are within bounds -- no checking at this level - diff --git a/src/gallium/drivers/i915/i915_texture.c b/src/gallium/drivers/i915/i915_texture.c index 50a9e19094..e101c8683e 100644 --- a/src/gallium/drivers/i915/i915_texture.c +++ b/src/gallium/drivers/i915/i915_texture.c @@ -33,15 +33,13 @@ #include "pipe/p_state.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" -#include "pipe/p_inlines.h" -#include "pipe/internal/p_winsys_screen.h" +#include "util/u_inlines.h" #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" #include "i915_context.h" #include "i915_texture.h" -#include "i915_debug.h" #include "i915_screen.h" #include "intel_winsys.h" diff --git a/src/gallium/drivers/i915/intel_winsys.h b/src/gallium/drivers/i915/intel_winsys.h index c6bf6e6f7f..b3a802b0e2 100644 --- a/src/gallium/drivers/i915/intel_winsys.h +++ b/src/gallium/drivers/i915/intel_winsys.h @@ -203,10 +203,6 @@ struct intel_winsys { */ struct pipe_screen *i915_create_screen(struct intel_winsys *iws, unsigned pci_id); -/** - * Create a i915 pipe_context. - */ -struct pipe_context *i915_create_context(struct pipe_screen *screen); /** * Get the intel_winsys buffer backing the texture. diff --git a/src/gallium/drivers/i965/brw_batchbuffer.c b/src/gallium/drivers/i965/brw_batchbuffer.c index 22607dc608..003b1fd5bf 100644 --- a/src/gallium/drivers/i965/brw_batchbuffer.c +++ b/src/gallium/drivers/i965/brw_batchbuffer.c @@ -155,7 +155,7 @@ _brw_batchbuffer_flush(struct brw_batchbuffer *batch, enum pipe_error brw_batchbuffer_emit_reloc(struct brw_batchbuffer *batch, struct brw_winsys_buffer *buffer, - uint32_t usage, + enum brw_buffer_usage usage, uint32_t delta) { int ret; diff --git a/src/gallium/drivers/i965/brw_batchbuffer.h b/src/gallium/drivers/i965/brw_batchbuffer.h index 7473f5bea4..6ca9f617f5 100644 --- a/src/gallium/drivers/i965/brw_batchbuffer.h +++ b/src/gallium/drivers/i965/brw_batchbuffer.h @@ -64,12 +64,12 @@ brw_batchbuffer_reset(struct brw_batchbuffer *batch); * Consider it a convenience function wrapping multple * intel_buffer_dword() calls. */ -int brw_batchbuffer_data(struct brw_batchbuffer *batch, +enum pipe_error brw_batchbuffer_data(struct brw_batchbuffer *batch, const void *data, GLuint bytes, enum cliprect_mode cliprect_mode); -int brw_batchbuffer_emit_reloc(struct brw_batchbuffer *batch, +enum pipe_error brw_batchbuffer_emit_reloc(struct brw_batchbuffer *batch, struct brw_winsys_buffer *buffer, enum brw_buffer_usage usage, uint32_t offset); diff --git a/src/gallium/drivers/i965/brw_cc.c b/src/gallium/drivers/i965/brw_cc.c index 3e070f5591..4a543276f5 100644 --- a/src/gallium/drivers/i965/brw_cc.c +++ b/src/gallium/drivers/i965/brw_cc.c @@ -32,7 +32,6 @@ #include "brw_context.h" #include "brw_state.h" -#include "brw_defines.h" static enum pipe_error prepare_cc_vp( struct brw_context *brw ) diff --git a/src/gallium/drivers/i965/brw_clip.c b/src/gallium/drivers/i965/brw_clip.c index d67a1a6263..ccba205e8c 100644 --- a/src/gallium/drivers/i965/brw_clip.c +++ b/src/gallium/drivers/i965/brw_clip.c @@ -38,7 +38,6 @@ #include "brw_defines.h" #include "brw_context.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_state.h" #include "brw_pipe_rast.h" #include "brw_clip.h" diff --git a/src/gallium/drivers/i965/brw_clip_line.c b/src/gallium/drivers/i965/brw_clip_line.c index 54282d975e..66caadc4d5 100644 --- a/src/gallium/drivers/i965/brw_clip_line.c +++ b/src/gallium/drivers/i965/brw_clip_line.c @@ -33,7 +33,6 @@ #include "brw_defines.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_clip.h" diff --git a/src/gallium/drivers/i965/brw_clip_point.c b/src/gallium/drivers/i965/brw_clip_point.c index e0a5330556..124156c1b5 100644 --- a/src/gallium/drivers/i965/brw_clip_point.c +++ b/src/gallium/drivers/i965/brw_clip_point.c @@ -31,7 +31,6 @@ #include "brw_defines.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_clip.h" diff --git a/src/gallium/drivers/i965/brw_clip_tri.c b/src/gallium/drivers/i965/brw_clip_tri.c index 4cde7294ea..069524bc14 100644 --- a/src/gallium/drivers/i965/brw_clip_tri.c +++ b/src/gallium/drivers/i965/brw_clip_tri.c @@ -31,7 +31,6 @@ #include "brw_defines.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_clip.h" static void release_tmps( struct brw_clip_compile *c ) diff --git a/src/gallium/drivers/i965/brw_clip_util.c b/src/gallium/drivers/i965/brw_clip_util.c index 97a5710310..23e51ee9bc 100644 --- a/src/gallium/drivers/i965/brw_clip_util.c +++ b/src/gallium/drivers/i965/brw_clip_util.c @@ -32,7 +32,6 @@ #include "brw_defines.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_clip.h" diff --git a/src/gallium/drivers/i965/brw_context.c b/src/gallium/drivers/i965/brw_context.c index e67551882d..3dbe2b9130 100644 --- a/src/gallium/drivers/i965/brw_context.c +++ b/src/gallium/drivers/i965/brw_context.c @@ -31,10 +31,10 @@ #include "pipe/p_context.h" +#include "util/u_inlines.h" #include "util/u_simple_list.h" #include "brw_context.h" -#include "brw_defines.h" #include "brw_draw.h" #include "brw_state.h" #include "brw_batchbuffer.h" @@ -102,7 +102,8 @@ static void brw_destroy_context( struct pipe_context *pipe ) } -struct pipe_context *brw_create_context(struct pipe_screen *screen) +struct pipe_context *brw_create_context(struct pipe_screen *screen, + void *priv) { struct brw_context *brw = (struct brw_context *) CALLOC_STRUCT(brw_context); @@ -112,6 +113,7 @@ struct pipe_context *brw_create_context(struct pipe_screen *screen) } brw->base.screen = screen; + brw->base.priv = priv; brw->base.destroy = brw_destroy_context; brw->sws = brw_screen(screen)->sws; brw->chipset = brw_screen(screen)->chipset; diff --git a/src/gallium/drivers/i965/brw_context.h b/src/gallium/drivers/i965/brw_context.h index 8c006bb95b..19fda423de 100644 --- a/src/gallium/drivers/i965/brw_context.h +++ b/src/gallium/drivers/i965/brw_context.h @@ -837,6 +837,10 @@ int brw_upload_urb_fence(struct brw_context *brw); */ int brw_upload_cs_urb_state(struct brw_context *brw); +/* brw_context.c + */ +struct pipe_context *brw_create_context(struct pipe_screen *screen, + void *priv); /*====================================================================== * Inline conversion functions. These are better-typed than the diff --git a/src/gallium/drivers/i965/brw_curbe.c b/src/gallium/drivers/i965/brw_curbe.c index 3f031577d5..4b215a001c 100644 --- a/src/gallium/drivers/i965/brw_curbe.c +++ b/src/gallium/drivers/i965/brw_curbe.c @@ -36,9 +36,7 @@ #include "brw_context.h" #include "brw_defines.h" #include "brw_state.h" -#include "brw_util.h" #include "brw_debug.h" -#include "brw_screen.h" /** diff --git a/src/gallium/drivers/i965/brw_disasm.c b/src/gallium/drivers/i965/brw_disasm.c index 65db27248b..9c2ccfff65 100644 --- a/src/gallium/drivers/i965/brw_disasm.c +++ b/src/gallium/drivers/i965/brw_disasm.c @@ -366,6 +366,7 @@ static int format (FILE *f, char *format, ...) va_start (args, format); vsnprintf (buf, sizeof (buf) - 1, format, args); + va_end (args); string (f, buf); return 0; } diff --git a/src/gallium/drivers/i965/brw_draw.c b/src/gallium/drivers/i965/brw_draw.c index ea8d39adaf..9bad61ef72 100644 --- a/src/gallium/drivers/i965/brw_draw.c +++ b/src/gallium/drivers/i965/brw_draw.c @@ -26,6 +26,7 @@ **************************************************************************/ +#include "util/u_inlines.h" #include "util/u_prim.h" #include "util/u_upload_mgr.h" @@ -34,7 +35,6 @@ #include "brw_context.h" #include "brw_state.h" #include "brw_debug.h" -#include "brw_screen.h" #include "brw_batchbuffer.h" diff --git a/src/gallium/drivers/i965/brw_draw_upload.c b/src/gallium/drivers/i965/brw_draw_upload.c index a27da5f1c1..d59261557b 100644 --- a/src/gallium/drivers/i965/brw_draw_upload.c +++ b/src/gallium/drivers/i965/brw_draw_upload.c @@ -26,6 +26,7 @@ **************************************************************************/ #include "pipe/p_context.h" +#include "util/u_inlines.h" #include "util/u_upload_mgr.h" #include "util/u_math.h" diff --git a/src/gallium/drivers/i965/brw_gs.c b/src/gallium/drivers/i965/brw_gs.c index 921b201bae..06826635a8 100644 --- a/src/gallium/drivers/i965/brw_gs.c +++ b/src/gallium/drivers/i965/brw_gs.c @@ -34,7 +34,6 @@ #include "brw_defines.h" #include "brw_context.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_state.h" #include "brw_gs.h" diff --git a/src/gallium/drivers/i965/brw_gs_emit.c b/src/gallium/drivers/i965/brw_gs_emit.c index fd8e2acced..9b58773b3b 100644 --- a/src/gallium/drivers/i965/brw_gs_emit.c +++ b/src/gallium/drivers/i965/brw_gs_emit.c @@ -35,7 +35,6 @@ #include "brw_defines.h" #include "brw_context.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_gs.h" static void brw_gs_alloc_regs( struct brw_gs_compile *c, diff --git a/src/gallium/drivers/i965/brw_pipe_blend.c b/src/gallium/drivers/i965/brw_pipe_blend.c index b759a910b6..21f786f871 100644 --- a/src/gallium/drivers/i965/brw_pipe_blend.c +++ b/src/gallium/drivers/i965/brw_pipe_blend.c @@ -118,14 +118,14 @@ static void *brw_create_blend_state( struct pipe_context *pipe, blend->cc2.logicop_enable = 1; blend->cc5.logicop_func = translate_logicop(templ->logicop_func); } - else if (templ->blend_enable) { - blend->cc6.dest_blend_factor = translate_blend_factor(templ->rgb_dst_factor); - blend->cc6.src_blend_factor = translate_blend_factor(templ->rgb_src_factor); - blend->cc6.blend_function = translate_blend_equation(templ->rgb_func); + else if (templ->rt[0].blend_enable) { + blend->cc6.dest_blend_factor = translate_blend_factor(templ->rt[0].rgb_dst_factor); + blend->cc6.src_blend_factor = translate_blend_factor(templ->rt[0].rgb_src_factor); + blend->cc6.blend_function = translate_blend_equation(templ->rt[0].rgb_func); - blend->cc5.ia_dest_blend_factor = translate_blend_factor(templ->alpha_dst_factor); - blend->cc5.ia_src_blend_factor = translate_blend_factor(templ->alpha_src_factor); - blend->cc5.ia_blend_function = translate_blend_equation(templ->alpha_func); + blend->cc5.ia_dest_blend_factor = translate_blend_factor(templ->rt[0].alpha_dst_factor); + blend->cc5.ia_src_blend_factor = translate_blend_factor(templ->rt[0].alpha_src_factor); + blend->cc5.ia_blend_function = translate_blend_equation(templ->rt[0].alpha_func); blend->cc3.blend_enable = 1; blend->cc3.ia_blend_enable = @@ -146,10 +146,10 @@ static void *brw_create_blend_state( struct pipe_context *pipe, /* Per-surface color mask -- just follow global state: */ - blend->ss0.writedisable_red = (templ->colormask & PIPE_MASK_R) ? 0 : 1; - blend->ss0.writedisable_green = (templ->colormask & PIPE_MASK_G) ? 0 : 1; - blend->ss0.writedisable_blue = (templ->colormask & PIPE_MASK_B) ? 0 : 1; - blend->ss0.writedisable_alpha = (templ->colormask & PIPE_MASK_A) ? 0 : 1; + blend->ss0.writedisable_red = (templ->rt[0].colormask & PIPE_MASK_R) ? 0 : 1; + blend->ss0.writedisable_green = (templ->rt[0].colormask & PIPE_MASK_G) ? 0 : 1; + blend->ss0.writedisable_blue = (templ->rt[0].colormask & PIPE_MASK_B) ? 0 : 1; + blend->ss0.writedisable_alpha = (templ->rt[0].colormask & PIPE_MASK_A) ? 0 : 1; return (void *)blend; } diff --git a/src/gallium/drivers/i965/brw_pipe_fb.c b/src/gallium/drivers/i965/brw_pipe_fb.c index 5d4e5025f9..a90b7c73f6 100644 --- a/src/gallium/drivers/i965/brw_pipe_fb.c +++ b/src/gallium/drivers/i965/brw_pipe_fb.c @@ -1,9 +1,9 @@ #include "util/u_math.h" #include "pipe/p_context.h" #include "pipe/p_state.h" +#include "util/u_inlines.h" #include "brw_context.h" -#include "brw_debug.h" /** * called from intelDrawBuffer() diff --git a/src/gallium/drivers/i965/brw_pipe_sampler.c b/src/gallium/drivers/i965/brw_pipe_sampler.c index 81712798a5..6aab561004 100644 --- a/src/gallium/drivers/i965/brw_pipe_sampler.c +++ b/src/gallium/drivers/i965/brw_pipe_sampler.c @@ -4,10 +4,10 @@ #include "pipe/p_context.h" #include "pipe/p_state.h" +#include "util/u_inlines.h" #include "brw_context.h" #include "brw_defines.h" -#include "brw_debug.h" diff --git a/src/gallium/drivers/i965/brw_pipe_shader.c b/src/gallium/drivers/i965/brw_pipe_shader.c index bb32d90e33..fe445b9982 100644 --- a/src/gallium/drivers/i965/brw_pipe_shader.c +++ b/src/gallium/drivers/i965/brw_pipe_shader.c @@ -29,13 +29,13 @@ * Keith Whitwell <keith@tungstengraphics.com> */ +#include "util/u_inlines.h" #include "util/u_memory.h" #include "tgsi/tgsi_parse.h" #include "tgsi/tgsi_scan.h" #include "brw_context.h" -#include "brw_util.h" #include "brw_wm.h" @@ -262,7 +262,7 @@ static void brw_delete_vs_state( struct pipe_context *pipe, void *prog ) static void brw_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - const struct pipe_constant_buffer *buf) + struct pipe_buffer *buf) { struct brw_context *brw = brw_context(pipe); @@ -270,13 +270,13 @@ static void brw_set_constant_buffer(struct pipe_context *pipe, if (shader == PIPE_SHADER_FRAGMENT) { pipe_buffer_reference( &brw->curr.fragment_constants, - buf->buffer ); + buf ); brw->state.dirty.mesa |= PIPE_NEW_FRAGMENT_CONSTANTS; } else { pipe_buffer_reference( &brw->curr.vertex_constants, - buf->buffer ); + buf ); brw->state.dirty.mesa |= PIPE_NEW_VERTEX_CONSTANTS; } diff --git a/src/gallium/drivers/i965/brw_screen.c b/src/gallium/drivers/i965/brw_screen.c index 0ecacac9a3..184cd490e5 100644 --- a/src/gallium/drivers/i965/brw_screen.c +++ b/src/gallium/drivers/i965/brw_screen.c @@ -26,7 +26,7 @@ **************************************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_string.h" @@ -138,6 +138,9 @@ brw_get_name(struct pipe_screen *screen) case PCI_CHIP_ILM_G: chipset = "ILM_G"; break; + default: + chipset = "unknown"; + break; } util_snprintf(buffer, sizeof(buffer), "i965 (chipset: %s)", chipset); @@ -172,6 +175,12 @@ brw_get_param(struct pipe_screen *screen, int param) return 8; /* max 128x128x128 */ case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: return 11; /* max 1024x1024 */ + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 0; default: return 0; } @@ -388,6 +397,7 @@ brw_create_screen(struct brw_winsys_screen *sws, uint pci_id) bscreen->base.get_param = brw_get_param; bscreen->base.get_paramf = brw_get_paramf; bscreen->base.is_format_supported = brw_is_format_supported; + bscreen->base.context_create = brw_create_context; bscreen->base.fence_reference = brw_fence_reference; bscreen->base.fence_signalled = brw_fence_signalled; bscreen->base.fence_finish = brw_fence_finish; diff --git a/src/gallium/drivers/i965/brw_screen_buffers.c b/src/gallium/drivers/i965/brw_screen_buffers.c index d8141a3f5b..0b38885f40 100644 --- a/src/gallium/drivers/i965/brw_screen_buffers.c +++ b/src/gallium/drivers/i965/brw_screen_buffers.c @@ -4,7 +4,7 @@ #include "pipe/p_state.h" #include "pipe/p_defines.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "brw_screen.h" #include "brw_winsys.h" diff --git a/src/gallium/drivers/i965/brw_sf.c b/src/gallium/drivers/i965/brw_sf.c index fc3102b531..9cceb4dbe5 100644 --- a/src/gallium/drivers/i965/brw_sf.c +++ b/src/gallium/drivers/i965/brw_sf.c @@ -36,7 +36,6 @@ #include "brw_context.h" #include "brw_pipe_rast.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_sf.h" #include "brw_state.h" diff --git a/src/gallium/drivers/i965/brw_sf_emit.c b/src/gallium/drivers/i965/brw_sf_emit.c index 3b85725e36..497634ec9e 100644 --- a/src/gallium/drivers/i965/brw_sf_emit.c +++ b/src/gallium/drivers/i965/brw_sf_emit.c @@ -35,7 +35,6 @@ #include "brw_defines.h" #include "brw_context.h" #include "brw_eu.h" -#include "brw_util.h" #include "brw_sf.h" diff --git a/src/gallium/drivers/i965/brw_state_cache.c b/src/gallium/drivers/i965/brw_state_cache.c index 16b643ceb2..85c20076fb 100644 --- a/src/gallium/drivers/i965/brw_state_cache.c +++ b/src/gallium/drivers/i965/brw_state_cache.c @@ -59,7 +59,6 @@ #include "brw_debug.h" #include "brw_state.h" -#include "brw_batchbuffer.h" /* XXX: Fixme - have to include these to get the sizes of the prog_key * structs: diff --git a/src/gallium/drivers/i965/brw_util.c b/src/gallium/drivers/i965/brw_util.c index 458058d668..1fd2e29713 100644 --- a/src/gallium/drivers/i965/brw_util.c +++ b/src/gallium/drivers/i965/brw_util.c @@ -30,8 +30,6 @@ */ -#include "brw_util.h" -#include "brw_defines.h" diff --git a/src/gallium/drivers/i965/brw_vs.c b/src/gallium/drivers/i965/brw_vs.c index e3ea5a3a13..ca8ee79550 100644 --- a/src/gallium/drivers/i965/brw_vs.c +++ b/src/gallium/drivers/i965/brw_vs.c @@ -33,9 +33,7 @@ #include "brw_context.h" #include "brw_vs.h" -#include "brw_util.h" #include "brw_state.h" -#include "brw_pipe_rast.h" diff --git a/src/gallium/drivers/i965/brw_vs_surface_state.c b/src/gallium/drivers/i965/brw_vs_surface_state.c index 177a5170d2..004e3cb4e6 100644 --- a/src/gallium/drivers/i965/brw_vs_surface_state.c +++ b/src/gallium/drivers/i965/brw_vs_surface_state.c @@ -31,7 +31,6 @@ #include "brw_context.h" #include "brw_state.h" -#include "brw_defines.h" #include "brw_winsys.h" /* XXX: disabled true constant buffer functionality diff --git a/src/gallium/drivers/i965/brw_winsys.h b/src/gallium/drivers/i965/brw_winsys.h index a242e31218..c82d00f4a4 100644 --- a/src/gallium/drivers/i965/brw_winsys.h +++ b/src/gallium/drivers/i965/brw_winsys.h @@ -28,7 +28,7 @@ #include "pipe/p_compiler.h" #include "pipe/p_defines.h" -#include "pipe/p_refcnt.h" +#include "util/u_inlines.h" struct brw_winsys; struct pipe_fence_handle; @@ -256,10 +256,6 @@ bo_reference(struct brw_winsys_buffer **ptr, struct brw_winsys_buffer *buf) */ struct pipe_screen *brw_create_screen(struct brw_winsys_screen *iws, unsigned pci_id); -/** - * Create a brw pipe_context. - */ -struct pipe_context *brw_create_context(struct pipe_screen *screen); /** * Get the brw_winsys buffer backing the texture. diff --git a/src/gallium/drivers/i965/brw_wm.c b/src/gallium/drivers/i965/brw_wm.c index fdf820a9aa..5164c90ed6 100644 --- a/src/gallium/drivers/i965/brw_wm.c +++ b/src/gallium/drivers/i965/brw_wm.c @@ -32,7 +32,6 @@ #include "brw_context.h" #include "brw_screen.h" -#include "brw_util.h" #include "brw_wm.h" #include "brw_state.h" #include "brw_debug.h" diff --git a/src/gallium/drivers/i965/brw_wm_fp.c b/src/gallium/drivers/i965/brw_wm_fp.c index 9c5b527f89..9c67759ad0 100644 --- a/src/gallium/drivers/i965/brw_wm_fp.c +++ b/src/gallium/drivers/i965/brw_wm_fp.c @@ -41,7 +41,6 @@ #include "tgsi/tgsi_util.h" #include "brw_wm.h" -#include "brw_util.h" #include "brw_debug.h" diff --git a/src/gallium/drivers/i965/brw_wm_surface_state.c b/src/gallium/drivers/i965/brw_wm_surface_state.c index f92b8198ed..b01a7f194b 100644 --- a/src/gallium/drivers/i965/brw_wm_surface_state.c +++ b/src/gallium/drivers/i965/brw_wm_surface_state.c @@ -34,7 +34,6 @@ #include "brw_batchbuffer.h" #include "brw_context.h" #include "brw_state.h" -#include "brw_defines.h" #include "brw_screen.h" diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c index 9f5b4e6323..9955380e1f 100644 --- a/src/gallium/drivers/identity/id_context.c +++ b/src/gallium/drivers/identity/id_context.c @@ -29,7 +29,6 @@ #include "pipe/p_context.h" #include "util/u_memory.h" -#include "id_public.h" #include "id_context.h" #include "id_objects.h" @@ -404,17 +403,17 @@ static void identity_set_constant_buffer(struct pipe_context *_pipe, uint shader, uint index, - const struct pipe_constant_buffer *_buffer) + struct pipe_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; + struct pipe_buffer *unwrapped_buffer; + struct pipe_buffer *buffer = NULL; - /* unwrap the input state */ + /* XXX hmm? unwrap the input state */ if (_buffer) { - unwrapped_buffer.buffer = identity_buffer_unwrap(_buffer->buffer); - buffer = &unwrapped_buffer; + unwrapped_buffer = identity_buffer_unwrap(_buffer); + buffer = unwrapped_buffer; } pipe->set_constant_buffer(pipe, @@ -692,7 +691,7 @@ identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) id_pipe->base.winsys = NULL; id_pipe->base.screen = _screen; - id_pipe->base.priv = pipe->priv; + id_pipe->base.priv = pipe->priv; /* expose wrapped data */ id_pipe->base.draw = NULL; id_pipe->base.destroy = identity_destroy; diff --git a/src/gallium/drivers/identity/id_context.h b/src/gallium/drivers/identity/id_context.h index 75b73fc7df..6d3c1899d5 100644 --- a/src/gallium/drivers/identity/id_context.h +++ b/src/gallium/drivers/identity/id_context.h @@ -39,6 +39,10 @@ struct identity_context { }; +struct pipe_context * +identity_context_create(struct pipe_screen *screen, struct pipe_context *pipe); + + static INLINE struct identity_context * identity_context(struct pipe_context *pipe) { diff --git a/src/gallium/drivers/identity/id_drm.c b/src/gallium/drivers/identity/id_drm.c index 14f68ac0d0..12b516b445 100644 --- a/src/gallium/drivers/identity/id_drm.c +++ b/src/gallium/drivers/identity/id_drm.c @@ -63,22 +63,6 @@ identity_drm_create_screen(struct drm_api *_api, int fd, 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 struct pipe_texture * identity_drm_texture_from_shared_handle(struct drm_api *_api, @@ -159,7 +143,6 @@ identity_drm_create(struct drm_api *api) goto error; id_api->base.create_screen = identity_drm_create_screen; - id_api->base.create_context = identity_drm_create_context; id_api->base.texture_from_shared_handle = identity_drm_texture_from_shared_handle; id_api->base.shared_handle_from_texture = identity_drm_shared_handle_from_texture; id_api->base.local_handle_from_texture = identity_drm_local_handle_from_texture; diff --git a/src/gallium/drivers/identity/id_objects.c b/src/gallium/drivers/identity/id_objects.c index bc9bc7121d..2b1a60c1bf 100644 --- a/src/gallium/drivers/identity/id_objects.c +++ b/src/gallium/drivers/identity/id_objects.c @@ -25,9 +25,9 @@ * **************************************************************************/ +#include "util/u_inlines.h" #include "util/u_memory.h" -#include "id_public.h" #include "id_screen.h" #include "id_objects.h" diff --git a/src/gallium/drivers/identity/id_public.h b/src/gallium/drivers/identity/id_public.h index 3d2862eaa0..d0d5847c61 100644 --- a/src/gallium/drivers/identity/id_public.h +++ b/src/gallium/drivers/identity/id_public.h @@ -34,7 +34,4 @@ 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 /* ID_PUBLIC_H */ diff --git a/src/gallium/drivers/identity/id_screen.c b/src/gallium/drivers/identity/id_screen.c index 53eae3ef54..b85492114a 100644 --- a/src/gallium/drivers/identity/id_screen.c +++ b/src/gallium/drivers/identity/id_screen.c @@ -32,6 +32,7 @@ #include "id_public.h" #include "id_screen.h" +#include "id_context.h" #include "id_objects.h" @@ -103,6 +104,20 @@ identity_screen_is_format_supported(struct pipe_screen *_screen, geom_flags); } +static struct pipe_context * +identity_screen_context_create(struct pipe_screen *_screen, + void *priv) +{ + struct identity_screen *id_screen = identity_screen(_screen); + struct pipe_screen *screen = id_screen->screen; + struct pipe_context *result; + + result = screen->context_create(screen, priv); + if (result) + return identity_context_create(_screen, result); + return NULL; +} + static struct pipe_texture * identity_screen_texture_create(struct pipe_screen *_screen, const struct pipe_texture *templat) @@ -478,6 +493,7 @@ identity_screen_create(struct pipe_screen *screen) 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.context_create = identity_screen_context_create; 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; diff --git a/src/gallium/drivers/llvmpipe/Makefile b/src/gallium/drivers/llvmpipe/Makefile index 7c6e46006b..e880042b71 100644 --- a/src/gallium/drivers/llvmpipe/Makefile +++ b/src/gallium/drivers/llvmpipe/Makefile @@ -3,42 +3,28 @@ include $(TOP)/configs/current LIBNAME = llvmpipe -CFLAGS += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS +DEFINES += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS C_SOURCES = \ - lp_bld_alpha.c \ - lp_bld_arit.c \ - lp_bld_blend_aos.c \ - lp_bld_blend_logicop.c \ - lp_bld_blend_soa.c \ - lp_bld_const.c \ - lp_bld_conv.c \ - lp_bld_debug.c \ - lp_bld_depth.c \ - lp_bld_flow.c \ - lp_bld_format_aos.c \ - lp_bld_format_query.c \ - lp_bld_format_soa.c \ - lp_bld_interp.c \ - lp_bld_intr.c \ - lp_bld_logic.c \ - lp_bld_pack.c \ - lp_bld_sample.c \ - lp_bld_sample_soa.c \ - lp_bld_swizzle.c \ - lp_bld_struct.c \ - lp_bld_tgsi_soa.c \ - lp_bld_type.c \ lp_buffer.c \ lp_clear.c \ lp_context.c \ lp_draw_arrays.c \ + lp_fence.c \ lp_flush.c \ lp_jit.c \ - lp_prim_vbuf.c \ - lp_setup.c \ + lp_perf.c \ lp_query.c \ + lp_rast.c \ + lp_rast_tri.c \ + lp_scene.c \ + lp_scene_queue.c \ lp_screen.c \ + lp_setup.c \ + lp_setup_line.c \ + lp_setup_point.c \ + lp_setup_tri.c \ + lp_setup_vbuf.c \ lp_state_blend.c \ lp_state_clip.c \ lp_state_derived.c \ @@ -49,16 +35,32 @@ C_SOURCES = \ lp_state_vertex.c \ lp_state_vs.c \ lp_surface.c \ - lp_tex_cache.c \ lp_tex_sample_llvm.c \ lp_texture.c \ - lp_tile_cache.c \ + lp_tile_surface.c \ lp_tile_soa.c CPP_SOURCES = \ - lp_bld_misc.cpp + include ../../Makefile.template lp_tile_soa.c: lp_tile_soa.py ../../auxiliary/util/u_format_parse.py ../../auxiliary/util/u_format_access.py ../../auxiliary/util/u_format.csv python lp_tile_soa.py ../../auxiliary/util/u_format.csv > $@ + + +# to make a .s file to inspect assembly code +.c.s: + $(CC) -S $(INCLUDES) $(DEFINES) $(CFLAGS) $(LIBRARY_DEFINES) $< + + +testprogs := lp_test_format \ + lp_test_blend \ + lp_test_conv + +LIBS += $(GL_LIB_DEPS) -L. -lllvmpipe -L../../auxiliary/ -lgallium + +$(testprogs): lp_test_% : lp_test_%.o lp_test_main.o libllvmpipe.a + $(LD) $(filter %.o,$^) -o $@ -Wl,--start-group $(LIBS) -Wl,--end-group + +default: $(testprogs) diff --git a/src/gallium/drivers/llvmpipe/SConscript b/src/gallium/drivers/llvmpipe/SConscript index 6bb545a501..a39283e5e8 100644 --- a/src/gallium/drivers/llvmpipe/SConscript +++ b/src/gallium/drivers/llvmpipe/SConscript @@ -21,40 +21,25 @@ env.CodeGenerate( llvmpipe = env.ConvenienceLibrary( target = 'llvmpipe', source = [ - 'lp_bld_alpha.c', - 'lp_bld_arit.c', - 'lp_bld_blend_aos.c', - 'lp_bld_blend_logicop.c', - 'lp_bld_blend_soa.c', - 'lp_bld_const.c', - 'lp_bld_conv.c', - 'lp_bld_debug.c', - 'lp_bld_depth.c', - 'lp_bld_flow.c', - 'lp_bld_format_aos.c', - 'lp_bld_format_query.c', - 'lp_bld_format_soa.c', - 'lp_bld_interp.c', - 'lp_bld_intr.c', - 'lp_bld_misc.cpp', - 'lp_bld_pack.c', - 'lp_bld_sample.c', - 'lp_bld_sample_soa.c', - 'lp_bld_struct.c', - 'lp_bld_logic.c', - 'lp_bld_swizzle.c', - 'lp_bld_tgsi_soa.c', - 'lp_bld_type.c', 'lp_buffer.c', 'lp_clear.c', 'lp_context.c', 'lp_draw_arrays.c', + 'lp_fence.c', 'lp_flush.c', 'lp_jit.c', - 'lp_prim_vbuf.c', - 'lp_setup.c', + 'lp_perf.c', 'lp_query.c', + 'lp_rast.c', + 'lp_rast_tri.c', + 'lp_scene.c', + 'lp_scene_queue.c', 'lp_screen.c', + 'lp_setup.c', + 'lp_setup_line.c', + 'lp_setup_point.c', + 'lp_setup_tri.c', + 'lp_setup_vbuf.c', 'lp_state_blend.c', 'lp_state_clip.c', 'lp_state_derived.c', @@ -65,29 +50,28 @@ llvmpipe = env.ConvenienceLibrary( 'lp_state_vertex.c', 'lp_state_vs.c', 'lp_surface.c', - 'lp_tex_cache.c', 'lp_tex_sample_llvm.c', 'lp_texture.c', - 'lp_tile_cache.c', 'lp_tile_soa.c', ]) -env = env.Clone() +if env['platform'] != 'embedded': + env = env.Clone() -env.Prepend(LIBS = [llvmpipe] + gallium) + env.Prepend(LIBS = [llvmpipe] + gallium) -tests = [ - 'format', - 'blend', - 'conv', -] + tests = [ + 'format', + 'blend', + 'conv', + ] -for test in tests: - target = env.Program( - target = 'lp_test_' + test, - source = ['lp_test_' + test + '.c', 'lp_test_main.c'], - ) - env.InstallProgram(target) + for test in tests: + target = env.Program( + target = 'lp_test_' + test, + source = ['lp_test_' + test + '.c', 'lp_test_main.c'], + ) + env.InstallProgram(target) -Export('llvmpipe') + Export('llvmpipe') diff --git a/src/gallium/drivers/llvmpipe/lp_bld_alpha.c b/src/gallium/drivers/llvmpipe/lp_bld_alpha.c deleted file mode 100644 index 2b4bc5c819..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_alpha.c +++ /dev/null @@ -1,64 +0,0 @@ -/************************************************************************** - * - * 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. - * - **************************************************************************/ - -/** - * Alpha testing to LLVM IR translation. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - -#include "pipe/p_state.h" - -#include "lp_bld_type.h" -#include "lp_bld_const.h" -#include "lp_bld_arit.h" -#include "lp_bld_logic.h" -#include "lp_bld_flow.h" -#include "lp_bld_debug.h" -#include "lp_bld_alpha.h" - - -void -lp_build_alpha_test(LLVMBuilderRef builder, - const struct pipe_alpha_state *state, - struct lp_type type, - struct lp_build_mask_context *mask, - LLVMValueRef alpha, - LLVMValueRef ref) -{ - struct lp_build_context bld; - - lp_build_context_init(&bld, builder, type); - - if(state->enabled) { - LLVMValueRef test = lp_build_cmp(&bld, state->func, alpha, ref); - - lp_build_name(test, "alpha_mask"); - - lp_build_mask_update(mask, test); - } -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_arit.c b/src/gallium/drivers/llvmpipe/lp_bld_arit.c deleted file mode 100644 index eea6b5d6a5..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_arit.c +++ /dev/null @@ -1,1318 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -/** - * @file - * Helper - * - * LLVM IR doesn't support all basic arithmetic operations we care about (most - * notably min/max and saturated operations), and it is often necessary to - * resort machine-specific intrinsics directly. The functions here hide all - * these implementation details from the other modules. - * - * We also do simple expressions simplification here. Reasons are: - * - it is very easy given we have all necessary information readily available - * - LLVM optimization passes fail to simplify several vector expressions - * - We often know value constraints which the optimization passes have no way - * of knowing, such as when source arguments are known to be in [0, 1] range. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#include "util/u_memory.h" -#include "util/u_debug.h" -#include "util/u_math.h" -#include "util/u_string.h" -#include "util/u_cpu_detect.h" - -#include "lp_bld_type.h" -#include "lp_bld_const.h" -#include "lp_bld_intr.h" -#include "lp_bld_logic.h" -#include "lp_bld_pack.h" -#include "lp_bld_debug.h" -#include "lp_bld_arit.h" - - -/** - * Generate min(a, b) - * No checks for special case values of a or b = 1 or 0 are done. - */ -static LLVMValueRef -lp_build_min_simple(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b) -{ - const struct lp_type type = bld->type; - const char *intrinsic = NULL; - LLVMValueRef cond; - - /* TODO: optimize the constant case */ - - if(type.width * type.length == 128) { - if(type.floating) { - if(type.width == 32 && util_cpu_caps.has_sse) - intrinsic = "llvm.x86.sse.min.ps"; - if(type.width == 64 && util_cpu_caps.has_sse2) - intrinsic = "llvm.x86.sse2.min.pd"; - } - else { - if(type.width == 8 && !type.sign && util_cpu_caps.has_sse2) - intrinsic = "llvm.x86.sse2.pminu.b"; - if(type.width == 8 && type.sign && util_cpu_caps.has_sse4_1) - intrinsic = "llvm.x86.sse41.pminsb"; - if(type.width == 16 && !type.sign && util_cpu_caps.has_sse4_1) - intrinsic = "llvm.x86.sse41.pminuw"; - if(type.width == 16 && type.sign && util_cpu_caps.has_sse2) - intrinsic = "llvm.x86.sse2.pmins.w"; - if(type.width == 32 && !type.sign && util_cpu_caps.has_sse4_1) - intrinsic = "llvm.x86.sse41.pminud"; - if(type.width == 32 && type.sign && util_cpu_caps.has_sse4_1) - intrinsic = "llvm.x86.sse41.pminsd"; - } - } - - if(intrinsic) - return lp_build_intrinsic_binary(bld->builder, intrinsic, lp_build_vec_type(bld->type), a, b); - - cond = lp_build_cmp(bld, PIPE_FUNC_LESS, a, b); - return lp_build_select(bld, cond, a, b); -} - - -/** - * Generate max(a, b) - * No checks for special case values of a or b = 1 or 0 are done. - */ -static LLVMValueRef -lp_build_max_simple(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b) -{ - const struct lp_type type = bld->type; - const char *intrinsic = NULL; - LLVMValueRef cond; - - /* TODO: optimize the constant case */ - - if(type.width * type.length == 128) { - if(type.floating) { - if(type.width == 32 && util_cpu_caps.has_sse) - intrinsic = "llvm.x86.sse.max.ps"; - if(type.width == 64 && util_cpu_caps.has_sse2) - intrinsic = "llvm.x86.sse2.max.pd"; - } - else { - if(type.width == 8 && !type.sign && util_cpu_caps.has_sse2) - intrinsic = "llvm.x86.sse2.pmaxu.b"; - if(type.width == 8 && type.sign && util_cpu_caps.has_sse4_1) - intrinsic = "llvm.x86.sse41.pmaxsb"; - if(type.width == 16 && !type.sign && util_cpu_caps.has_sse4_1) - intrinsic = "llvm.x86.sse41.pmaxuw"; - if(type.width == 16 && type.sign && util_cpu_caps.has_sse2) - intrinsic = "llvm.x86.sse2.pmaxs.w"; - if(type.width == 32 && !type.sign && util_cpu_caps.has_sse4_1) - intrinsic = "llvm.x86.sse41.pmaxud"; - if(type.width == 32 && type.sign && util_cpu_caps.has_sse4_1) - intrinsic = "llvm.x86.sse41.pmaxsd"; - } - } - - if(intrinsic) - return lp_build_intrinsic_binary(bld->builder, intrinsic, lp_build_vec_type(bld->type), a, b); - - cond = lp_build_cmp(bld, PIPE_FUNC_GREATER, a, b); - return lp_build_select(bld, cond, a, b); -} - - -/** - * Generate 1 - a, or ~a depending on bld->type. - */ -LLVMValueRef -lp_build_comp(struct lp_build_context *bld, - LLVMValueRef a) -{ - const struct lp_type type = bld->type; - - if(a == bld->one) - return bld->zero; - if(a == bld->zero) - return bld->one; - - if(type.norm && !type.floating && !type.fixed && !type.sign) { - if(LLVMIsConstant(a)) - return LLVMConstNot(a); - else - return LLVMBuildNot(bld->builder, a, ""); - } - - if(LLVMIsConstant(a)) - return LLVMConstSub(bld->one, a); - else - return LLVMBuildSub(bld->builder, bld->one, a, ""); -} - - -/** - * Generate a + b - */ -LLVMValueRef -lp_build_add(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b) -{ - const struct lp_type type = bld->type; - LLVMValueRef res; - - if(a == bld->zero) - return b; - if(b == bld->zero) - return a; - if(a == bld->undef || b == bld->undef) - return bld->undef; - - if(bld->type.norm) { - const char *intrinsic = NULL; - - if(a == bld->one || b == bld->one) - return bld->one; - - if(util_cpu_caps.has_sse2 && - type.width * type.length == 128 && - !type.floating && !type.fixed) { - if(type.width == 8) - intrinsic = type.sign ? "llvm.x86.sse2.padds.b" : "llvm.x86.sse2.paddus.b"; - if(type.width == 16) - intrinsic = type.sign ? "llvm.x86.sse2.padds.w" : "llvm.x86.sse2.paddus.w"; - } - - if(intrinsic) - return lp_build_intrinsic_binary(bld->builder, intrinsic, lp_build_vec_type(bld->type), a, b); - } - - if(LLVMIsConstant(a) && LLVMIsConstant(b)) - res = LLVMConstAdd(a, b); - else - res = LLVMBuildAdd(bld->builder, a, b, ""); - - /* clamp to ceiling of 1.0 */ - if(bld->type.norm && (bld->type.floating || bld->type.fixed)) - res = lp_build_min_simple(bld, res, bld->one); - - /* XXX clamp to floor of -1 or 0??? */ - - return res; -} - - -/** - * Generate a - b - */ -LLVMValueRef -lp_build_sub(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b) -{ - const struct lp_type type = bld->type; - LLVMValueRef res; - - if(b == bld->zero) - return a; - if(a == bld->undef || b == bld->undef) - return bld->undef; - if(a == b) - return bld->zero; - - if(bld->type.norm) { - const char *intrinsic = NULL; - - if(b == bld->one) - return bld->zero; - - if(util_cpu_caps.has_sse2 && - type.width * type.length == 128 && - !type.floating && !type.fixed) { - if(type.width == 8) - intrinsic = type.sign ? "llvm.x86.sse2.psubs.b" : "llvm.x86.sse2.psubus.b"; - if(type.width == 16) - intrinsic = type.sign ? "llvm.x86.sse2.psubs.w" : "llvm.x86.sse2.psubus.w"; - } - - if(intrinsic) - return lp_build_intrinsic_binary(bld->builder, intrinsic, lp_build_vec_type(bld->type), a, b); - } - - if(LLVMIsConstant(a) && LLVMIsConstant(b)) - res = LLVMConstSub(a, b); - else - res = LLVMBuildSub(bld->builder, a, b, ""); - - if(bld->type.norm && (bld->type.floating || bld->type.fixed)) - res = lp_build_max_simple(bld, res, bld->zero); - - return res; -} - - -/** - * Normalized 8bit multiplication. - * - * - alpha plus one - * - * makes the following approximation to the division (Sree) - * - * a*b/255 ~= (a*(b + 1)) >> 256 - * - * which is the fastest method that satisfies the following OpenGL criteria - * - * 0*0 = 0 and 255*255 = 255 - * - * - geometric series - * - * takes the geometric series approximation to the division - * - * t/255 = (t >> 8) + (t >> 16) + (t >> 24) .. - * - * in this case just the first two terms to fit in 16bit arithmetic - * - * t/255 ~= (t + (t >> 8)) >> 8 - * - * note that just by itself it doesn't satisfies the OpenGL criteria, as - * 255*255 = 254, so the special case b = 255 must be accounted or roundoff - * must be used - * - * - geometric series plus rounding - * - * when using a geometric series division instead of truncating the result - * use roundoff in the approximation (Jim Blinn) - * - * t/255 ~= (t + (t >> 8) + 0x80) >> 8 - * - * achieving the exact results - * - * @sa Alvy Ray Smith, Image Compositing Fundamentals, Tech Memo 4, Aug 15, 1995, - * ftp://ftp.alvyray.com/Acrobat/4_Comp.pdf - * @sa Michael Herf, The "double blend trick", May 2000, - * http://www.stereopsis.com/doubleblend.html - */ -static LLVMValueRef -lp_build_mul_u8n(LLVMBuilderRef builder, - struct lp_type i16_type, - LLVMValueRef a, LLVMValueRef b) -{ - LLVMValueRef c8; - LLVMValueRef ab; - - c8 = lp_build_int_const_scalar(i16_type, 8); - -#if 0 - - /* a*b/255 ~= (a*(b + 1)) >> 256 */ - b = LLVMBuildAdd(builder, b, lp_build_int_const_scalar(i16_type, 1), ""); - ab = LLVMBuildMul(builder, a, b, ""); - -#else - - /* ab/255 ~= (ab + (ab >> 8) + 0x80) >> 8 */ - ab = LLVMBuildMul(builder, a, b, ""); - ab = LLVMBuildAdd(builder, ab, LLVMBuildLShr(builder, ab, c8, ""), ""); - ab = LLVMBuildAdd(builder, ab, lp_build_int_const_scalar(i16_type, 0x80), ""); - -#endif - - ab = LLVMBuildLShr(builder, ab, c8, ""); - - return ab; -} - - -/** - * Generate a * b - */ -LLVMValueRef -lp_build_mul(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b) -{ - const struct lp_type type = bld->type; - LLVMValueRef shift; - LLVMValueRef res; - - if(a == bld->zero) - return bld->zero; - if(a == bld->one) - return b; - if(b == bld->zero) - return bld->zero; - if(b == bld->one) - return a; - if(a == bld->undef || b == bld->undef) - return bld->undef; - - if(!type.floating && !type.fixed && type.norm) { - if(type.width == 8) { - struct lp_type i16_type = lp_wider_type(type); - LLVMValueRef al, ah, bl, bh, abl, abh, ab; - - lp_build_unpack2(bld->builder, type, i16_type, a, &al, &ah); - lp_build_unpack2(bld->builder, type, i16_type, b, &bl, &bh); - - /* PMULLW, PSRLW, PADDW */ - abl = lp_build_mul_u8n(bld->builder, i16_type, al, bl); - abh = lp_build_mul_u8n(bld->builder, i16_type, ah, bh); - - ab = lp_build_pack2(bld->builder, i16_type, type, abl, abh); - - return ab; - } - - /* FIXME */ - assert(0); - } - - if(type.fixed) - shift = lp_build_int_const_scalar(type, type.width/2); - else - shift = NULL; - - if(LLVMIsConstant(a) && LLVMIsConstant(b)) { - res = LLVMConstMul(a, b); - if(shift) { - if(type.sign) - res = LLVMConstAShr(res, shift); - else - res = LLVMConstLShr(res, shift); - } - } - else { - res = LLVMBuildMul(bld->builder, a, b, ""); - if(shift) { - if(type.sign) - res = LLVMBuildAShr(bld->builder, res, shift, ""); - else - res = LLVMBuildLShr(bld->builder, res, shift, ""); - } - } - - return res; -} - - -/** - * Small vector x scale multiplication optimization. - */ -LLVMValueRef -lp_build_mul_imm(struct lp_build_context *bld, - LLVMValueRef a, - int b) -{ - LLVMValueRef factor; - - if(b == 0) - return bld->zero; - - if(b == 1) - return a; - - if(b == -1) - return LLVMBuildNeg(bld->builder, a, ""); - - if(b == 2 && bld->type.floating) - return lp_build_add(bld, a, a); - - if(util_is_pot(b)) { - unsigned shift = ffs(b) - 1; - - if(bld->type.floating) { -#if 0 - /* - * Power of two multiplication by directly manipulating the mantissa. - * - * XXX: This might not be always faster, it will introduce a small error - * for multiplication by zero, and it will produce wrong results - * for Inf and NaN. - */ - unsigned mantissa = lp_mantissa(bld->type); - factor = lp_build_int_const_scalar(bld->type, (unsigned long long)shift << mantissa); - a = LLVMBuildBitCast(bld->builder, a, lp_build_int_vec_type(bld->type), ""); - a = LLVMBuildAdd(bld->builder, a, factor, ""); - a = LLVMBuildBitCast(bld->builder, a, lp_build_vec_type(bld->type), ""); - return a; -#endif - } - else { - factor = lp_build_const_scalar(bld->type, shift); - return LLVMBuildShl(bld->builder, a, factor, ""); - } - } - - factor = lp_build_const_scalar(bld->type, (double)b); - return lp_build_mul(bld, a, factor); -} - - -/** - * Generate a / b - */ -LLVMValueRef -lp_build_div(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b) -{ - const struct lp_type type = bld->type; - - if(a == bld->zero) - return bld->zero; - if(a == bld->one) - return lp_build_rcp(bld, b); - if(b == bld->zero) - return bld->undef; - if(b == bld->one) - return a; - if(a == bld->undef || b == bld->undef) - return bld->undef; - - if(LLVMIsConstant(a) && LLVMIsConstant(b)) - return LLVMConstFDiv(a, b); - - if(util_cpu_caps.has_sse && type.width == 32 && type.length == 4) - return lp_build_mul(bld, a, lp_build_rcp(bld, b)); - - return LLVMBuildFDiv(bld->builder, a, b, ""); -} - - -/** - * Linear interpolation. - * - * This also works for integer values with a few caveats. - * - * @sa http://www.stereopsis.com/doubleblend.html - */ -LLVMValueRef -lp_build_lerp(struct lp_build_context *bld, - LLVMValueRef x, - LLVMValueRef v0, - LLVMValueRef v1) -{ - LLVMValueRef delta; - LLVMValueRef res; - - delta = lp_build_sub(bld, v1, v0); - - res = lp_build_mul(bld, x, delta); - - res = lp_build_add(bld, v0, res); - - if(bld->type.fixed) - /* XXX: This step is necessary for lerping 8bit colors stored on 16bits, - * but it will be wrong for other uses. Basically we need a more - * powerful lp_type, capable of further distinguishing the values - * interpretation from the value storage. */ - res = LLVMBuildAnd(bld->builder, res, lp_build_int_const_scalar(bld->type, (1 << bld->type.width/2) - 1), ""); - - return res; -} - - -LLVMValueRef -lp_build_lerp_2d(struct lp_build_context *bld, - LLVMValueRef x, - LLVMValueRef y, - LLVMValueRef v00, - LLVMValueRef v01, - LLVMValueRef v10, - LLVMValueRef v11) -{ - LLVMValueRef v0 = lp_build_lerp(bld, x, v00, v01); - LLVMValueRef v1 = lp_build_lerp(bld, x, v10, v11); - return lp_build_lerp(bld, y, v0, v1); -} - - -/** - * Generate min(a, b) - * Do checks for special cases. - */ -LLVMValueRef -lp_build_min(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b) -{ - if(a == bld->undef || b == bld->undef) - return bld->undef; - - if(a == b) - return a; - - if(bld->type.norm) { - if(a == bld->zero || b == bld->zero) - return bld->zero; - if(a == bld->one) - return b; - if(b == bld->one) - return a; - } - - return lp_build_min_simple(bld, a, b); -} - - -/** - * Generate max(a, b) - * Do checks for special cases. - */ -LLVMValueRef -lp_build_max(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b) -{ - if(a == bld->undef || b == bld->undef) - return bld->undef; - - if(a == b) - return a; - - if(bld->type.norm) { - if(a == bld->one || b == bld->one) - return bld->one; - if(a == bld->zero) - return b; - if(b == bld->zero) - return a; - } - - return lp_build_max_simple(bld, a, b); -} - - -/** - * Generate abs(a) - */ -LLVMValueRef -lp_build_abs(struct lp_build_context *bld, - LLVMValueRef a) -{ - const struct lp_type type = bld->type; - LLVMTypeRef vec_type = lp_build_vec_type(type); - - if(!type.sign) - return a; - - if(type.floating) { - /* Mask out the sign bit */ - LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); - unsigned long absMask = ~(1 << (type.width - 1)); - LLVMValueRef mask = lp_build_int_const_scalar(type, ((unsigned long long) absMask)); - a = LLVMBuildBitCast(bld->builder, a, int_vec_type, ""); - a = LLVMBuildAnd(bld->builder, a, mask, ""); - a = LLVMBuildBitCast(bld->builder, a, vec_type, ""); - return a; - } - - if(type.width*type.length == 128 && util_cpu_caps.has_ssse3) { - switch(type.width) { - case 8: - return lp_build_intrinsic_unary(bld->builder, "llvm.x86.ssse3.pabs.b.128", vec_type, a); - case 16: - return lp_build_intrinsic_unary(bld->builder, "llvm.x86.ssse3.pabs.w.128", vec_type, a); - case 32: - return lp_build_intrinsic_unary(bld->builder, "llvm.x86.ssse3.pabs.d.128", vec_type, a); - } - } - - return lp_build_max(bld, a, LLVMBuildNeg(bld->builder, a, "")); -} - - -LLVMValueRef -lp_build_sgn(struct lp_build_context *bld, - LLVMValueRef a) -{ - const struct lp_type type = bld->type; - LLVMTypeRef vec_type = lp_build_vec_type(type); - LLVMValueRef cond; - LLVMValueRef res; - - /* Handle non-zero case */ - if(!type.sign) { - /* if not zero then sign must be positive */ - res = bld->one; - } - else if(type.floating) { - /* Take the sign bit and add it to 1 constant */ - LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); - LLVMValueRef mask = lp_build_int_const_scalar(type, (unsigned long long)1 << (type.width - 1)); - LLVMValueRef sign; - LLVMValueRef one; - sign = LLVMBuildBitCast(bld->builder, a, int_vec_type, ""); - sign = LLVMBuildAnd(bld->builder, sign, mask, ""); - one = LLVMConstBitCast(bld->one, int_vec_type); - res = LLVMBuildOr(bld->builder, sign, one, ""); - res = LLVMBuildBitCast(bld->builder, res, vec_type, ""); - } - else - { - LLVMValueRef minus_one = lp_build_const_scalar(type, -1.0); - cond = lp_build_cmp(bld, PIPE_FUNC_GREATER, a, bld->zero); - res = lp_build_select(bld, cond, bld->one, minus_one); - } - - /* Handle zero */ - cond = lp_build_cmp(bld, PIPE_FUNC_EQUAL, a, bld->zero); - res = lp_build_select(bld, cond, bld->zero, bld->one); - - return res; -} - - -enum lp_build_round_sse41_mode -{ - LP_BUILD_ROUND_SSE41_NEAREST = 0, - LP_BUILD_ROUND_SSE41_FLOOR = 1, - LP_BUILD_ROUND_SSE41_CEIL = 2, - LP_BUILD_ROUND_SSE41_TRUNCATE = 3 -}; - - -static INLINE LLVMValueRef -lp_build_round_sse41(struct lp_build_context *bld, - LLVMValueRef a, - enum lp_build_round_sse41_mode mode) -{ - const struct lp_type type = bld->type; - LLVMTypeRef vec_type = lp_build_vec_type(type); - const char *intrinsic; - - assert(type.floating); - assert(type.width*type.length == 128); - assert(lp_check_value(type, a)); - assert(util_cpu_caps.has_sse4_1); - - switch(type.width) { - case 32: - intrinsic = "llvm.x86.sse41.round.ps"; - break; - case 64: - intrinsic = "llvm.x86.sse41.round.pd"; - break; - default: - assert(0); - return bld->undef; - } - - return lp_build_intrinsic_binary(bld->builder, intrinsic, vec_type, a, - LLVMConstInt(LLVMInt32Type(), mode, 0)); -} - - -LLVMValueRef -lp_build_trunc(struct lp_build_context *bld, - LLVMValueRef a) -{ - const struct lp_type type = bld->type; - - assert(type.floating); - assert(lp_check_value(type, a)); - - if(util_cpu_caps.has_sse4_1) - return lp_build_round_sse41(bld, a, LP_BUILD_ROUND_SSE41_TRUNCATE); - else { - LLVMTypeRef vec_type = lp_build_vec_type(type); - LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); - LLVMValueRef res; - res = LLVMBuildFPToSI(bld->builder, a, int_vec_type, ""); - res = LLVMBuildSIToFP(bld->builder, res, vec_type, ""); - return res; - } -} - - -LLVMValueRef -lp_build_round(struct lp_build_context *bld, - LLVMValueRef a) -{ - const struct lp_type type = bld->type; - - assert(type.floating); - assert(lp_check_value(type, a)); - - if(util_cpu_caps.has_sse4_1) - return lp_build_round_sse41(bld, a, LP_BUILD_ROUND_SSE41_NEAREST); - else { - LLVMTypeRef vec_type = lp_build_vec_type(type); - LLVMValueRef res; - res = lp_build_iround(bld, a); - res = LLVMBuildSIToFP(bld->builder, res, vec_type, ""); - return res; - } -} - - -LLVMValueRef -lp_build_floor(struct lp_build_context *bld, - LLVMValueRef a) -{ - const struct lp_type type = bld->type; - - assert(type.floating); - - if(util_cpu_caps.has_sse4_1) - return lp_build_round_sse41(bld, a, LP_BUILD_ROUND_SSE41_FLOOR); - else { - LLVMTypeRef vec_type = lp_build_vec_type(type); - LLVMValueRef res; - res = lp_build_ifloor(bld, a); - res = LLVMBuildSIToFP(bld->builder, res, vec_type, ""); - return res; - } -} - - -LLVMValueRef -lp_build_ceil(struct lp_build_context *bld, - LLVMValueRef a) -{ - const struct lp_type type = bld->type; - - assert(type.floating); - assert(lp_check_value(type, a)); - - if(util_cpu_caps.has_sse4_1) - return lp_build_round_sse41(bld, a, LP_BUILD_ROUND_SSE41_CEIL); - else { - LLVMTypeRef vec_type = lp_build_vec_type(type); - LLVMValueRef res; - res = lp_build_iceil(bld, a); - res = LLVMBuildSIToFP(bld->builder, res, vec_type, ""); - return res; - } -} - - -/** - * Convert to integer, through whichever rounding method that's fastest, - * typically truncating to zero. - */ -LLVMValueRef -lp_build_itrunc(struct lp_build_context *bld, - LLVMValueRef a) -{ - const struct lp_type type = bld->type; - LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); - - assert(type.floating); - assert(lp_check_value(type, a)); - - return LLVMBuildFPToSI(bld->builder, a, int_vec_type, ""); -} - - -LLVMValueRef -lp_build_iround(struct lp_build_context *bld, - LLVMValueRef a) -{ - const struct lp_type type = bld->type; - LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); - LLVMValueRef res; - - assert(type.floating); - assert(lp_check_value(type, a)); - - if(util_cpu_caps.has_sse4_1) { - res = lp_build_round_sse41(bld, a, LP_BUILD_ROUND_SSE41_NEAREST); - } - else { - LLVMTypeRef vec_type = lp_build_vec_type(type); - LLVMValueRef mask = lp_build_int_const_scalar(type, (unsigned long long)1 << (type.width - 1)); - LLVMValueRef sign; - LLVMValueRef half; - - /* get sign bit */ - sign = LLVMBuildBitCast(bld->builder, a, int_vec_type, ""); - sign = LLVMBuildAnd(bld->builder, sign, mask, ""); - - /* sign * 0.5 */ - half = lp_build_const_scalar(type, 0.5); - half = LLVMBuildBitCast(bld->builder, half, int_vec_type, ""); - half = LLVMBuildOr(bld->builder, sign, half, ""); - half = LLVMBuildBitCast(bld->builder, half, vec_type, ""); - - res = LLVMBuildAdd(bld->builder, a, half, ""); - } - - res = LLVMBuildFPToSI(bld->builder, res, int_vec_type, ""); - - return res; -} - - -LLVMValueRef -lp_build_ifloor(struct lp_build_context *bld, - LLVMValueRef a) -{ - const struct lp_type type = bld->type; - LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); - LLVMValueRef res; - - assert(type.floating); - assert(lp_check_value(type, a)); - - if(util_cpu_caps.has_sse4_1) { - res = lp_build_round_sse41(bld, a, LP_BUILD_ROUND_SSE41_FLOOR); - } - else { - /* Take the sign bit and add it to 1 constant */ - LLVMTypeRef vec_type = lp_build_vec_type(type); - unsigned mantissa = lp_mantissa(type); - LLVMValueRef mask = lp_build_int_const_scalar(type, (unsigned long long)1 << (type.width - 1)); - LLVMValueRef sign; - LLVMValueRef offset; - - /* sign = a < 0 ? ~0 : 0 */ - sign = LLVMBuildBitCast(bld->builder, a, int_vec_type, ""); - sign = LLVMBuildAnd(bld->builder, sign, mask, ""); - sign = LLVMBuildAShr(bld->builder, sign, lp_build_int_const_scalar(type, type.width - 1), ""); - - /* offset = -0.99999(9)f */ - offset = lp_build_const_scalar(type, -(double)(((unsigned long long)1 << mantissa) - 1)/((unsigned long long)1 << mantissa)); - offset = LLVMConstBitCast(offset, int_vec_type); - - /* offset = a < 0 ? -0.99999(9)f : 0.0f */ - offset = LLVMBuildAnd(bld->builder, offset, sign, ""); - offset = LLVMBuildBitCast(bld->builder, offset, vec_type, ""); - - res = LLVMBuildAdd(bld->builder, a, offset, ""); - } - - res = LLVMBuildFPToSI(bld->builder, res, int_vec_type, ""); - - return res; -} - - -LLVMValueRef -lp_build_iceil(struct lp_build_context *bld, - LLVMValueRef a) -{ - const struct lp_type type = bld->type; - LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); - LLVMValueRef res; - - assert(type.floating); - assert(lp_check_value(type, a)); - - if(util_cpu_caps.has_sse4_1) { - res = lp_build_round_sse41(bld, a, LP_BUILD_ROUND_SSE41_CEIL); - } - else { - assert(0); - res = bld->undef; - } - - res = LLVMBuildFPToSI(bld->builder, res, int_vec_type, ""); - - return res; -} - - -LLVMValueRef -lp_build_sqrt(struct lp_build_context *bld, - LLVMValueRef a) -{ - const struct lp_type type = bld->type; - LLVMTypeRef vec_type = lp_build_vec_type(type); - char intrinsic[32]; - - /* TODO: optimize the constant case */ - /* TODO: optimize the constant case */ - - assert(type.floating); - util_snprintf(intrinsic, sizeof intrinsic, "llvm.sqrt.v%uf%u", type.length, type.width); - - return lp_build_intrinsic_unary(bld->builder, intrinsic, vec_type, a); -} - - -LLVMValueRef -lp_build_rcp(struct lp_build_context *bld, - LLVMValueRef a) -{ - const struct lp_type type = bld->type; - - if(a == bld->zero) - return bld->undef; - if(a == bld->one) - return bld->one; - if(a == bld->undef) - return bld->undef; - - assert(type.floating); - - if(LLVMIsConstant(a)) - return LLVMConstFDiv(bld->one, a); - - if(util_cpu_caps.has_sse && type.width == 32 && type.length == 4) - /* FIXME: improve precision */ - return lp_build_intrinsic_unary(bld->builder, "llvm.x86.sse.rcp.ps", lp_build_vec_type(type), a); - - return LLVMBuildFDiv(bld->builder, bld->one, a, ""); -} - - -/** - * Generate 1/sqrt(a) - */ -LLVMValueRef -lp_build_rsqrt(struct lp_build_context *bld, - LLVMValueRef a) -{ - const struct lp_type type = bld->type; - - assert(type.floating); - - if(util_cpu_caps.has_sse && type.width == 32 && type.length == 4) - return lp_build_intrinsic_unary(bld->builder, "llvm.x86.sse.rsqrt.ps", lp_build_vec_type(type), a); - - return lp_build_rcp(bld, lp_build_sqrt(bld, a)); -} - - -/** - * Generate cos(a) - */ -LLVMValueRef -lp_build_cos(struct lp_build_context *bld, - LLVMValueRef a) -{ - const struct lp_type type = bld->type; - LLVMTypeRef vec_type = lp_build_vec_type(type); - char intrinsic[32]; - - /* TODO: optimize the constant case */ - - assert(type.floating); - util_snprintf(intrinsic, sizeof intrinsic, "llvm.cos.v%uf%u", type.length, type.width); - - return lp_build_intrinsic_unary(bld->builder, intrinsic, vec_type, a); -} - - -/** - * Generate sin(a) - */ -LLVMValueRef -lp_build_sin(struct lp_build_context *bld, - LLVMValueRef a) -{ - const struct lp_type type = bld->type; - LLVMTypeRef vec_type = lp_build_vec_type(type); - char intrinsic[32]; - - /* TODO: optimize the constant case */ - - assert(type.floating); - util_snprintf(intrinsic, sizeof intrinsic, "llvm.sin.v%uf%u", type.length, type.width); - - return lp_build_intrinsic_unary(bld->builder, intrinsic, vec_type, a); -} - - -/** - * Generate pow(x, y) - */ -LLVMValueRef -lp_build_pow(struct lp_build_context *bld, - LLVMValueRef x, - LLVMValueRef y) -{ - /* TODO: optimize the constant case */ - if(LLVMIsConstant(x) && LLVMIsConstant(y)) - debug_printf("%s: inefficient/imprecise constant arithmetic\n", - __FUNCTION__); - - return lp_build_exp2(bld, lp_build_mul(bld, lp_build_log2(bld, x), y)); -} - - -/** - * Generate exp(x) - */ -LLVMValueRef -lp_build_exp(struct lp_build_context *bld, - LLVMValueRef x) -{ - /* log2(e) = 1/log(2) */ - LLVMValueRef log2e = lp_build_const_scalar(bld->type, 1.4426950408889634); - - return lp_build_mul(bld, log2e, lp_build_exp2(bld, x)); -} - - -/** - * Generate log(x) - */ -LLVMValueRef -lp_build_log(struct lp_build_context *bld, - LLVMValueRef x) -{ - /* log(2) */ - LLVMValueRef log2 = lp_build_const_scalar(bld->type, 0.69314718055994529); - - return lp_build_mul(bld, log2, lp_build_exp2(bld, x)); -} - - -#define EXP_POLY_DEGREE 3 -#define LOG_POLY_DEGREE 5 - - -/** - * Generate polynomial. - * Ex: coeffs[0] + x * coeffs[1] + x^2 * coeffs[2]. - */ -static LLVMValueRef -lp_build_polynomial(struct lp_build_context *bld, - LLVMValueRef x, - const double *coeffs, - unsigned num_coeffs) -{ - const struct lp_type type = bld->type; - LLVMValueRef res = NULL; - unsigned i; - - /* TODO: optimize the constant case */ - if(LLVMIsConstant(x)) - debug_printf("%s: inefficient/imprecise constant arithmetic\n", - __FUNCTION__); - - for (i = num_coeffs; i--; ) { - LLVMValueRef coeff = lp_build_const_scalar(type, coeffs[i]); - if(res) - res = lp_build_add(bld, coeff, lp_build_mul(bld, x, res)); - else - res = coeff; - } - - if(res) - return res; - else - return bld->undef; -} - - -/** - * Minimax polynomial fit of 2**x, in range [-0.5, 0.5[ - */ -const double lp_build_exp2_polynomial[] = { -#if EXP_POLY_DEGREE == 5 - 9.9999994e-1, 6.9315308e-1, 2.4015361e-1, 5.5826318e-2, 8.9893397e-3, 1.8775767e-3 -#elif EXP_POLY_DEGREE == 4 - 1.0000026, 6.9300383e-1, 2.4144275e-1, 5.2011464e-2, 1.3534167e-2 -#elif EXP_POLY_DEGREE == 3 - 9.9992520e-1, 6.9583356e-1, 2.2606716e-1, 7.8024521e-2 -#elif EXP_POLY_DEGREE == 2 - 1.0017247, 6.5763628e-1, 3.3718944e-1 -#else -#error -#endif -}; - - -void -lp_build_exp2_approx(struct lp_build_context *bld, - LLVMValueRef x, - LLVMValueRef *p_exp2_int_part, - LLVMValueRef *p_frac_part, - LLVMValueRef *p_exp2) -{ - const struct lp_type type = bld->type; - LLVMTypeRef vec_type = lp_build_vec_type(type); - LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); - LLVMValueRef ipart = NULL; - LLVMValueRef fpart = NULL; - LLVMValueRef expipart = NULL; - LLVMValueRef expfpart = NULL; - LLVMValueRef res = NULL; - - if(p_exp2_int_part || p_frac_part || p_exp2) { - /* TODO: optimize the constant case */ - if(LLVMIsConstant(x)) - debug_printf("%s: inefficient/imprecise constant arithmetic\n", - __FUNCTION__); - - assert(type.floating && type.width == 32); - - x = lp_build_min(bld, x, lp_build_const_scalar(type, 129.0)); - x = lp_build_max(bld, x, lp_build_const_scalar(type, -126.99999)); - - /* ipart = int(x - 0.5) */ - ipart = LLVMBuildSub(bld->builder, x, lp_build_const_scalar(type, 0.5f), ""); - ipart = LLVMBuildFPToSI(bld->builder, ipart, int_vec_type, ""); - - /* fpart = x - ipart */ - fpart = LLVMBuildSIToFP(bld->builder, ipart, vec_type, ""); - fpart = LLVMBuildSub(bld->builder, x, fpart, ""); - } - - if(p_exp2_int_part || p_exp2) { - /* expipart = (float) (1 << ipart) */ - expipart = LLVMBuildAdd(bld->builder, ipart, lp_build_int_const_scalar(type, 127), ""); - expipart = LLVMBuildShl(bld->builder, expipart, lp_build_int_const_scalar(type, 23), ""); - expipart = LLVMBuildBitCast(bld->builder, expipart, vec_type, ""); - } - - if(p_exp2) { - expfpart = lp_build_polynomial(bld, fpart, lp_build_exp2_polynomial, - Elements(lp_build_exp2_polynomial)); - - res = LLVMBuildMul(bld->builder, expipart, expfpart, ""); - } - - if(p_exp2_int_part) - *p_exp2_int_part = expipart; - - if(p_frac_part) - *p_frac_part = fpart; - - if(p_exp2) - *p_exp2 = res; -} - - -LLVMValueRef -lp_build_exp2(struct lp_build_context *bld, - LLVMValueRef x) -{ - LLVMValueRef res; - lp_build_exp2_approx(bld, x, NULL, NULL, &res); - return res; -} - - -/** - * Minimax polynomial fit of log2(x)/(x - 1), for x in range [1, 2[ - * These coefficients can be generate with - * http://www.boost.org/doc/libs/1_36_0/libs/math/doc/sf_and_dist/html/math_toolkit/toolkit/internals2/minimax.html - */ -const double lp_build_log2_polynomial[] = { -#if LOG_POLY_DEGREE == 6 - 3.11578814719469302614, -3.32419399085241980044, 2.59883907202499966007, -1.23152682416275988241, 0.318212422185251071475, -0.0344359067839062357313 -#elif LOG_POLY_DEGREE == 5 - 2.8882704548164776201, -2.52074962577807006663, 1.48116647521213171641, -0.465725644288844778798, 0.0596515482674574969533 -#elif LOG_POLY_DEGREE == 4 - 2.61761038894603480148, -1.75647175389045657003, 0.688243882994381274313, -0.107254423828329604454 -#elif LOG_POLY_DEGREE == 3 - 2.28330284476918490682, -1.04913055217340124191, 0.204446009836232697516 -#else -#error -#endif -}; - - -/** - * See http://www.devmaster.net/forums/showthread.php?p=43580 - */ -void -lp_build_log2_approx(struct lp_build_context *bld, - LLVMValueRef x, - LLVMValueRef *p_exp, - LLVMValueRef *p_floor_log2, - LLVMValueRef *p_log2) -{ - const struct lp_type type = bld->type; - LLVMTypeRef vec_type = lp_build_vec_type(type); - LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); - - LLVMValueRef expmask = lp_build_int_const_scalar(type, 0x7f800000); - LLVMValueRef mantmask = lp_build_int_const_scalar(type, 0x007fffff); - LLVMValueRef one = LLVMConstBitCast(bld->one, int_vec_type); - - LLVMValueRef i = NULL; - LLVMValueRef exp = NULL; - LLVMValueRef mant = NULL; - LLVMValueRef logexp = NULL; - LLVMValueRef logmant = NULL; - LLVMValueRef res = NULL; - - if(p_exp || p_floor_log2 || p_log2) { - /* TODO: optimize the constant case */ - if(LLVMIsConstant(x)) - debug_printf("%s: inefficient/imprecise constant arithmetic\n", - __FUNCTION__); - - assert(type.floating && type.width == 32); - - i = LLVMBuildBitCast(bld->builder, x, int_vec_type, ""); - - /* exp = (float) exponent(x) */ - exp = LLVMBuildAnd(bld->builder, i, expmask, ""); - } - - if(p_floor_log2 || p_log2) { - logexp = LLVMBuildLShr(bld->builder, exp, lp_build_int_const_scalar(type, 23), ""); - logexp = LLVMBuildSub(bld->builder, logexp, lp_build_int_const_scalar(type, 127), ""); - logexp = LLVMBuildSIToFP(bld->builder, logexp, vec_type, ""); - } - - if(p_log2) { - /* mant = (float) mantissa(x) */ - mant = LLVMBuildAnd(bld->builder, i, mantmask, ""); - mant = LLVMBuildOr(bld->builder, mant, one, ""); - mant = LLVMBuildBitCast(bld->builder, mant, vec_type, ""); - - logmant = lp_build_polynomial(bld, mant, lp_build_log2_polynomial, - Elements(lp_build_log2_polynomial)); - - /* This effectively increases the polynomial degree by one, but ensures that log2(1) == 0*/ - logmant = LLVMBuildMul(bld->builder, logmant, LLVMBuildSub(bld->builder, mant, bld->one, ""), ""); - - res = LLVMBuildAdd(bld->builder, logmant, logexp, ""); - } - - if(p_exp) - *p_exp = exp; - - if(p_floor_log2) - *p_floor_log2 = logexp; - - if(p_log2) - *p_log2 = res; -} - - -LLVMValueRef -lp_build_log2(struct lp_build_context *bld, - LLVMValueRef x) -{ - LLVMValueRef res; - lp_build_log2_approx(bld, x, NULL, NULL, &res); - return res; -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_arit.h b/src/gallium/drivers/llvmpipe/lp_bld_arit.h deleted file mode 100644 index 62be4b9aee..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_arit.h +++ /dev/null @@ -1,203 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Helper arithmetic functions. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#ifndef LP_BLD_ARIT_H -#define LP_BLD_ARIT_H - - -#include <llvm-c/Core.h> - - -struct lp_type; -struct lp_build_context; - - -/** - * Complement, i.e., 1 - a. - */ -LLVMValueRef -lp_build_comp(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_add(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b); - -LLVMValueRef -lp_build_sub(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b); - -LLVMValueRef -lp_build_mul(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b); - -LLVMValueRef -lp_build_mul_imm(struct lp_build_context *bld, - LLVMValueRef a, - int b); - -LLVMValueRef -lp_build_div(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b); - -LLVMValueRef -lp_build_lerp(struct lp_build_context *bld, - LLVMValueRef x, - LLVMValueRef v0, - LLVMValueRef v1); - -/** - * Bilinear interpolation. - * - * Values indices are in v_{yx}. - */ -LLVMValueRef -lp_build_lerp_2d(struct lp_build_context *bld, - LLVMValueRef x, - LLVMValueRef y, - LLVMValueRef v00, - LLVMValueRef v01, - LLVMValueRef v10, - LLVMValueRef v11); - -LLVMValueRef -lp_build_min(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b); - -LLVMValueRef -lp_build_max(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b); - -LLVMValueRef -lp_build_abs(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_sgn(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_round(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_floor(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_ceil(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_trunc(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_ifloor(struct lp_build_context *bld, - LLVMValueRef a); -LLVMValueRef -lp_build_iceil(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_iround(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_itrunc(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_sqrt(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_rcp(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_rsqrt(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_cos(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_sin(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_pow(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b); - -LLVMValueRef -lp_build_exp(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_log(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_exp2(struct lp_build_context *bld, - LLVMValueRef a); - -LLVMValueRef -lp_build_log2(struct lp_build_context *bld, - LLVMValueRef a); - -void -lp_build_exp2_approx(struct lp_build_context *bld, - LLVMValueRef x, - LLVMValueRef *p_exp2_int_part, - LLVMValueRef *p_frac_part, - LLVMValueRef *p_exp2); - -void -lp_build_log2_approx(struct lp_build_context *bld, - LLVMValueRef x, - LLVMValueRef *p_exp, - LLVMValueRef *p_floor_log2, - LLVMValueRef *p_log2); - -#endif /* !LP_BLD_ARIT_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_bld_blend.h b/src/gallium/drivers/llvmpipe/lp_bld_blend.h deleted file mode 100644 index da272e549f..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_blend.h +++ /dev/null @@ -1,107 +0,0 @@ -/************************************************************************** - * - * 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 LP_BLD_BLEND_H -#define LP_BLD_BLEND_H - - -/** - * @file - * LLVM IR building helpers interfaces. - * - * We use LLVM-C bindings for now. They are not documented, but follow the C++ - * interfaces very closely, and appear to be complete enough for code - * genration. See - * http://npcontemplation.blogspot.com/2008/06/secret-of-llvm-c-bindings.html - * for a standalone example. - */ - -#include <llvm-c/Core.h> - -#include "pipe/p_format.h" - - -struct pipe_blend_state; -struct lp_type; -struct lp_build_context; - - -/** - * Whether the blending function is commutative or not. - */ -boolean -lp_build_blend_func_commutative(unsigned func); - - -/** - * Whether the blending functions are the reverse of each other. - */ -boolean -lp_build_blend_func_reverse(unsigned rgb_func, unsigned alpha_func); - - -LLVMValueRef -lp_build_blend_func(struct lp_build_context *bld, - unsigned func, - LLVMValueRef term1, - LLVMValueRef term2); - - -LLVMValueRef -lp_build_blend_aos(LLVMBuilderRef builder, - const struct pipe_blend_state *blend, - struct lp_type type, - LLVMValueRef src, - LLVMValueRef dst, - LLVMValueRef const_, - unsigned alpha_swizzle); - - -void -lp_build_blend_soa(LLVMBuilderRef builder, - const struct pipe_blend_state *blend, - struct lp_type type, - LLVMValueRef src[4], - LLVMValueRef dst[4], - LLVMValueRef const_[4], - LLVMValueRef res[4]); - - -/** - * Apply a logic op. - * - * src/dst parameters are packed values. It should work regardless the inputs - * are scalars, or a vector. - */ -LLVMValueRef -lp_build_logicop(LLVMBuilderRef builder, - unsigned logicop_func, - LLVMValueRef src, - LLVMValueRef dst); - - -#endif /* !LP_BLD_BLEND_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c b/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c deleted file mode 100644 index ced7b9c11d..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_blend_aos.c +++ /dev/null @@ -1,356 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -/** - * @file - * Blend LLVM IR generation -- AoS layout. - * - * AoS blending is in general much slower than SoA, but there are some cases - * where it might be faster. In particular, if a pixel is rendered only once - * then the overhead of tiling and untiling will dominate over the speedup that - * SoA gives. So we might want to detect such cases and fallback to AoS in the - * future, but for now this function is here for historical/benchmarking - * purposes. - * - * Run lp_blend_test after any change to this file. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#include "pipe/p_state.h" - -#include "lp_bld_type.h" -#include "lp_bld_const.h" -#include "lp_bld_arit.h" -#include "lp_bld_logic.h" -#include "lp_bld_swizzle.h" -#include "lp_bld_blend.h" -#include "lp_bld_debug.h" - - -/** - * We may the same values several times, so we keep them here to avoid - * recomputing them. Also reusing the values allows us to do simplifications - * that LLVM optimization passes wouldn't normally be able to do. - */ -struct lp_build_blend_aos_context -{ - struct lp_build_context base; - - LLVMValueRef src; - LLVMValueRef dst; - LLVMValueRef const_; - - LLVMValueRef inv_src; - LLVMValueRef inv_dst; - LLVMValueRef inv_const; - LLVMValueRef saturate; - - LLVMValueRef rgb_src_factor; - LLVMValueRef alpha_src_factor; - LLVMValueRef rgb_dst_factor; - LLVMValueRef alpha_dst_factor; -}; - - -static LLVMValueRef -lp_build_blend_factor_unswizzled(struct lp_build_blend_aos_context *bld, - unsigned factor, - boolean alpha) -{ - switch (factor) { - case PIPE_BLENDFACTOR_ZERO: - return bld->base.zero; - case PIPE_BLENDFACTOR_ONE: - return bld->base.one; - case PIPE_BLENDFACTOR_SRC_COLOR: - case PIPE_BLENDFACTOR_SRC_ALPHA: - return bld->src; - case PIPE_BLENDFACTOR_DST_COLOR: - case PIPE_BLENDFACTOR_DST_ALPHA: - return bld->dst; - case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: - if(alpha) - return bld->base.one; - else { - if(!bld->inv_dst) - bld->inv_dst = lp_build_comp(&bld->base, bld->dst); - if(!bld->saturate) - bld->saturate = lp_build_min(&bld->base, bld->src, bld->inv_dst); - return bld->saturate; - } - case PIPE_BLENDFACTOR_CONST_COLOR: - case PIPE_BLENDFACTOR_CONST_ALPHA: - return bld->const_; - case PIPE_BLENDFACTOR_SRC1_COLOR: - case PIPE_BLENDFACTOR_SRC1_ALPHA: - /* TODO */ - assert(0); - return bld->base.zero; - case PIPE_BLENDFACTOR_INV_SRC_COLOR: - case PIPE_BLENDFACTOR_INV_SRC_ALPHA: - if(!bld->inv_src) - bld->inv_src = lp_build_comp(&bld->base, bld->src); - return bld->inv_src; - case PIPE_BLENDFACTOR_INV_DST_COLOR: - case PIPE_BLENDFACTOR_INV_DST_ALPHA: - if(!bld->inv_dst) - bld->inv_dst = lp_build_comp(&bld->base, bld->dst); - return bld->inv_dst; - case PIPE_BLENDFACTOR_INV_CONST_COLOR: - case PIPE_BLENDFACTOR_INV_CONST_ALPHA: - if(!bld->inv_const) - bld->inv_const = lp_build_comp(&bld->base, bld->const_); - return bld->inv_const; - case PIPE_BLENDFACTOR_INV_SRC1_COLOR: - case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: - /* TODO */ - assert(0); - return bld->base.zero; - default: - assert(0); - return bld->base.zero; - } -} - - -enum lp_build_blend_swizzle { - LP_BUILD_BLEND_SWIZZLE_RGBA = 0, - LP_BUILD_BLEND_SWIZZLE_AAAA = 1 -}; - - -/** - * How should we shuffle the base factor. - */ -static enum lp_build_blend_swizzle -lp_build_blend_factor_swizzle(unsigned factor) -{ - switch (factor) { - case PIPE_BLENDFACTOR_ONE: - case PIPE_BLENDFACTOR_ZERO: - case PIPE_BLENDFACTOR_SRC_COLOR: - case PIPE_BLENDFACTOR_DST_COLOR: - case PIPE_BLENDFACTOR_CONST_COLOR: - case PIPE_BLENDFACTOR_SRC1_COLOR: - case PIPE_BLENDFACTOR_INV_SRC_COLOR: - case PIPE_BLENDFACTOR_INV_DST_COLOR: - case PIPE_BLENDFACTOR_INV_CONST_COLOR: - case PIPE_BLENDFACTOR_INV_SRC1_COLOR: - return LP_BUILD_BLEND_SWIZZLE_RGBA; - case PIPE_BLENDFACTOR_SRC_ALPHA: - case PIPE_BLENDFACTOR_DST_ALPHA: - case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: - case PIPE_BLENDFACTOR_SRC1_ALPHA: - case PIPE_BLENDFACTOR_CONST_ALPHA: - case PIPE_BLENDFACTOR_INV_SRC_ALPHA: - case PIPE_BLENDFACTOR_INV_DST_ALPHA: - case PIPE_BLENDFACTOR_INV_CONST_ALPHA: - case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: - return LP_BUILD_BLEND_SWIZZLE_AAAA; - default: - assert(0); - return LP_BUILD_BLEND_SWIZZLE_RGBA; - } -} - - -static LLVMValueRef -lp_build_blend_swizzle(struct lp_build_blend_aos_context *bld, - LLVMValueRef rgb, - LLVMValueRef alpha, - enum lp_build_blend_swizzle rgb_swizzle, - unsigned alpha_swizzle) -{ - if(rgb == alpha) { - if(rgb_swizzle == LP_BUILD_BLEND_SWIZZLE_RGBA) - return rgb; - if(rgb_swizzle == LP_BUILD_BLEND_SWIZZLE_AAAA) - return lp_build_broadcast_aos(&bld->base, rgb, alpha_swizzle); - } - else { - if(rgb_swizzle == LP_BUILD_BLEND_SWIZZLE_RGBA) { - boolean cond[4] = {0, 0, 0, 0}; - cond[alpha_swizzle] = 1; - return lp_build_select_aos(&bld->base, alpha, rgb, cond); - } - if(rgb_swizzle == LP_BUILD_BLEND_SWIZZLE_AAAA) { - unsigned char swizzle[4]; - swizzle[0] = alpha_swizzle; - swizzle[1] = alpha_swizzle; - swizzle[2] = alpha_swizzle; - swizzle[3] = alpha_swizzle; - swizzle[alpha_swizzle] += 4; - return lp_build_swizzle2_aos(&bld->base, rgb, alpha, swizzle); - } - } - assert(0); - return bld->base.undef; -} - - -/** - * @sa http://www.opengl.org/sdk/docs/man/xhtml/glBlendFuncSeparate.xml - */ -static LLVMValueRef -lp_build_blend_factor(struct lp_build_blend_aos_context *bld, - LLVMValueRef factor1, - unsigned rgb_factor, - unsigned alpha_factor, - unsigned alpha_swizzle) -{ - LLVMValueRef rgb_factor_; - LLVMValueRef alpha_factor_; - LLVMValueRef factor2; - enum lp_build_blend_swizzle rgb_swizzle; - - rgb_factor_ = lp_build_blend_factor_unswizzled(bld, rgb_factor, FALSE); - alpha_factor_ = lp_build_blend_factor_unswizzled(bld, alpha_factor, TRUE); - - rgb_swizzle = lp_build_blend_factor_swizzle(rgb_factor); - - factor2 = lp_build_blend_swizzle(bld, rgb_factor_, alpha_factor_, rgb_swizzle, alpha_swizzle); - - return lp_build_mul(&bld->base, factor1, factor2); -} - - -boolean -lp_build_blend_func_commutative(unsigned func) -{ - switch (func) { - case PIPE_BLEND_ADD: - case PIPE_BLEND_MIN: - case PIPE_BLEND_MAX: - return TRUE; - case PIPE_BLEND_SUBTRACT: - case PIPE_BLEND_REVERSE_SUBTRACT: - return FALSE; - default: - assert(0); - return TRUE; - } -} - - -boolean -lp_build_blend_func_reverse(unsigned rgb_func, unsigned alpha_func) -{ - if(rgb_func == alpha_func) - return FALSE; - if(rgb_func == PIPE_BLEND_SUBTRACT && alpha_func == PIPE_BLEND_REVERSE_SUBTRACT) - return TRUE; - if(rgb_func == PIPE_BLEND_REVERSE_SUBTRACT && alpha_func == PIPE_BLEND_SUBTRACT) - return TRUE; - return FALSE; -} - - -/** - * @sa http://www.opengl.org/sdk/docs/man/xhtml/glBlendEquationSeparate.xml - */ -LLVMValueRef -lp_build_blend_func(struct lp_build_context *bld, - unsigned func, - LLVMValueRef term1, - LLVMValueRef term2) -{ - switch (func) { - case PIPE_BLEND_ADD: - return lp_build_add(bld, term1, term2); - break; - case PIPE_BLEND_SUBTRACT: - return lp_build_sub(bld, term1, term2); - case PIPE_BLEND_REVERSE_SUBTRACT: - return lp_build_sub(bld, term2, term1); - case PIPE_BLEND_MIN: - return lp_build_min(bld, term1, term2); - case PIPE_BLEND_MAX: - return lp_build_max(bld, term1, term2); - default: - assert(0); - return bld->zero; - } -} - - -LLVMValueRef -lp_build_blend_aos(LLVMBuilderRef builder, - const struct pipe_blend_state *blend, - struct lp_type type, - LLVMValueRef src, - LLVMValueRef dst, - LLVMValueRef const_, - unsigned alpha_swizzle) -{ - struct lp_build_blend_aos_context bld; - LLVMValueRef src_term; - LLVMValueRef dst_term; - - /* FIXME */ - assert(blend->colormask == 0xf); - - if(!blend->blend_enable) - return src; - - /* It makes no sense to blend unless values are normalized */ - assert(type.norm); - - /* Setup build context */ - memset(&bld, 0, sizeof bld); - lp_build_context_init(&bld.base, builder, type); - bld.src = src; - bld.dst = dst; - bld.const_ = const_; - - /* TODO: There are still a few optimization opportunities here. For certain - * combinations it is possible to reorder the operations and therefore saving - * some instructions. */ - - src_term = lp_build_blend_factor(&bld, src, blend->rgb_src_factor, blend->alpha_src_factor, alpha_swizzle); - dst_term = lp_build_blend_factor(&bld, dst, blend->rgb_dst_factor, blend->alpha_dst_factor, alpha_swizzle); - - lp_build_name(src_term, "src_term"); - lp_build_name(dst_term, "dst_term"); - - if(blend->rgb_func == blend->alpha_func) { - return lp_build_blend_func(&bld.base, blend->rgb_func, src_term, dst_term); - } - else { - /* Seperate RGB / A functions */ - - LLVMValueRef rgb; - LLVMValueRef alpha; - - rgb = lp_build_blend_func(&bld.base, blend->rgb_func, src_term, dst_term); - alpha = lp_build_blend_func(&bld.base, blend->alpha_func, src_term, dst_term); - - return lp_build_blend_swizzle(&bld, rgb, alpha, LP_BUILD_BLEND_SWIZZLE_RGBA, alpha_swizzle); - } -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_blend_logicop.c b/src/gallium/drivers/llvmpipe/lp_bld_blend_logicop.c deleted file mode 100644 index 88321f62a2..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_blend_logicop.c +++ /dev/null @@ -1,108 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -/** - * @file - * Blend LLVM IR generation -- logic ops. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#include "pipe/p_state.h" - -#include "lp_bld_blend.h" - - -LLVMValueRef -lp_build_logicop(LLVMBuilderRef builder, - unsigned logicop_func, - LLVMValueRef src, - LLVMValueRef dst) -{ - LLVMTypeRef type; - LLVMValueRef res; - - type = LLVMTypeOf(src); - - switch (logicop_func) { - case PIPE_LOGICOP_CLEAR: - res = LLVMConstNull(type); - break; - case PIPE_LOGICOP_NOR: - res = LLVMBuildNot(builder, LLVMBuildOr(builder, src, dst, ""), ""); - break; - case PIPE_LOGICOP_AND_INVERTED: - res = LLVMBuildAnd(builder, LLVMBuildNot(builder, src, ""), dst, ""); - break; - case PIPE_LOGICOP_COPY_INVERTED: - res = LLVMBuildNot(builder, src, ""); - break; - case PIPE_LOGICOP_AND_REVERSE: - res = LLVMBuildAnd(builder, src, LLVMBuildNot(builder, dst, ""), ""); - break; - case PIPE_LOGICOP_INVERT: - res = LLVMBuildNot(builder, dst, ""); - break; - case PIPE_LOGICOP_XOR: - res = LLVMBuildXor(builder, src, dst, ""); - break; - case PIPE_LOGICOP_NAND: - res = LLVMBuildNot(builder, LLVMBuildAnd(builder, src, dst, ""), ""); - break; - case PIPE_LOGICOP_AND: - res = LLVMBuildAnd(builder, src, dst, ""); - break; - case PIPE_LOGICOP_EQUIV: - res = LLVMBuildNot(builder, LLVMBuildXor(builder, src, dst, ""), ""); - break; - case PIPE_LOGICOP_NOOP: - res = dst; - break; - case PIPE_LOGICOP_OR_INVERTED: - res = LLVMBuildOr(builder, LLVMBuildNot(builder, src, ""), dst, ""); - break; - case PIPE_LOGICOP_COPY: - res = src; - break; - case PIPE_LOGICOP_OR_REVERSE: - res = LLVMBuildOr(builder, src, LLVMBuildNot(builder, dst, ""), ""); - break; - case PIPE_LOGICOP_OR: - res = LLVMBuildOr(builder, src, dst, ""); - break; - case PIPE_LOGICOP_SET: - res = LLVMConstAllOnes(type); - break; - default: - assert(0); - res = src; - } - - return res; -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_blend_soa.c b/src/gallium/drivers/llvmpipe/lp_bld_blend_soa.c deleted file mode 100644 index 9511299d55..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_blend_soa.c +++ /dev/null @@ -1,298 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -/** - * @file - * Blend LLVM IR generation -- SoA layout. - * - * Blending in SoA is much faster than AoS, especially when separate rgb/alpha - * factors/functions are used, since no channel masking/shuffling is necessary - * and we can achieve the full throughput of the SIMD operations. Furthermore - * the fragment shader output is also in SoA, so it fits nicely with the rest of - * the fragment pipeline. - * - * The drawback is that to be displayed the color buffer needs to be in AoS - * layout, so we need to tile/untile the color buffer before/after rendering. - * A color buffer like - * - * R11 G11 B11 A11 R12 G12 B12 A12 R13 G13 B13 A13 R14 G14 B14 A14 ... - * R21 G21 B21 A21 R22 G22 B22 A22 R23 G23 B23 A23 R24 G24 B24 A24 ... - * - * R31 G31 B31 A31 R32 G32 B32 A32 R33 G33 B33 A33 R34 G34 B34 A34 ... - * R41 G41 B41 A41 R42 G42 B42 A42 R43 G43 B43 A43 R44 G44 B44 A44 ... - * - * ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... - * - * will actually be stored in memory as - * - * R11 R12 R21 R22 R13 R14 R23 R24 ... G11 G12 G21 G22 G13 G14 G23 G24 ... B11 B12 B21 B22 B13 B14 B23 B24 ... A11 A12 A21 A22 A13 A14 A23 A24 ... - * R31 R32 R41 R42 R33 R34 R43 R44 ... G31 G32 G41 G42 G33 G34 G43 G44 ... B31 B32 B41 B42 B33 B34 B43 B44 ... A31 A32 A41 A42 A33 A34 A43 A44 ... - * ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... - * - * NOTE: Run lp_blend_test after any change to this file. - * - * You can also run lp_blend_test to obtain AoS vs SoA benchmarks. Invoking it - * as: - * - * lp_blend_test -o blend.tsv - * - * will generate a tab-seperated-file with the test results and performance - * measurements. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#include "pipe/p_state.h" - -#include "lp_bld_type.h" -#include "lp_bld_const.h" -#include "lp_bld_arit.h" -#include "lp_bld_blend.h" - - -/** - * We may the same values several times, so we keep them here to avoid - * recomputing them. Also reusing the values allows us to do simplifications - * that LLVM optimization passes wouldn't normally be able to do. - */ -struct lp_build_blend_soa_context -{ - struct lp_build_context base; - - LLVMValueRef src[4]; - LLVMValueRef dst[4]; - LLVMValueRef con[4]; - - LLVMValueRef inv_src[4]; - LLVMValueRef inv_dst[4]; - LLVMValueRef inv_con[4]; - - LLVMValueRef src_alpha_saturate; - - /** - * We store all factors in a table in order to eliminate redundant - * multiplications later. - */ - LLVMValueRef factor[2][2][4]; - - /** - * Table with all terms. - */ - LLVMValueRef term[2][4]; -}; - - -static LLVMValueRef -lp_build_blend_soa_factor(struct lp_build_blend_soa_context *bld, - unsigned factor, unsigned i) -{ - /* - * Compute src/first term RGB - */ - switch (factor) { - case PIPE_BLENDFACTOR_ONE: - return bld->base.one; - case PIPE_BLENDFACTOR_SRC_COLOR: - return bld->src[i]; - case PIPE_BLENDFACTOR_SRC_ALPHA: - return bld->src[3]; - case PIPE_BLENDFACTOR_DST_COLOR: - return bld->dst[i]; - case PIPE_BLENDFACTOR_DST_ALPHA: - return bld->dst[3]; - case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: - if(i == 3) - return bld->base.one; - else { - if(!bld->inv_dst[3]) - bld->inv_dst[3] = lp_build_comp(&bld->base, bld->dst[3]); - if(!bld->src_alpha_saturate) - bld->src_alpha_saturate = lp_build_min(&bld->base, bld->src[3], bld->inv_dst[3]); - return bld->src_alpha_saturate; - } - case PIPE_BLENDFACTOR_CONST_COLOR: - return bld->con[i]; - case PIPE_BLENDFACTOR_CONST_ALPHA: - return bld->con[3]; - case PIPE_BLENDFACTOR_SRC1_COLOR: - /* TODO */ - assert(0); - return bld->base.zero; - case PIPE_BLENDFACTOR_SRC1_ALPHA: - /* TODO */ - assert(0); - return bld->base.zero; - case PIPE_BLENDFACTOR_ZERO: - return bld->base.zero; - case PIPE_BLENDFACTOR_INV_SRC_COLOR: - if(!bld->inv_src[i]) - bld->inv_src[i] = lp_build_comp(&bld->base, bld->src[i]); - return bld->inv_src[i]; - case PIPE_BLENDFACTOR_INV_SRC_ALPHA: - if(!bld->inv_src[3]) - bld->inv_src[3] = lp_build_comp(&bld->base, bld->src[3]); - return bld->inv_src[3]; - case PIPE_BLENDFACTOR_INV_DST_COLOR: - if(!bld->inv_dst[i]) - bld->inv_dst[i] = lp_build_comp(&bld->base, bld->dst[i]); - return bld->inv_dst[i]; - case PIPE_BLENDFACTOR_INV_DST_ALPHA: - if(!bld->inv_dst[3]) - bld->inv_dst[3] = lp_build_comp(&bld->base, bld->dst[3]); - return bld->inv_dst[3]; - case PIPE_BLENDFACTOR_INV_CONST_COLOR: - if(!bld->inv_con[i]) - bld->inv_con[i] = lp_build_comp(&bld->base, bld->con[i]); - return bld->inv_con[i]; - case PIPE_BLENDFACTOR_INV_CONST_ALPHA: - if(!bld->inv_con[3]) - bld->inv_con[3] = lp_build_comp(&bld->base, bld->con[3]); - return bld->inv_con[3]; - case PIPE_BLENDFACTOR_INV_SRC1_COLOR: - /* TODO */ - assert(0); - return bld->base.zero; - case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: - /* TODO */ - assert(0); - return bld->base.zero; - default: - assert(0); - return bld->base.zero; - } -} - - -/** - * Generate blend code in SOA mode. - * \param src src/fragment color - * \param dst dst/framebuffer color - * \param con constant blend color - * \param res the result/output - */ -void -lp_build_blend_soa(LLVMBuilderRef builder, - const struct pipe_blend_state *blend, - struct lp_type type, - LLVMValueRef src[4], - LLVMValueRef dst[4], - LLVMValueRef con[4], - LLVMValueRef res[4]) -{ - struct lp_build_blend_soa_context bld; - unsigned i, j, k; - - /* Setup build context */ - memset(&bld, 0, sizeof bld); - lp_build_context_init(&bld.base, builder, type); - for (i = 0; i < 4; ++i) { - bld.src[i] = src[i]; - bld.dst[i] = dst[i]; - bld.con[i] = con[i]; - } - - for (i = 0; i < 4; ++i) { - if (blend->colormask & (1 << i)) { - if (blend->logicop_enable) { - if(!type.floating) { - res[i] = lp_build_logicop(builder, blend->logicop_func, src[i], dst[i]); - } - else - res[i] = dst[i]; - } - else if (blend->blend_enable) { - unsigned src_factor = i < 3 ? blend->rgb_src_factor : blend->alpha_src_factor; - unsigned dst_factor = i < 3 ? blend->rgb_dst_factor : blend->alpha_dst_factor; - unsigned func = i < 3 ? blend->rgb_func : blend->alpha_func; - boolean func_commutative = lp_build_blend_func_commutative(func); - - /* It makes no sense to blend unless values are normalized */ - assert(type.norm); - - /* - * Compute src/dst factors. - */ - - bld.factor[0][0][i] = src[i]; - bld.factor[0][1][i] = lp_build_blend_soa_factor(&bld, src_factor, i); - bld.factor[1][0][i] = dst[i]; - bld.factor[1][1][i] = lp_build_blend_soa_factor(&bld, dst_factor, i); - - /* - * Compute src/dst terms - */ - - for(k = 0; k < 2; ++k) { - /* See if this multiplication has been previously computed */ - for(j = 0; j < i; ++j) { - if((bld.factor[k][0][j] == bld.factor[k][0][i] && - bld.factor[k][1][j] == bld.factor[k][1][i]) || - (bld.factor[k][0][j] == bld.factor[k][1][i] && - bld.factor[k][1][j] == bld.factor[k][0][i])) - break; - } - - if(j < i) - bld.term[k][i] = bld.term[k][j]; - else - bld.term[k][i] = lp_build_mul(&bld.base, bld.factor[k][0][i], bld.factor[k][1][i]); - } - - /* - * Combine terms - */ - - /* See if this function has been previously applied */ - for(j = 0; j < i; ++j) { - unsigned prev_func = j < 3 ? blend->rgb_func : blend->alpha_func; - unsigned func_reverse = lp_build_blend_func_reverse(func, prev_func); - - if((!func_reverse && - bld.term[0][j] == bld.term[0][i] && - bld.term[1][j] == bld.term[1][i]) || - ((func_commutative || func_reverse) && - bld.term[0][j] == bld.term[1][i] && - bld.term[1][j] == bld.term[0][i])) - break; - } - - if(j < i) - res[i] = res[j]; - else - res[i] = lp_build_blend_func(&bld.base, func, bld.term[0][i], bld.term[1][i]); - } - else { - res[i] = src[i]; - } - } - else { - res[i] = dst[i]; - } - } -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_const.c b/src/gallium/drivers/llvmpipe/lp_bld_const.c deleted file mode 100644 index c8eaa8c394..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_const.c +++ /dev/null @@ -1,369 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -/** - * @file - * Helper functions for constant building. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - -#include <float.h> - -#include "util/u_debug.h" - -#include "lp_bld_type.h" -#include "lp_bld_const.h" - - -unsigned -lp_mantissa(struct lp_type type) -{ - assert(type.floating); - - if(type.floating) { - switch(type.width) { - case 32: - return 23; - case 64: - return 53; - default: - assert(0); - return 0; - } - } - else { - if(type.sign) - return type.width - 1; - else - return type.width; - } -} - - -/** - * Shift of the unity. - * - * Same as lp_const_scale(), but in terms of shifts. - */ -unsigned -lp_const_shift(struct lp_type type) -{ - if(type.floating) - return 0; - else if(type.fixed) - return type.width/2; - else if(type.norm) - return type.sign ? type.width - 1 : type.width; - else - return 0; -} - - -unsigned -lp_const_offset(struct lp_type type) -{ - if(type.floating || type.fixed) - return 0; - else if(type.norm) - return 1; - else - return 0; -} - - -/** - * Scaling factor between the LLVM native value and its interpretation. - * - * This is 1.0 for all floating types and unnormalized integers, and something - * else for the fixed points types and normalized integers. - */ -double -lp_const_scale(struct lp_type type) -{ - unsigned long long llscale; - double dscale; - - llscale = (unsigned long long)1 << lp_const_shift(type); - llscale -= lp_const_offset(type); - dscale = (double)llscale; - assert((unsigned long long)dscale == llscale); - - return dscale; -} - - -/** - * Minimum value representable by the type. - */ -double -lp_const_min(struct lp_type type) -{ - unsigned bits; - - if(!type.sign) - return 0.0; - - if(type.norm) - return -1.0; - - if (type.floating) { - switch(type.width) { - case 32: - return -FLT_MAX; - case 64: - return -DBL_MAX; - default: - assert(0); - return 0.0; - } - } - - if(type.fixed) - /* FIXME: consider the fractional bits? */ - bits = type.width / 2 - 1; - else - bits = type.width - 1; - - return (double)-((long long)1 << bits); -} - - -/** - * Maximum value representable by the type. - */ -double -lp_const_max(struct lp_type type) -{ - unsigned bits; - - if(type.norm) - return 1.0; - - if (type.floating) { - switch(type.width) { - case 32: - return FLT_MAX; - case 64: - return DBL_MAX; - default: - assert(0); - return 0.0; - } - } - - if(type.fixed) - bits = type.width / 2; - else - bits = type.width; - - if(type.sign) - bits -= 1; - - return (double)(((unsigned long long)1 << bits) - 1); -} - - -double -lp_const_eps(struct lp_type type) -{ - if (type.floating) { - switch(type.width) { - case 32: - return FLT_EPSILON; - case 64: - return DBL_EPSILON; - default: - assert(0); - return 0.0; - } - } - else { - double scale = lp_const_scale(type); - return 1.0/scale; - } -} - - -LLVMValueRef -lp_build_undef(struct lp_type type) -{ - LLVMTypeRef vec_type = lp_build_vec_type(type); - return LLVMGetUndef(vec_type); -} - - -LLVMValueRef -lp_build_zero(struct lp_type type) -{ - LLVMTypeRef vec_type = lp_build_vec_type(type); - return LLVMConstNull(vec_type); -} - - -LLVMValueRef -lp_build_one(struct lp_type type) -{ - LLVMTypeRef elem_type; - LLVMValueRef elems[LP_MAX_VECTOR_LENGTH]; - unsigned i; - - assert(type.length <= LP_MAX_VECTOR_LENGTH); - - elem_type = lp_build_elem_type(type); - - if(type.floating) - elems[0] = LLVMConstReal(elem_type, 1.0); - else if(type.fixed) - elems[0] = LLVMConstInt(elem_type, 1LL << (type.width/2), 0); - else if(!type.norm) - elems[0] = LLVMConstInt(elem_type, 1, 0); - else if(type.sign) - elems[0] = LLVMConstInt(elem_type, (1LL << (type.width - 1)) - 1, 0); - else { - /* special case' -- 1.0 for normalized types is more easily attained if - * we start with a vector consisting of all bits set */ - LLVMTypeRef vec_type = LLVMVectorType(elem_type, type.length); - LLVMValueRef vec = LLVMConstAllOnes(vec_type); - -#if 0 - if(type.sign) - /* TODO: Unfortunately this caused "Tried to create a shift operation - * on a non-integer type!" */ - vec = LLVMConstLShr(vec, lp_build_int_const_scalar(type, 1)); -#endif - - return vec; - } - - for(i = 1; i < type.length; ++i) - elems[i] = elems[0]; - - return LLVMConstVector(elems, type.length); -} - - -LLVMValueRef -lp_build_const_scalar(struct lp_type type, - double val) -{ - LLVMTypeRef elem_type = lp_build_elem_type(type); - LLVMValueRef elems[LP_MAX_VECTOR_LENGTH]; - unsigned i; - - assert(type.length <= LP_MAX_VECTOR_LENGTH); - - if(type.floating) { - elems[0] = LLVMConstReal(elem_type, val); - } - else { - double dscale = lp_const_scale(type); - - elems[0] = LLVMConstInt(elem_type, val*dscale + 0.5, 0); - } - - for(i = 1; i < type.length; ++i) - elems[i] = elems[0]; - - return LLVMConstVector(elems, type.length); -} - - -LLVMValueRef -lp_build_int_const_scalar(struct lp_type type, - long long val) -{ - LLVMTypeRef elem_type = lp_build_int_elem_type(type); - LLVMValueRef elems[LP_MAX_VECTOR_LENGTH]; - unsigned i; - - assert(type.length <= LP_MAX_VECTOR_LENGTH); - - for(i = 0; i < type.length; ++i) - elems[i] = LLVMConstInt(elem_type, val, type.sign ? 1 : 0); - - return LLVMConstVector(elems, type.length); -} - - -LLVMValueRef -lp_build_const_aos(struct lp_type type, - double r, double g, double b, double a, - const unsigned char *swizzle) -{ - const unsigned char default_swizzle[4] = {0, 1, 2, 3}; - LLVMTypeRef elem_type; - LLVMValueRef elems[LP_MAX_VECTOR_LENGTH]; - unsigned i; - - assert(type.length % 4 == 0); - assert(type.length <= LP_MAX_VECTOR_LENGTH); - - elem_type = lp_build_elem_type(type); - - if(swizzle == NULL) - swizzle = default_swizzle; - - if(type.floating) { - elems[swizzle[0]] = LLVMConstReal(elem_type, r); - elems[swizzle[1]] = LLVMConstReal(elem_type, g); - elems[swizzle[2]] = LLVMConstReal(elem_type, b); - elems[swizzle[3]] = LLVMConstReal(elem_type, a); - } - else { - double dscale = lp_const_scale(type); - - elems[swizzle[0]] = LLVMConstInt(elem_type, r*dscale + 0.5, 0); - elems[swizzle[1]] = LLVMConstInt(elem_type, g*dscale + 0.5, 0); - elems[swizzle[2]] = LLVMConstInt(elem_type, b*dscale + 0.5, 0); - elems[swizzle[3]] = LLVMConstInt(elem_type, a*dscale + 0.5, 0); - } - - for(i = 4; i < type.length; ++i) - elems[i] = elems[i % 4]; - - return LLVMConstVector(elems, type.length); -} - - -LLVMValueRef -lp_build_const_mask_aos(struct lp_type type, - const boolean cond[4]) -{ - LLVMTypeRef elem_type = LLVMIntType(type.width); - LLVMValueRef masks[LP_MAX_VECTOR_LENGTH]; - unsigned i, j; - - assert(type.length <= LP_MAX_VECTOR_LENGTH); - - for(j = 0; j < type.length; j += 4) - for(i = 0; i < 4; ++i) - masks[j + i] = LLVMConstInt(elem_type, cond[i] ? ~0 : 0, 0); - - return LLVMConstVector(masks, type.length); -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_const.h b/src/gallium/drivers/llvmpipe/lp_bld_const.h deleted file mode 100644 index cb8e1c7b00..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_const.h +++ /dev/null @@ -1,108 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Helper functions for constant building. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#ifndef LP_BLD_CONST_H -#define LP_BLD_CONST_H - - -#include <llvm-c/Core.h> - -#include <pipe/p_compiler.h> - - -struct lp_type; - - -unsigned -lp_mantissa(struct lp_type type); - - -unsigned -lp_const_shift(struct lp_type type); - - -unsigned -lp_const_offset(struct lp_type type); - - -double -lp_const_scale(struct lp_type type); - -double -lp_const_min(struct lp_type type); - - -double -lp_const_max(struct lp_type type); - - -double -lp_const_eps(struct lp_type type); - - -LLVMValueRef -lp_build_undef(struct lp_type type); - - -LLVMValueRef -lp_build_zero(struct lp_type type); - - -LLVMValueRef -lp_build_one(struct lp_type type); - - -LLVMValueRef -lp_build_const_scalar(struct lp_type type, - double val); - - -LLVMValueRef -lp_build_int_const_scalar(struct lp_type type, - long long val); - - -LLVMValueRef -lp_build_const_aos(struct lp_type type, - double r, double g, double b, double a, - const unsigned char *swizzle); - - -LLVMValueRef -lp_build_const_mask_aos(struct lp_type type, - const boolean cond[4]); - - -#endif /* !LP_BLD_CONST_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_bld_conv.c b/src/gallium/drivers/llvmpipe/lp_bld_conv.c deleted file mode 100644 index 9935209437..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_conv.c +++ /dev/null @@ -1,467 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -/** - * @file - * Helper functions for type conversions. - * - * We want to use the fastest type for a given computation whenever feasible. - * The other side of this is that we need to be able convert between several - * types accurately and efficiently. - * - * Conversion between types of different bit width is quite complex since a - * - * To remember there are a few invariants in type conversions: - * - * - register width must remain constant: - * - * src_type.width * src_type.length == dst_type.width * dst_type.length - * - * - total number of elements must remain constant: - * - * src_type.length * num_srcs == dst_type.length * num_dsts - * - * It is not always possible to do the conversion both accurately and - * efficiently, usually due to lack of adequate machine instructions. In these - * cases it is important not to cut shortcuts here and sacrifice accuracy, as - * there this functions can be used anywhere. In the future we might have a - * precision parameter which can gauge the accuracy vs efficiency compromise, - * but for now if the data conversion between two stages happens to be the - * bottleneck, then most likely should just avoid converting at all and run - * both stages with the same type. - * - * Make sure to run lp_test_conv unit test after any change to this file. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#include "util/u_debug.h" -#include "util/u_math.h" -#include "util/u_cpu_detect.h" - -#include "lp_bld_type.h" -#include "lp_bld_const.h" -#include "lp_bld_intr.h" -#include "lp_bld_arit.h" -#include "lp_bld_pack.h" -#include "lp_bld_conv.h" - - -/** - * Special case for converting clamped IEEE-754 floats to unsigned norms. - * - * The mathematical voodoo below may seem excessive but it is actually - * paramount we do it this way for several reasons. First, there is no single - * precision FP to unsigned integer conversion Intel SSE instruction. Second, - * secondly, even if there was, since the FP's mantissa takes only a fraction - * of register bits the typically scale and cast approach would require double - * precision for accurate results, and therefore half the throughput - * - * Although the result values can be scaled to an arbitrary bit width specified - * by dst_width, the actual result type will have the same width. - */ -LLVMValueRef -lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder, - struct lp_type src_type, - unsigned dst_width, - LLVMValueRef src) -{ - LLVMTypeRef int_vec_type = lp_build_int_vec_type(src_type); - LLVMValueRef res; - unsigned mantissa; - unsigned n; - unsigned long long ubound; - unsigned long long mask; - double scale; - double bias; - - assert(src_type.floating); - - mantissa = lp_mantissa(src_type); - - /* We cannot carry more bits than the mantissa */ - n = MIN2(mantissa, dst_width); - - /* This magic coefficients will make the desired result to appear in the - * lowest significant bits of the mantissa. - */ - ubound = ((unsigned long long)1 << n); - mask = ubound - 1; - scale = (double)mask/ubound; - bias = (double)((unsigned long long)1 << (mantissa - n)); - - res = LLVMBuildMul(builder, src, lp_build_const_scalar(src_type, scale), ""); - res = LLVMBuildAdd(builder, res, lp_build_const_scalar(src_type, bias), ""); - res = LLVMBuildBitCast(builder, res, int_vec_type, ""); - - if(dst_width > n) { - int shift = dst_width - n; - res = LLVMBuildShl(builder, res, lp_build_int_const_scalar(src_type, shift), ""); - - /* TODO: Fill in the empty lower bits for additional precision? */ -#if 0 - { - LLVMValueRef msb; - msb = LLVMBuildLShr(builder, res, lp_build_int_const_scalar(src_type, dst_width - 1), ""); - msb = LLVMBuildShl(builder, msb, lp_build_int_const_scalar(src_type, shift), ""); - msb = LLVMBuildSub(builder, msb, lp_build_int_const_scalar(src_type, 1), ""); - res = LLVMBuildOr(builder, res, msb, ""); - } -#elif 0 - while(shift > 0) { - res = LLVMBuildOr(builder, res, LLVMBuildLShr(builder, res, lp_build_int_const_scalar(src_type, n), ""), ""); - shift -= n; - n *= 2; - } -#endif - } - else - res = LLVMBuildAnd(builder, res, lp_build_int_const_scalar(src_type, mask), ""); - - return res; -} - - -/** - * Inverse of lp_build_clamped_float_to_unsigned_norm above. - */ -LLVMValueRef -lp_build_unsigned_norm_to_float(LLVMBuilderRef builder, - unsigned src_width, - struct lp_type dst_type, - LLVMValueRef src) -{ - LLVMTypeRef vec_type = lp_build_vec_type(dst_type); - LLVMTypeRef int_vec_type = lp_build_int_vec_type(dst_type); - LLVMValueRef bias_; - LLVMValueRef res; - unsigned mantissa; - unsigned n; - unsigned long long ubound; - unsigned long long mask; - double scale; - double bias; - - mantissa = lp_mantissa(dst_type); - - n = MIN2(mantissa, src_width); - - ubound = ((unsigned long long)1 << n); - mask = ubound - 1; - scale = (double)ubound/mask; - bias = (double)((unsigned long long)1 << (mantissa - n)); - - res = src; - - if(src_width > mantissa) { - int shift = src_width - mantissa; - res = LLVMBuildLShr(builder, res, lp_build_int_const_scalar(dst_type, shift), ""); - } - - bias_ = lp_build_const_scalar(dst_type, bias); - - res = LLVMBuildOr(builder, - res, - LLVMBuildBitCast(builder, bias_, int_vec_type, ""), ""); - - res = LLVMBuildBitCast(builder, res, vec_type, ""); - - res = LLVMBuildSub(builder, res, bias_, ""); - res = LLVMBuildMul(builder, res, lp_build_const_scalar(dst_type, scale), ""); - - return res; -} - - -/** - * Generic type conversion. - * - * TODO: Take a precision argument, or even better, add a new precision member - * to the lp_type union. - */ -void -lp_build_conv(LLVMBuilderRef builder, - struct lp_type src_type, - struct lp_type dst_type, - const LLVMValueRef *src, unsigned num_srcs, - LLVMValueRef *dst, unsigned num_dsts) -{ - struct lp_type tmp_type; - LLVMValueRef tmp[LP_MAX_VECTOR_LENGTH]; - unsigned num_tmps; - unsigned i; - - /* Register width must remain constant */ - assert(src_type.width * src_type.length == dst_type.width * dst_type.length); - - /* We must not loose or gain channels. Only precision */ - assert(src_type.length * num_srcs == dst_type.length * num_dsts); - - assert(src_type.length <= LP_MAX_VECTOR_LENGTH); - assert(dst_type.length <= LP_MAX_VECTOR_LENGTH); - - tmp_type = src_type; - for(i = 0; i < num_srcs; ++i) - tmp[i] = src[i]; - num_tmps = num_srcs; - - /* - * Clamp if necessary - */ - - if(memcmp(&src_type, &dst_type, sizeof src_type) != 0) { - struct lp_build_context bld; - double src_min = lp_const_min(src_type); - double dst_min = lp_const_min(dst_type); - double src_max = lp_const_max(src_type); - double dst_max = lp_const_max(dst_type); - LLVMValueRef thres; - - lp_build_context_init(&bld, builder, tmp_type); - - if(src_min < dst_min) { - if(dst_min == 0.0) - thres = bld.zero; - else - thres = lp_build_const_scalar(src_type, dst_min); - for(i = 0; i < num_tmps; ++i) - tmp[i] = lp_build_max(&bld, tmp[i], thres); - } - - if(src_max > dst_max) { - if(dst_max == 1.0) - thres = bld.one; - else - thres = lp_build_const_scalar(src_type, dst_max); - for(i = 0; i < num_tmps; ++i) - tmp[i] = lp_build_min(&bld, tmp[i], thres); - } - } - - /* - * Scale to the narrowest range - */ - - if(dst_type.floating) { - /* Nothing to do */ - } - else if(tmp_type.floating) { - if(!dst_type.fixed && !dst_type.sign && dst_type.norm) { - for(i = 0; i < num_tmps; ++i) { - tmp[i] = lp_build_clamped_float_to_unsigned_norm(builder, - tmp_type, - dst_type.width, - tmp[i]); - } - tmp_type.floating = FALSE; - } - else { - double dst_scale = lp_const_scale(dst_type); - LLVMTypeRef tmp_vec_type; - - if (dst_scale != 1.0) { - LLVMValueRef scale = lp_build_const_scalar(tmp_type, dst_scale); - for(i = 0; i < num_tmps; ++i) - tmp[i] = LLVMBuildMul(builder, tmp[i], scale, ""); - } - - /* Use an equally sized integer for intermediate computations */ - tmp_type.floating = FALSE; - tmp_vec_type = lp_build_vec_type(tmp_type); - for(i = 0; i < num_tmps; ++i) { -#if 0 - if(dst_type.sign) - tmp[i] = LLVMBuildFPToSI(builder, tmp[i], tmp_vec_type, ""); - else - tmp[i] = LLVMBuildFPToUI(builder, tmp[i], tmp_vec_type, ""); -#else - /* FIXME: there is no SSE counterpart for LLVMBuildFPToUI */ - tmp[i] = LLVMBuildFPToSI(builder, tmp[i], tmp_vec_type, ""); -#endif - } - } - } - else { - unsigned src_shift = lp_const_shift(src_type); - unsigned dst_shift = lp_const_shift(dst_type); - - /* FIXME: compensate different offsets too */ - if(src_shift > dst_shift) { - LLVMValueRef shift = lp_build_int_const_scalar(tmp_type, src_shift - dst_shift); - for(i = 0; i < num_tmps; ++i) - if(src_type.sign) - tmp[i] = LLVMBuildAShr(builder, tmp[i], shift, ""); - else - tmp[i] = LLVMBuildLShr(builder, tmp[i], shift, ""); - } - } - - /* - * Truncate or expand bit width - */ - - assert(!tmp_type.floating || tmp_type.width == dst_type.width); - - if(tmp_type.width > dst_type.width) { - assert(num_dsts == 1); - tmp[0] = lp_build_pack(builder, tmp_type, dst_type, TRUE, tmp, num_tmps); - tmp_type.width = dst_type.width; - tmp_type.length = dst_type.length; - num_tmps = 1; - } - - if(tmp_type.width < dst_type.width) { - assert(num_tmps == 1); - lp_build_unpack(builder, tmp_type, dst_type, tmp[0], tmp, num_dsts); - tmp_type.width = dst_type.width; - tmp_type.length = dst_type.length; - num_tmps = num_dsts; - } - - assert(tmp_type.width == dst_type.width); - assert(tmp_type.length == dst_type.length); - assert(num_tmps == num_dsts); - - /* - * Scale to the widest range - */ - - if(src_type.floating) { - /* Nothing to do */ - } - else if(!src_type.floating && dst_type.floating) { - if(!src_type.fixed && !src_type.sign && src_type.norm) { - for(i = 0; i < num_tmps; ++i) { - tmp[i] = lp_build_unsigned_norm_to_float(builder, - src_type.width, - dst_type, - tmp[i]); - } - tmp_type.floating = TRUE; - } - else { - double src_scale = lp_const_scale(src_type); - LLVMTypeRef tmp_vec_type; - - /* Use an equally sized integer for intermediate computations */ - tmp_type.floating = TRUE; - tmp_type.sign = TRUE; - tmp_vec_type = lp_build_vec_type(tmp_type); - for(i = 0; i < num_tmps; ++i) { -#if 0 - if(dst_type.sign) - tmp[i] = LLVMBuildSIToFP(builder, tmp[i], tmp_vec_type, ""); - else - tmp[i] = LLVMBuildUIToFP(builder, tmp[i], tmp_vec_type, ""); -#else - /* FIXME: there is no SSE counterpart for LLVMBuildUIToFP */ - tmp[i] = LLVMBuildSIToFP(builder, tmp[i], tmp_vec_type, ""); -#endif - } - - if (src_scale != 1.0) { - LLVMValueRef scale = lp_build_const_scalar(tmp_type, 1.0/src_scale); - for(i = 0; i < num_tmps; ++i) - tmp[i] = LLVMBuildMul(builder, tmp[i], scale, ""); - } - } - } - else { - unsigned src_shift = lp_const_shift(src_type); - unsigned dst_shift = lp_const_shift(dst_type); - - /* FIXME: compensate different offsets too */ - if(src_shift < dst_shift) { - LLVMValueRef shift = lp_build_int_const_scalar(tmp_type, dst_shift - src_shift); - for(i = 0; i < num_tmps; ++i) - tmp[i] = LLVMBuildShl(builder, tmp[i], shift, ""); - } - } - - for(i = 0; i < num_dsts; ++i) - dst[i] = tmp[i]; -} - - -/** - * Bit mask conversion. - * - * This will convert the integer masks that match the given types. - * - * The mask values should 0 or -1, i.e., all bits either set to zero or one. - * Any other value will likely cause in unpredictable results. - * - * This is basically a very trimmed down version of lp_build_conv. - */ -void -lp_build_conv_mask(LLVMBuilderRef builder, - struct lp_type src_type, - struct lp_type dst_type, - const LLVMValueRef *src, unsigned num_srcs, - LLVMValueRef *dst, unsigned num_dsts) -{ - /* Register width must remain constant */ - assert(src_type.width * src_type.length == dst_type.width * dst_type.length); - - /* We must not loose or gain channels. Only precision */ - assert(src_type.length * num_srcs == dst_type.length * num_dsts); - - /* - * Drop - * - * We assume all values are 0 or -1 - */ - - src_type.floating = FALSE; - src_type.fixed = FALSE; - src_type.sign = TRUE; - src_type.norm = FALSE; - - dst_type.floating = FALSE; - dst_type.fixed = FALSE; - dst_type.sign = TRUE; - dst_type.norm = FALSE; - - /* - * Truncate or expand bit width - */ - - if(src_type.width > dst_type.width) { - assert(num_dsts == 1); - dst[0] = lp_build_pack(builder, src_type, dst_type, TRUE, src, num_srcs); - } - else if(src_type.width < dst_type.width) { - assert(num_srcs == 1); - lp_build_unpack(builder, src_type, dst_type, src[0], dst, num_dsts); - } - else { - assert(num_srcs == num_dsts); - memcpy(dst, src, num_dsts * sizeof *dst); - } -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_conv.h b/src/gallium/drivers/llvmpipe/lp_bld_conv.h deleted file mode 100644 index 948e68fae4..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_conv.h +++ /dev/null @@ -1,73 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Helper functions for type conversions. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#ifndef LP_BLD_CONV_H -#define LP_BLD_CONV_H - - -#include <llvm-c/Core.h> - - -struct lp_type; - - -LLVMValueRef -lp_build_clamped_float_to_unsigned_norm(LLVMBuilderRef builder, - struct lp_type src_type, - unsigned dst_width, - LLVMValueRef src); - -LLVMValueRef -lp_build_unsigned_norm_to_float(LLVMBuilderRef builder, - unsigned src_width, - struct lp_type dst_type, - LLVMValueRef src); - - -void -lp_build_conv(LLVMBuilderRef builder, - struct lp_type src_type, - struct lp_type dst_type, - const LLVMValueRef *srcs, unsigned num_srcs, - LLVMValueRef *dsts, unsigned num_dsts); - -void -lp_build_conv_mask(LLVMBuilderRef builder, - struct lp_type src_type, - struct lp_type dst_type, - const LLVMValueRef *src, unsigned num_srcs, - LLVMValueRef *dst, unsigned num_dsts); - -#endif /* !LP_BLD_CONV_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_bld_debug.c b/src/gallium/drivers/llvmpipe/lp_bld_debug.c deleted file mode 100644 index 39dfc51e50..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_debug.c +++ /dev/null @@ -1,132 +0,0 @@ -/************************************************************************** - * - * 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. - * - **************************************************************************/ - - -#ifdef HAVE_UDIS86 -#include <udis86.h> -#endif - -#include "util/u_math.h" -#include "util/u_debug.h" -#include "lp_bld_debug.h" - - -/** - * Check alignment. - * - * It is important that this check is not implemented as a macro or inlined - * function, as the compiler assumptions in respect to alignment of global - * and stack variables would often make the check a no op, defeating the - * whole purpose of the exercise. - */ -boolean -lp_check_alignment(const void *ptr, unsigned alignment) -{ - assert(util_is_pot(alignment)); - return ((uintptr_t)ptr & (alignment - 1)) == 0; -} - - -void -lp_disassemble(const void* func) -{ -#ifdef HAVE_UDIS86 - ud_t ud_obj; - uint64_t max_jmp_pc; - - ud_init(&ud_obj); - - ud_set_input_buffer(&ud_obj, (void*)func, 0xffff); - - max_jmp_pc = (uint64_t) (uintptr_t) func; - ud_set_pc(&ud_obj, max_jmp_pc); - -#ifdef PIPE_ARCH_X86 - ud_set_mode(&ud_obj, 32); -#endif -#ifdef PIPE_ARCH_X86_64 - ud_set_mode(&ud_obj, 64); -#endif - - ud_set_syntax(&ud_obj, UD_SYN_ATT); - - while (ud_disassemble(&ud_obj)) { - -#ifdef PIPE_ARCH_X86 - debug_printf("0x%08lx:\t", (unsigned long)ud_insn_off(&ud_obj)); -#endif -#ifdef PIPE_ARCH_X86_64 - debug_printf("0x%016llx:\t", (unsigned long long)ud_insn_off(&ud_obj)); -#endif - -#if 0 - debug_printf("%-16s ", ud_insn_hex(&ud_obj)); -#endif - - debug_printf("%s\n", ud_insn_asm(&ud_obj)); - - if(ud_obj.mnemonic != UD_Icall) { - unsigned i; - for(i = 0; i < 3; ++i) { - const struct ud_operand *op = &ud_obj.operand[i]; - if (op->type == UD_OP_JIMM){ - uint64_t pc = ud_obj.pc; - - switch (op->size) { - case 8: - pc += op->lval.sbyte; - break; - case 16: - pc += op->lval.sword; - break; - case 32: - pc += op->lval.sdword; - break; - default: - break; - } - if(pc > max_jmp_pc) - max_jmp_pc = pc; - } - } - } - - if ((ud_insn_off(&ud_obj) >= max_jmp_pc && ud_obj.mnemonic == UD_Iret) || - ud_obj.mnemonic == UD_Iinvalid) - break; - } - -#if 0 - /* Print GDB command, useful to verify udis86 output */ - debug_printf("disassemble %p %p\n", func, (void*)(uintptr_t)ud_obj.pc); -#endif - - debug_printf("\n"); -#else - (void)func; -#endif -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.c b/src/gallium/drivers/llvmpipe/lp_bld_depth.c deleted file mode 100644 index d438c0e63d..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_depth.c +++ /dev/null @@ -1,213 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Depth/stencil testing to LLVM IR translation. - * - * To be done accurately/efficiently the depth/stencil test must be done with - * the same type/format of the depth/stencil buffer, which implies massaging - * the incoming depths to fit into place. Using a more straightforward - * type/format for depth/stencil values internally and only convert when - * flushing would avoid this, but it would most likely result in depth fighting - * artifacts. - * - * We are free to use a different pixel layout though. Since our basic - * processing unit is a quad (2x2 pixel block) we store the depth/stencil - * values tiled, a quad at time. That is, a depth buffer containing - * - * Z11 Z12 Z13 Z14 ... - * Z21 Z22 Z23 Z24 ... - * Z31 Z32 Z33 Z34 ... - * Z41 Z42 Z43 Z44 ... - * ... ... ... ... ... - * - * will actually be stored in memory as - * - * Z11 Z12 Z21 Z22 Z13 Z14 Z23 Z24 ... - * Z31 Z32 Z41 Z42 Z33 Z34 Z43 Z44 ... - * ... ... ... ... ... ... ... ... ... - * - * FIXME: Code generate stencil test - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - -#include "pipe/p_state.h" -#include "util/u_format.h" - -#include "lp_bld_type.h" -#include "lp_bld_const.h" -#include "lp_bld_logic.h" -#include "lp_bld_flow.h" -#include "lp_bld_debug.h" -#include "lp_bld_depth.h" - - -/** - * Return a type appropriate for depth/stencil testing. - */ -struct lp_type -lp_depth_type(const struct util_format_description *format_desc, - unsigned length) -{ - struct lp_type type; - unsigned swizzle; - - assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS); - assert(format_desc->block.width == 1); - assert(format_desc->block.height == 1); - - swizzle = format_desc->swizzle[0]; - assert(swizzle < 4); - - memset(&type, 0, sizeof type); - type.width = format_desc->block.bits; - - if(format_desc->channel[swizzle].type == UTIL_FORMAT_TYPE_FLOAT) { - type.floating = TRUE; - assert(swizzle == 0); - assert(format_desc->channel[swizzle].size == format_desc->block.bits); - } - else if(format_desc->channel[swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED) { - assert(format_desc->block.bits <= 32); - if(format_desc->channel[swizzle].normalized) - type.norm = TRUE; - } - else - assert(0); - - assert(type.width <= length); - type.length = length / type.width; - - return type; -} - - -/** - * Depth test. - */ -void -lp_build_depth_test(LLVMBuilderRef builder, - const struct pipe_depth_state *state, - struct lp_type type, - const struct util_format_description *format_desc, - struct lp_build_mask_context *mask, - LLVMValueRef src, - LLVMValueRef dst_ptr) -{ - struct lp_build_context bld; - unsigned z_swizzle; - LLVMValueRef dst; - LLVMValueRef z_bitmask = NULL; - LLVMValueRef test; - - if(!state->enabled) - return; - - assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS); - assert(format_desc->block.width == 1); - assert(format_desc->block.height == 1); - - z_swizzle = format_desc->swizzle[0]; - if(z_swizzle == UTIL_FORMAT_SWIZZLE_NONE) - return; - - /* Sanity checking */ - assert(z_swizzle < 4); - assert(format_desc->block.bits == type.width); - if(type.floating) { - assert(z_swizzle == 0); - assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_FLOAT); - assert(format_desc->channel[z_swizzle].size == format_desc->block.bits); - } - else { - assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED); - assert(format_desc->channel[z_swizzle].normalized); - assert(!type.fixed); - assert(!type.sign); - assert(type.norm); - } - - /* Setup build context */ - lp_build_context_init(&bld, builder, type); - - dst = LLVMBuildLoad(builder, dst_ptr, ""); - - lp_build_name(dst, "zsbuf"); - - /* Align the source depth bits with the destination's, and mask out any - * stencil or padding bits from both */ - if(format_desc->channel[z_swizzle].size == format_desc->block.bits) { - assert(z_swizzle == 0); - /* nothing to do */ - } - else { - unsigned padding_left; - unsigned padding_right; - unsigned chan; - - assert(format_desc->layout == UTIL_FORMAT_LAYOUT_ARITH); - assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED); - assert(format_desc->channel[z_swizzle].size <= format_desc->block.bits); - assert(format_desc->channel[z_swizzle].normalized); - - padding_right = 0; - for(chan = 0; chan < z_swizzle; ++chan) - padding_right += format_desc->channel[chan].size; - padding_left = format_desc->block.bits - - (padding_right + format_desc->channel[z_swizzle].size); - - if(padding_left || padding_right) { - const unsigned long long mask_left = ((unsigned long long)1 << (format_desc->block.bits - padding_left)) - 1; - const unsigned long long mask_right = ((unsigned long long)1 << (padding_right)) - 1; - z_bitmask = lp_build_int_const_scalar(type, mask_left ^ mask_right); - } - - if(padding_left) - src = LLVMBuildLShr(builder, src, lp_build_int_const_scalar(type, padding_left), ""); - if(padding_right) - src = LLVMBuildAnd(builder, src, z_bitmask, ""); - if(padding_left || padding_right) - dst = LLVMBuildAnd(builder, dst, z_bitmask, ""); - } - - lp_build_name(dst, "zsbuf.z"); - - test = lp_build_cmp(&bld, state->func, src, dst); - lp_build_mask_update(mask, test); - - if(state->writemask) { - if(z_bitmask) - z_bitmask = LLVMBuildAnd(builder, mask->value, z_bitmask, ""); - else - z_bitmask = mask->value; - - dst = lp_build_select(&bld, z_bitmask, src, dst); - LLVMBuildStore(builder, dst, dst_ptr); - } -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.h b/src/gallium/drivers/llvmpipe/lp_bld_depth.h deleted file mode 100644 index 79d6981bb5..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_depth.h +++ /dev/null @@ -1,63 +0,0 @@ -/************************************************************************** - * - * 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. - * - **************************************************************************/ - - -/** - * Depth/stencil testing to LLVM IR translation. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - -#ifndef LP_BLD_DEPTH_H -#define LP_BLD_DEPTH_H - - -#include <llvm-c/Core.h> - - -struct pipe_depth_state; -struct util_format_description; -struct lp_type; -struct lp_build_mask_context; - - -struct lp_type -lp_depth_type(const struct util_format_description *format_desc, - unsigned length); - - -void -lp_build_depth_test(LLVMBuilderRef builder, - const struct pipe_depth_state *state, - struct lp_type type, - const struct util_format_description *format_desc, - struct lp_build_mask_context *mask, - LLVMValueRef src, - LLVMValueRef dst_ptr); - - -#endif /* !LP_BLD_DEPTH_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_bld_flow.c b/src/gallium/drivers/llvmpipe/lp_bld_flow.c deleted file mode 100644 index 25c10af29f..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_flow.c +++ /dev/null @@ -1,493 +0,0 @@ -/************************************************************************** - * - * 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. - * - **************************************************************************/ - -/** - * LLVM control flow build helpers. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - -#include "util/u_debug.h" -#include "util/u_memory.h" - -#include "lp_bld_type.h" -#include "lp_bld_flow.h" - - -#define LP_BUILD_FLOW_MAX_VARIABLES 32 -#define LP_BUILD_FLOW_MAX_DEPTH 32 - - -/** - * Enumeration of all possible flow constructs. - */ -enum lp_build_flow_construct_kind { - lP_BUILD_FLOW_SCOPE, - LP_BUILD_FLOW_SKIP -}; - - -/** - * Variable declaration scope. - */ -struct lp_build_flow_scope -{ - /** Number of variables declared in this scope */ - unsigned num_variables; -}; - - -/** - * Early exit. Useful to skip to the end of a function or block when - * the execution mask becomes zero or when there is an error condition. - */ -struct lp_build_flow_skip -{ - /** Block to skip to */ - LLVMBasicBlockRef block; - - /** Number of variables declared at the beginning */ - unsigned num_variables; - - LLVMValueRef *phi; -}; - - -/** - * Union of all possible flow constructs' data - */ -union lp_build_flow_construct_data -{ - struct lp_build_flow_scope scope; - struct lp_build_flow_skip skip; -}; - - -/** - * Element of the flow construct stack. - */ -struct lp_build_flow_construct -{ - enum lp_build_flow_construct_kind kind; - union lp_build_flow_construct_data data; -}; - - -/** - * All necessary data to generate LLVM control flow constructs. - * - * Besides keeping track of the control flow construct themselves we also - * need to keep track of variables in order to generate SSA Phi values. - */ -struct lp_build_flow_context -{ - LLVMBuilderRef builder; - - /** - * Control flow stack. - */ - struct lp_build_flow_construct constructs[LP_BUILD_FLOW_MAX_DEPTH]; - unsigned num_constructs; - - /** - * Variable stack - */ - LLVMValueRef *variables[LP_BUILD_FLOW_MAX_VARIABLES]; - unsigned num_variables; -}; - - -struct lp_build_flow_context * -lp_build_flow_create(LLVMBuilderRef builder) -{ - struct lp_build_flow_context *flow; - - flow = CALLOC_STRUCT(lp_build_flow_context); - if(!flow) - return NULL; - - flow->builder = builder; - - return flow; -} - - -void -lp_build_flow_destroy(struct lp_build_flow_context *flow) -{ - assert(flow->num_constructs == 0); - assert(flow->num_variables == 0); - FREE(flow); -} - - -static union lp_build_flow_construct_data * -lp_build_flow_push(struct lp_build_flow_context *flow, - enum lp_build_flow_construct_kind kind) -{ - assert(flow->num_constructs < LP_BUILD_FLOW_MAX_DEPTH); - if(flow->num_constructs >= LP_BUILD_FLOW_MAX_DEPTH) - return NULL; - - flow->constructs[flow->num_constructs].kind = kind; - return &flow->constructs[flow->num_constructs++].data; -} - - -static union lp_build_flow_construct_data * -lp_build_flow_peek(struct lp_build_flow_context *flow, - enum lp_build_flow_construct_kind kind) -{ - assert(flow->num_constructs); - if(!flow->num_constructs) - return NULL; - - assert(flow->constructs[flow->num_constructs - 1].kind == kind); - if(flow->constructs[flow->num_constructs - 1].kind != kind) - return NULL; - - return &flow->constructs[flow->num_constructs - 1].data; -} - - -static union lp_build_flow_construct_data * -lp_build_flow_pop(struct lp_build_flow_context *flow, - enum lp_build_flow_construct_kind kind) -{ - assert(flow->num_constructs); - if(!flow->num_constructs) - return NULL; - - assert(flow->constructs[flow->num_constructs - 1].kind == kind); - if(flow->constructs[flow->num_constructs - 1].kind != kind) - return NULL; - - return &flow->constructs[--flow->num_constructs].data; -} - - -/** - * Begin a variable scope. - * - * - */ -void -lp_build_flow_scope_begin(struct lp_build_flow_context *flow) -{ - struct lp_build_flow_scope *scope; - - scope = &lp_build_flow_push(flow, lP_BUILD_FLOW_SCOPE)->scope; - if(!scope) - return; - - scope->num_variables = 0; -} - - -/** - * Declare a variable. - * - * A variable is a named entity which can have different LLVMValueRef's at - * different points of the program. This is relevant for control flow because - * when there are mutiple branches to a same location we need to replace - * the variable's value with a Phi function as explained in - * http://en.wikipedia.org/wiki/Static_single_assignment_form . - * - * We keep track of variables by keeping around a pointer to where their - * current. - * - * There are a few cautions to observe: - * - * - Variable's value must not be NULL. If there is no initial value then - * LLVMGetUndef() should be used. - * - * - Variable's value must be kept up-to-date. If the variable is going to be - * modified by a function then a pointer should be passed so that its value - * is accurate. Failure to do this will cause some of the variables' - * transient values to be lost, leading to wrong results. - * - * - A program should be written from top to bottom, by always appending - * instructions to the bottom with a single LLVMBuilderRef. Inserting and/or - * modifying existing statements will most likely lead to wrong results. - * - */ -void -lp_build_flow_scope_declare(struct lp_build_flow_context *flow, - LLVMValueRef *variable) -{ - struct lp_build_flow_scope *scope; - - scope = &lp_build_flow_peek(flow, lP_BUILD_FLOW_SCOPE)->scope; - if(!scope) - return; - - assert(*variable); - if(!*variable) - return; - - assert(flow->num_variables < LP_BUILD_FLOW_MAX_VARIABLES); - if(flow->num_variables >= LP_BUILD_FLOW_MAX_VARIABLES) - return; - - flow->variables[flow->num_variables++] = variable; - ++scope->num_variables; -} - - -void -lp_build_flow_scope_end(struct lp_build_flow_context *flow) -{ - struct lp_build_flow_scope *scope; - - scope = &lp_build_flow_pop(flow, lP_BUILD_FLOW_SCOPE)->scope; - if(!scope) - return; - - assert(flow->num_variables >= scope->num_variables); - if(flow->num_variables < scope->num_variables) { - flow->num_variables = 0; - return; - } - - flow->num_variables -= scope->num_variables; -} - - -static LLVMBasicBlockRef -lp_build_flow_insert_block(struct lp_build_flow_context *flow) -{ - LLVMBasicBlockRef current_block; - LLVMBasicBlockRef next_block; - LLVMBasicBlockRef new_block; - - current_block = LLVMGetInsertBlock(flow->builder); - - next_block = LLVMGetNextBasicBlock(current_block); - if(next_block) { - new_block = LLVMInsertBasicBlock(next_block, ""); - } - else { - LLVMValueRef function = LLVMGetBasicBlockParent(current_block); - new_block = LLVMAppendBasicBlock(function, ""); - } - - return new_block; -} - -void -lp_build_flow_skip_begin(struct lp_build_flow_context *flow) -{ - struct lp_build_flow_skip *skip; - LLVMBuilderRef builder; - unsigned i; - - skip = &lp_build_flow_push(flow, LP_BUILD_FLOW_SKIP)->skip; - if(!skip) - return; - - skip->block = lp_build_flow_insert_block(flow); - skip->num_variables = flow->num_variables; - if(!skip->num_variables) { - skip->phi = NULL; - return; - } - - skip->phi = MALLOC(skip->num_variables * sizeof *skip->phi); - if(!skip->phi) { - skip->num_variables = 0; - return; - } - - builder = LLVMCreateBuilder(); - LLVMPositionBuilderAtEnd(builder, skip->block); - - for(i = 0; i < skip->num_variables; ++i) - skip->phi[i] = LLVMBuildPhi(builder, LLVMTypeOf(*flow->variables[i]), ""); - - LLVMDisposeBuilder(builder); -} - - -void -lp_build_flow_skip_cond_break(struct lp_build_flow_context *flow, - LLVMValueRef cond) -{ - struct lp_build_flow_skip *skip; - LLVMBasicBlockRef current_block; - LLVMBasicBlockRef new_block; - unsigned i; - - skip = &lp_build_flow_peek(flow, LP_BUILD_FLOW_SKIP)->skip; - if(!skip) - return; - - current_block = LLVMGetInsertBlock(flow->builder); - - new_block = lp_build_flow_insert_block(flow); - - for(i = 0; i < skip->num_variables; ++i) { - assert(*flow->variables[i]); - LLVMAddIncoming(skip->phi[i], flow->variables[i], ¤t_block, 1); - } - - LLVMBuildCondBr(flow->builder, cond, skip->block, new_block); - - LLVMPositionBuilderAtEnd(flow->builder, new_block); - } - - -void -lp_build_flow_skip_end(struct lp_build_flow_context *flow) -{ - struct lp_build_flow_skip *skip; - LLVMBasicBlockRef current_block; - unsigned i; - - skip = &lp_build_flow_pop(flow, LP_BUILD_FLOW_SKIP)->skip; - if(!skip) - return; - - current_block = LLVMGetInsertBlock(flow->builder); - - for(i = 0; i < skip->num_variables; ++i) { - assert(*flow->variables[i]); - LLVMAddIncoming(skip->phi[i], flow->variables[i], ¤t_block, 1); - *flow->variables[i] = skip->phi[i]; - } - - LLVMBuildBr(flow->builder, skip->block); - LLVMPositionBuilderAtEnd(flow->builder, skip->block); - - FREE(skip->phi); -} - - -static void -lp_build_mask_check(struct lp_build_mask_context *mask) -{ - LLVMBuilderRef builder = mask->flow->builder; - LLVMValueRef cond; - - cond = LLVMBuildICmp(builder, - LLVMIntEQ, - LLVMBuildBitCast(builder, mask->value, mask->reg_type, ""), - LLVMConstNull(mask->reg_type), - ""); - - lp_build_flow_skip_cond_break(mask->flow, cond); -} - - -void -lp_build_mask_begin(struct lp_build_mask_context *mask, - struct lp_build_flow_context *flow, - struct lp_type type, - LLVMValueRef value) -{ - memset(mask, 0, sizeof *mask); - - mask->flow = flow; - mask->reg_type = LLVMIntType(type.width * type.length); - mask->value = value; - - lp_build_flow_scope_begin(flow); - lp_build_flow_scope_declare(flow, &mask->value); - lp_build_flow_skip_begin(flow); - - lp_build_mask_check(mask); -} - - -void -lp_build_mask_update(struct lp_build_mask_context *mask, - LLVMValueRef value) -{ - mask->value = LLVMBuildAnd( mask->flow->builder, mask->value, value, ""); - - lp_build_mask_check(mask); -} - - -LLVMValueRef -lp_build_mask_end(struct lp_build_mask_context *mask) -{ - lp_build_flow_skip_end(mask->flow); - lp_build_flow_scope_end(mask->flow); - return mask->value; -} - - - -void -lp_build_loop_begin(LLVMBuilderRef builder, - LLVMValueRef start, - struct lp_build_loop_state *state) -{ - LLVMBasicBlockRef block = LLVMGetInsertBlock(builder); - LLVMValueRef function = LLVMGetBasicBlockParent(block); - - state->block = LLVMAppendBasicBlock(function, "loop"); - - LLVMBuildBr(builder, state->block); - - LLVMPositionBuilderAtEnd(builder, state->block); - - state->counter = LLVMBuildPhi(builder, LLVMTypeOf(start), ""); - - LLVMAddIncoming(state->counter, &start, &block, 1); - -} - - -void -lp_build_loop_end(LLVMBuilderRef builder, - LLVMValueRef end, - LLVMValueRef step, - struct lp_build_loop_state *state) -{ - LLVMBasicBlockRef block = LLVMGetInsertBlock(builder); - LLVMValueRef function = LLVMGetBasicBlockParent(block); - LLVMValueRef next; - LLVMValueRef cond; - LLVMBasicBlockRef after_block; - - if (!step) - step = LLVMConstInt(LLVMTypeOf(end), 1, 0); - - next = LLVMBuildAdd(builder, state->counter, step, ""); - - cond = LLVMBuildICmp(builder, LLVMIntNE, next, end, ""); - - after_block = LLVMAppendBasicBlock(function, ""); - - LLVMBuildCondBr(builder, cond, after_block, state->block); - - LLVMAddIncoming(state->counter, &next, &block, 1); - - LLVMPositionBuilderAtEnd(builder, after_block); -} - diff --git a/src/gallium/drivers/llvmpipe/lp_bld_flow.h b/src/gallium/drivers/llvmpipe/lp_bld_flow.h deleted file mode 100644 index e61999ff06..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_flow.h +++ /dev/null @@ -1,129 +0,0 @@ -/************************************************************************** - * - * 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. - * - **************************************************************************/ - -/** - * LLVM control flow build helpers. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - -#ifndef LP_BLD_FLOW_H -#define LP_BLD_FLOW_H - - -#include <llvm-c/Core.h> - - -struct lp_type; - - -struct lp_build_flow_context; - - -struct lp_build_flow_context * -lp_build_flow_create(LLVMBuilderRef builder); - -void -lp_build_flow_destroy(struct lp_build_flow_context *flow); - -void -lp_build_flow_scope_begin(struct lp_build_flow_context *flow); - -void -lp_build_flow_scope_declare(struct lp_build_flow_context *flow, - LLVMValueRef *variable); - -void -lp_build_flow_scope_end(struct lp_build_flow_context *flow); - -void -lp_build_flow_skip_begin(struct lp_build_flow_context *flow); - -void -lp_build_flow_skip_cond_break(struct lp_build_flow_context *flow, - LLVMValueRef cond); - -void -lp_build_flow_skip_end(struct lp_build_flow_context *flow); - - -struct lp_build_mask_context -{ - struct lp_build_flow_context *flow; - - LLVMTypeRef reg_type; - - LLVMValueRef value; -}; - - -void -lp_build_mask_begin(struct lp_build_mask_context *mask, - struct lp_build_flow_context *flow, - struct lp_type type, - LLVMValueRef value); - -/** - * Bitwise AND the mask with the given value, if a previous mask was set. - */ -void -lp_build_mask_update(struct lp_build_mask_context *mask, - LLVMValueRef value); - -LLVMValueRef -lp_build_mask_end(struct lp_build_mask_context *mask); - - -/** - * LLVM's IR doesn't represent for-loops directly. Furthermore it - * it requires creating code blocks, branches, phi variables, so it - * requires a fair amount of code. - * - * @sa http://www.llvm.org/docs/tutorial/LangImpl5.html#for - */ -struct lp_build_loop_state -{ - LLVMBasicBlockRef block; - LLVMValueRef counter; -}; - - -void -lp_build_loop_begin(LLVMBuilderRef builder, - LLVMValueRef start, - struct lp_build_loop_state *state); - - -void -lp_build_loop_end(LLVMBuilderRef builder, - LLVMValueRef end, - LLVMValueRef step, - struct lp_build_loop_state *state); - - - -#endif /* !LP_BLD_FLOW_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_bld_format.h b/src/gallium/drivers/llvmpipe/lp_bld_format.h deleted file mode 100644 index 970bee379f..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_format.h +++ /dev/null @@ -1,83 +0,0 @@ -/************************************************************************** - * - * 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 LP_BLD_FORMAT_H -#define LP_BLD_FORMAT_H - - -/** - * @file - * Pixel format helpers. - */ - -#include <llvm-c/Core.h> - -#include "pipe/p_format.h" - -struct util_format_description; -struct lp_type; - - -boolean -lp_format_is_rgba8(const struct util_format_description *desc); - - -void -lp_build_format_swizzle_soa(const struct util_format_description *format_desc, - struct lp_type type, - const LLVMValueRef *unswizzled, - LLVMValueRef *swizzled); - - -LLVMValueRef -lp_build_unpack_rgba_aos(LLVMBuilderRef builder, - const struct util_format_description *desc, - LLVMValueRef packed); - - -LLVMValueRef -lp_build_unpack_rgba8_aos(LLVMBuilderRef builder, - const struct util_format_description *desc, - struct lp_type type, - LLVMValueRef packed); - - -LLVMValueRef -lp_build_pack_rgba_aos(LLVMBuilderRef builder, - const struct util_format_description *desc, - LLVMValueRef rgba); - - -void -lp_build_unpack_rgba_soa(LLVMBuilderRef builder, - const struct util_format_description *format_desc, - struct lp_type type, - LLVMValueRef packed, - LLVMValueRef *rgba); - - -#endif /* !LP_BLD_FORMAT_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_bld_format_aos.c b/src/gallium/drivers/llvmpipe/lp_bld_format_aos.c deleted file mode 100644 index 10e82f120b..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_format_aos.c +++ /dev/null @@ -1,384 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * AoS pixel format manipulation. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#include "util/u_cpu_detect.h" -#include "util/u_format.h" - -#include "lp_bld_type.h" -#include "lp_bld_const.h" -#include "lp_bld_logic.h" -#include "lp_bld_swizzle.h" -#include "lp_bld_format.h" - - -/** - * Unpack a single pixel into its RGBA components. - * - * @param packed integer. - * - * @return RGBA in a 4 floats vector. - * - * XXX: This is mostly for reference and testing -- operating a single pixel at - * a time is rarely if ever needed. - */ -LLVMValueRef -lp_build_unpack_rgba_aos(LLVMBuilderRef builder, - const struct util_format_description *desc, - LLVMValueRef packed) -{ - LLVMTypeRef type; - LLVMValueRef shifted, casted, scaled, masked; - LLVMValueRef shifts[4]; - LLVMValueRef masks[4]; - LLVMValueRef scales[4]; - LLVMValueRef swizzles[4]; - LLVMValueRef aux[4]; - bool normalized; - int empty_channel; - unsigned shift; - unsigned i; - - /* FIXME: Support more formats */ - assert(desc->layout == UTIL_FORMAT_LAYOUT_ARITH); - assert(desc->block.width == 1); - assert(desc->block.height == 1); - assert(desc->block.bits <= 32); - - type = LLVMIntType(desc->block.bits); - - /* Do the intermediate integer computations with 32bit integers since it - * matches floating point size */ - if (desc->block.bits < 32) - packed = LLVMBuildZExt(builder, packed, LLVMInt32Type(), ""); - - /* Broadcast the packed value to all four channels */ - packed = LLVMBuildInsertElement(builder, - LLVMGetUndef(LLVMVectorType(LLVMInt32Type(), 4)), - packed, - LLVMConstNull(LLVMInt32Type()), - ""); - packed = LLVMBuildShuffleVector(builder, - packed, - LLVMGetUndef(LLVMVectorType(LLVMInt32Type(), 4)), - LLVMConstNull(LLVMVectorType(LLVMInt32Type(), 4)), - ""); - - /* Initialize vector constants */ - normalized = FALSE; - empty_channel = -1; - shift = 0; - for (i = 0; i < 4; ++i) { - unsigned bits = desc->channel[i].size; - - if (desc->channel[i].type == UTIL_FORMAT_TYPE_VOID) { - shifts[i] = LLVMGetUndef(LLVMInt32Type()); - masks[i] = LLVMConstNull(LLVMInt32Type()); - scales[i] = LLVMConstNull(LLVMFloatType()); - empty_channel = i; - } - else { - unsigned mask = (1 << bits) - 1; - - assert(desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED); - assert(bits < 32); - - shifts[i] = LLVMConstInt(LLVMInt32Type(), shift, 0); - masks[i] = LLVMConstInt(LLVMInt32Type(), mask, 0); - - if (desc->channel[i].normalized) { - scales[i] = LLVMConstReal(LLVMFloatType(), 1.0/mask); - normalized = TRUE; - } - else - scales[i] = LLVMConstReal(LLVMFloatType(), 1.0); - } - - shift += bits; - } - - shifted = LLVMBuildLShr(builder, packed, LLVMConstVector(shifts, 4), ""); - masked = LLVMBuildAnd(builder, shifted, LLVMConstVector(masks, 4), ""); - /* UIToFP can't be expressed in SSE2 */ - casted = LLVMBuildSIToFP(builder, masked, LLVMVectorType(LLVMFloatType(), 4), ""); - - if (normalized) - scaled = LLVMBuildMul(builder, casted, LLVMConstVector(scales, 4), ""); - else - scaled = casted; - - for (i = 0; i < 4; ++i) - aux[i] = LLVMGetUndef(LLVMFloatType()); - - for (i = 0; i < 4; ++i) { - enum util_format_swizzle swizzle = desc->swizzle[i]; - - switch (swizzle) { - case UTIL_FORMAT_SWIZZLE_X: - case UTIL_FORMAT_SWIZZLE_Y: - case UTIL_FORMAT_SWIZZLE_Z: - case UTIL_FORMAT_SWIZZLE_W: - swizzles[i] = LLVMConstInt(LLVMInt32Type(), swizzle, 0); - break; - case UTIL_FORMAT_SWIZZLE_0: - assert(empty_channel >= 0); - swizzles[i] = LLVMConstInt(LLVMInt32Type(), empty_channel, 0); - break; - case UTIL_FORMAT_SWIZZLE_1: - swizzles[i] = LLVMConstInt(LLVMInt32Type(), 4, 0); - aux[0] = LLVMConstReal(LLVMFloatType(), 1.0); - break; - case UTIL_FORMAT_SWIZZLE_NONE: - swizzles[i] = LLVMGetUndef(LLVMFloatType()); - assert(0); - break; - } - } - - return LLVMBuildShuffleVector(builder, scaled, LLVMConstVector(aux, 4), LLVMConstVector(swizzles, 4), ""); -} - - -/** - * Take a vector with packed pixels and unpack into a rgba8 vector. - * - * Formats with bit depth smaller than 32bits are accepted, but they must be - * padded to 32bits. - */ -LLVMValueRef -lp_build_unpack_rgba8_aos(LLVMBuilderRef builder, - const struct util_format_description *desc, - struct lp_type type, - LLVMValueRef packed) -{ - struct lp_build_context bld; - bool rgba8; - LLVMValueRef res; - unsigned i; - - lp_build_context_init(&bld, builder, type); - - /* FIXME: Support more formats */ - assert(desc->layout == UTIL_FORMAT_LAYOUT_ARITH); - assert(desc->block.width == 1); - assert(desc->block.height == 1); - assert(desc->block.bits <= 32); - - assert(!type.floating); - assert(!type.fixed); - assert(type.norm); - assert(type.width == 8); - assert(type.length % 4 == 0); - - rgba8 = TRUE; - for(i = 0; i < 4; ++i) { - assert(desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED || - desc->channel[i].type == UTIL_FORMAT_TYPE_VOID); - if(desc->channel[0].size != 8) - rgba8 = FALSE; - } - - if(rgba8) { - /* - * The pixel is already in a rgba8 format variant. All it is necessary - * is to swizzle the channels. - */ - - unsigned char swizzles[4]; - boolean zeros[4]; /* bitwise AND mask */ - boolean ones[4]; /* bitwise OR mask */ - boolean swizzles_needed = FALSE; - boolean zeros_needed = FALSE; - boolean ones_needed = FALSE; - - for(i = 0; i < 4; ++i) { - enum util_format_swizzle swizzle = desc->swizzle[i]; - - /* Initialize with the no-op case */ - swizzles[i] = util_cpu_caps.little_endian ? 3 - i : i; - zeros[i] = TRUE; - ones[i] = FALSE; - - switch (swizzle) { - case UTIL_FORMAT_SWIZZLE_X: - case UTIL_FORMAT_SWIZZLE_Y: - case UTIL_FORMAT_SWIZZLE_Z: - case UTIL_FORMAT_SWIZZLE_W: - if(swizzle != swizzles[i]) { - swizzles[i] = swizzle; - swizzles_needed = TRUE; - } - break; - case UTIL_FORMAT_SWIZZLE_0: - zeros[i] = FALSE; - zeros_needed = TRUE; - break; - case UTIL_FORMAT_SWIZZLE_1: - ones[i] = TRUE; - ones_needed = TRUE; - break; - case UTIL_FORMAT_SWIZZLE_NONE: - assert(0); - break; - } - } - - res = packed; - - if(swizzles_needed) - res = lp_build_swizzle1_aos(&bld, res, swizzles); - - if(zeros_needed) { - /* Mask out zero channels */ - LLVMValueRef mask = lp_build_const_mask_aos(type, zeros); - res = LLVMBuildAnd(builder, res, mask, ""); - } - - if(ones_needed) { - /* Or one channels */ - LLVMValueRef mask = lp_build_const_mask_aos(type, ones); - res = LLVMBuildOr(builder, res, mask, ""); - } - } - else { - /* FIXME */ - assert(0); - res = lp_build_undef(type); - } - - return res; -} - - -/** - * Pack a single pixel. - * - * @param rgba 4 float vector with the unpacked components. - * - * XXX: This is mostly for reference and testing -- operating a single pixel at - * a time is rarely if ever needed. - */ -LLVMValueRef -lp_build_pack_rgba_aos(LLVMBuilderRef builder, - const struct util_format_description *desc, - LLVMValueRef rgba) -{ - LLVMTypeRef type; - LLVMValueRef packed = NULL; - LLVMValueRef swizzles[4]; - LLVMValueRef shifted, casted, scaled, unswizzled; - LLVMValueRef shifts[4]; - LLVMValueRef scales[4]; - bool normalized; - unsigned shift; - unsigned i, j; - - assert(desc->layout == UTIL_FORMAT_LAYOUT_ARITH); - assert(desc->block.width == 1); - assert(desc->block.height == 1); - - type = LLVMIntType(desc->block.bits); - - /* Unswizzle the color components into the source vector. */ - for (i = 0; i < 4; ++i) { - for (j = 0; j < 4; ++j) { - if (desc->swizzle[j] == i) - break; - } - if (j < 4) - swizzles[i] = LLVMConstInt(LLVMInt32Type(), j, 0); - else - swizzles[i] = LLVMGetUndef(LLVMInt32Type()); - } - - unswizzled = LLVMBuildShuffleVector(builder, rgba, - LLVMGetUndef(LLVMVectorType(LLVMFloatType(), 4)), - LLVMConstVector(swizzles, 4), ""); - - normalized = FALSE; - shift = 0; - for (i = 0; i < 4; ++i) { - unsigned bits = desc->channel[i].size; - - if (desc->channel[i].type == UTIL_FORMAT_TYPE_VOID) { - shifts[i] = LLVMGetUndef(LLVMInt32Type()); - scales[i] = LLVMGetUndef(LLVMFloatType()); - } - else { - unsigned mask = (1 << bits) - 1; - - assert(desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED); - assert(bits < 32); - - shifts[i] = LLVMConstInt(LLVMInt32Type(), shift, 0); - - if (desc->channel[i].normalized) { - scales[i] = LLVMConstReal(LLVMFloatType(), mask); - normalized = TRUE; - } - else - scales[i] = LLVMConstReal(LLVMFloatType(), 1.0); - } - - shift += bits; - } - - if (normalized) - scaled = LLVMBuildMul(builder, unswizzled, LLVMConstVector(scales, 4), ""); - else - scaled = unswizzled; - - casted = LLVMBuildFPToSI(builder, scaled, LLVMVectorType(LLVMInt32Type(), 4), ""); - - shifted = LLVMBuildShl(builder, casted, LLVMConstVector(shifts, 4), ""); - - /* Bitwise or all components */ - for (i = 0; i < 4; ++i) { - if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) { - LLVMValueRef component = LLVMBuildExtractElement(builder, shifted, LLVMConstInt(LLVMInt32Type(), i, 0), ""); - if (packed) - packed = LLVMBuildOr(builder, packed, component, ""); - else - packed = component; - } - } - - if (!packed) - packed = LLVMGetUndef(LLVMInt32Type()); - - if (desc->block.bits < 32) - packed = LLVMBuildTrunc(builder, packed, type, ""); - - return packed; -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_format_query.c b/src/gallium/drivers/llvmpipe/lp_bld_format_query.c deleted file mode 100644 index f3832d07ff..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_format_query.c +++ /dev/null @@ -1,72 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Utility functions to make assertions about formats. - * - * This module centralizes most of logic used when determining what algorithm - * is most suitable (i.e., most efficient yet correct) for a given format. - * - * It might be possible to move some of these functions to u_format module, - * but since tiny differences in the format my render it more/less - * appropriate to a given algorithm it is impossible to make any long term - * guarantee about the semantics of these functions. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#include "util/u_format.h" - -#include "lp_bld_format.h" - - -/** - * Whether this format is a 4 rgba8 variant - */ -boolean -lp_format_is_rgba8(const struct util_format_description *desc) -{ - unsigned chan; - - if(desc->block.width != 1 || - desc->block.height != 1 || - desc->block.bits != 32) - return FALSE; - - for(chan = 0; chan < 4; ++chan) { - if(desc->channel[chan].type != UTIL_FORMAT_TYPE_UNSIGNED && - desc->channel[chan].type != UTIL_FORMAT_TYPE_SIGNED && - desc->channel[chan].type != UTIL_FORMAT_TYPE_VOID) - return FALSE; - if(desc->channel[chan].size != 8) - return FALSE; - } - - return TRUE; -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_format_soa.c b/src/gallium/drivers/llvmpipe/lp_bld_format_soa.c deleted file mode 100644 index 64151d169d..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_format_soa.c +++ /dev/null @@ -1,149 +0,0 @@ -/************************************************************************** - * - * 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_format.h" - -#include "lp_bld_type.h" -#include "lp_bld_const.h" -#include "lp_bld_conv.h" -#include "lp_bld_format.h" - - -static LLVMValueRef -lp_build_format_swizzle_chan_soa(struct lp_type type, - const LLVMValueRef *unswizzled, - enum util_format_swizzle swizzle) -{ - switch (swizzle) { - case UTIL_FORMAT_SWIZZLE_X: - case UTIL_FORMAT_SWIZZLE_Y: - case UTIL_FORMAT_SWIZZLE_Z: - case UTIL_FORMAT_SWIZZLE_W: - return unswizzled[swizzle]; - case UTIL_FORMAT_SWIZZLE_0: - return lp_build_zero(type); - case UTIL_FORMAT_SWIZZLE_1: - return lp_build_one(type); - case UTIL_FORMAT_SWIZZLE_NONE: - return lp_build_undef(type); - default: - assert(0); - return lp_build_undef(type); - } -} - - -void -lp_build_format_swizzle_soa(const struct util_format_description *format_desc, - struct lp_type type, - const LLVMValueRef *unswizzled, - LLVMValueRef *swizzled) -{ - if(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) { - enum util_format_swizzle swizzle = format_desc->swizzle[0]; - LLVMValueRef depth = lp_build_format_swizzle_chan_soa(type, unswizzled, swizzle); - swizzled[2] = swizzled[1] = swizzled[0] = depth; - swizzled[3] = lp_build_one(type); - } - else { - unsigned chan; - for (chan = 0; chan < 4; ++chan) { - enum util_format_swizzle swizzle = format_desc->swizzle[chan]; - swizzled[chan] = lp_build_format_swizzle_chan_soa(type, unswizzled, swizzle); - } - } -} - - -void -lp_build_unpack_rgba_soa(LLVMBuilderRef builder, - const struct util_format_description *format_desc, - struct lp_type type, - LLVMValueRef packed, - LLVMValueRef *rgba) -{ - LLVMValueRef inputs[4]; - unsigned start; - unsigned chan; - - /* FIXME: Support more formats */ - assert(format_desc->layout == UTIL_FORMAT_LAYOUT_ARITH || - (format_desc->layout == UTIL_FORMAT_LAYOUT_ARRAY && - format_desc->block.bits == format_desc->channel[0].size)); - assert(format_desc->block.width == 1); - assert(format_desc->block.height == 1); - assert(format_desc->block.bits <= 32); - - /* Decode the input vector components */ - start = 0; - for (chan = 0; chan < 4; ++chan) { - unsigned width = format_desc->channel[chan].size; - unsigned stop = start + width; - LLVMValueRef input; - - input = packed; - - switch(format_desc->channel[chan].type) { - case UTIL_FORMAT_TYPE_VOID: - input = NULL; - break; - - case UTIL_FORMAT_TYPE_UNSIGNED: - if(type.floating) { - if(start) - input = LLVMBuildLShr(builder, input, lp_build_int_const_scalar(type, start), ""); - if(stop < format_desc->block.bits) { - unsigned mask = ((unsigned long long)1 << width) - 1; - input = LLVMBuildAnd(builder, input, lp_build_int_const_scalar(type, mask), ""); - } - - if(format_desc->channel[chan].normalized) - input = lp_build_unsigned_norm_to_float(builder, width, type, input); - else - input = LLVMBuildFPToSI(builder, input, lp_build_vec_type(type), ""); - } - else { - /* FIXME */ - assert(0); - input = lp_build_undef(type); - } - break; - - default: - /* fall through */ - input = lp_build_undef(type); - break; - } - - inputs[chan] = input; - - start = stop; - } - - lp_build_format_swizzle_soa(format_desc, type, inputs, rgba); -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_interp.c b/src/gallium/drivers/llvmpipe/lp_bld_interp.c deleted file mode 100644 index 49dab8ab61..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_interp.c +++ /dev/null @@ -1,351 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * Copyright 2007-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. - * - **************************************************************************/ - -/** - * @file - * Position and shader input interpolation. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - -#include "pipe/p_shader_tokens.h" -#include "util/u_debug.h" -#include "util/u_memory.h" -#include "util/u_math.h" -#include "tgsi/tgsi_parse.h" -#include "lp_bld_debug.h" -#include "lp_bld_const.h" -#include "lp_bld_arit.h" -#include "lp_bld_swizzle.h" -#include "lp_bld_interp.h" - - -static void -attrib_name(LLVMValueRef val, unsigned attrib, unsigned chan, const char *suffix) -{ - if(attrib == 0) - lp_build_name(val, "pos.%c%s", "xyzw"[chan], suffix); - else - lp_build_name(val, "input%u.%c%s", attrib - 1, "xyzw"[chan], suffix); -} - - -static void -coeffs_init(struct lp_build_interp_soa_context *bld, - LLVMValueRef a0_ptr, - LLVMValueRef dadx_ptr, - LLVMValueRef dady_ptr) -{ - LLVMBuilderRef builder = bld->base.builder; - unsigned attrib; - unsigned chan; - - for(attrib = 0; attrib < bld->num_attribs; ++attrib) { - unsigned mask = bld->mask[attrib]; - unsigned mode = bld->mode[attrib]; - for(chan = 0; chan < NUM_CHANNELS; ++chan) { - if(mask & (1 << chan)) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), attrib*NUM_CHANNELS + chan, 0); - LLVMValueRef a0 = NULL; - LLVMValueRef dadx = NULL; - LLVMValueRef dady = NULL; - - switch( mode ) { - case TGSI_INTERPOLATE_PERSPECTIVE: - /* fall-through */ - - case TGSI_INTERPOLATE_LINEAR: - dadx = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dadx_ptr, &index, 1, ""), ""); - dady = LLVMBuildLoad(builder, LLVMBuildGEP(builder, dady_ptr, &index, 1, ""), ""); - dadx = lp_build_broadcast_scalar(&bld->base, dadx); - dady = lp_build_broadcast_scalar(&bld->base, dady); - attrib_name(dadx, attrib, chan, ".dadx"); - attrib_name(dady, attrib, chan, ".dady"); - /* fall-through */ - - case TGSI_INTERPOLATE_CONSTANT: - a0 = LLVMBuildLoad(builder, LLVMBuildGEP(builder, a0_ptr, &index, 1, ""), ""); - a0 = lp_build_broadcast_scalar(&bld->base, a0); - attrib_name(a0, attrib, chan, ".dady"); - break; - - default: - assert(0); - break; - } - - bld->a0 [attrib][chan] = a0; - bld->dadx[attrib][chan] = dadx; - bld->dady[attrib][chan] = dady; - } - } - } -} - - -/** - * Multiply the dadx and dady with the xstep and ystep respectively. - */ -static void -coeffs_update(struct lp_build_interp_soa_context *bld) -{ - unsigned attrib; - unsigned chan; - - for(attrib = 0; attrib < bld->num_attribs; ++attrib) { - unsigned mask = bld->mask[attrib]; - unsigned mode = bld->mode[attrib]; - if (mode != TGSI_INTERPOLATE_CONSTANT) { - for(chan = 0; chan < NUM_CHANNELS; ++chan) { - if(mask & (1 << chan)) { - bld->dadx[attrib][chan] = lp_build_mul_imm(&bld->base, bld->dadx[attrib][chan], bld->xstep); - bld->dady[attrib][chan] = lp_build_mul_imm(&bld->base, bld->dady[attrib][chan], bld->ystep); - } - } - } - } -} - - -static void -attribs_init(struct lp_build_interp_soa_context *bld) -{ - LLVMValueRef x = bld->pos[0]; - LLVMValueRef y = bld->pos[1]; - LLVMValueRef oow = NULL; - unsigned attrib; - unsigned chan; - - for(attrib = 0; attrib < bld->num_attribs; ++attrib) { - unsigned mask = bld->mask[attrib]; - unsigned mode = bld->mode[attrib]; - for(chan = 0; chan < NUM_CHANNELS; ++chan) { - if(mask & (1 << chan)) { - LLVMValueRef a0 = bld->a0 [attrib][chan]; - LLVMValueRef dadx = bld->dadx[attrib][chan]; - LLVMValueRef dady = bld->dady[attrib][chan]; - LLVMValueRef res; - - res = a0; - - if (mode != TGSI_INTERPOLATE_CONSTANT) { - res = lp_build_add(&bld->base, res, lp_build_mul(&bld->base, x, dadx)); - res = lp_build_add(&bld->base, res, lp_build_mul(&bld->base, y, dady)); - } - - /* Keep the value of the attribue before perspective divide for faster updates */ - bld->attribs_pre[attrib][chan] = res; - - if (mode == TGSI_INTERPOLATE_PERSPECTIVE) { - LLVMValueRef w = bld->pos[3]; - assert(attrib != 0); - if(!oow) - oow = lp_build_rcp(&bld->base, w); - res = lp_build_mul(&bld->base, res, oow); - } - - attrib_name(res, attrib, chan, ""); - - bld->attribs[attrib][chan] = res; - } - } - } -} - - -static void -attribs_update(struct lp_build_interp_soa_context *bld) -{ - LLVMValueRef oow = NULL; - unsigned attrib; - unsigned chan; - - for(attrib = 0; attrib < bld->num_attribs; ++attrib) { - unsigned mask = bld->mask[attrib]; - unsigned mode = bld->mode[attrib]; - - if (mode != TGSI_INTERPOLATE_CONSTANT) { - for(chan = 0; chan < NUM_CHANNELS; ++chan) { - if(mask & (1 << chan)) { - LLVMValueRef dadx = bld->dadx[attrib][chan]; - LLVMValueRef dady = bld->dady[attrib][chan]; - LLVMValueRef res; - - res = bld->attribs_pre[attrib][chan]; - - if(bld->xstep) - res = lp_build_add(&bld->base, res, dadx); - - if(bld->ystep) - res = lp_build_add(&bld->base, res, dady); - - bld->attribs_pre[attrib][chan] = res; - - if (mode == TGSI_INTERPOLATE_PERSPECTIVE) { - LLVMValueRef w = bld->pos[3]; - assert(attrib != 0); - if(!oow) - oow = lp_build_rcp(&bld->base, w); - res = lp_build_mul(&bld->base, res, oow); - } - - attrib_name(res, attrib, chan, ""); - - bld->attribs[attrib][chan] = res; - } - } - } - } -} - - -/** - * Generate the position vectors. - * - * Parameter x0, y0 are the integer values with the quad upper left coordinates. - */ -static void -pos_init(struct lp_build_interp_soa_context *bld, - LLVMValueRef x0, - LLVMValueRef y0) -{ - lp_build_name(x0, "pos.x"); - lp_build_name(y0, "pos.y"); - - bld->attribs[0][0] = x0; - bld->attribs[0][1] = y0; -} - - -static void -pos_update(struct lp_build_interp_soa_context *bld) -{ - LLVMValueRef x = bld->attribs[0][0]; - LLVMValueRef y = bld->attribs[0][1]; - - if(bld->xstep) - x = lp_build_add(&bld->base, x, lp_build_const_scalar(bld->base.type, bld->xstep)); - - if(bld->ystep) - y = lp_build_add(&bld->base, y, lp_build_const_scalar(bld->base.type, bld->ystep)); - - lp_build_name(x, "pos.x"); - lp_build_name(y, "pos.y"); - - bld->attribs[0][0] = x; - bld->attribs[0][1] = y; -} - - -void -lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld, - const struct tgsi_token *tokens, - LLVMBuilderRef builder, - struct lp_type type, - LLVMValueRef a0_ptr, - LLVMValueRef dadx_ptr, - LLVMValueRef dady_ptr, - LLVMValueRef x0, - LLVMValueRef y0, - int xstep, - int ystep) -{ - struct tgsi_parse_context parse; - struct tgsi_full_declaration *decl; - - memset(bld, 0, sizeof *bld); - - lp_build_context_init(&bld->base, builder, type); - - /* For convenience */ - bld->pos = bld->attribs[0]; - bld->inputs = (const LLVMValueRef (*)[NUM_CHANNELS]) bld->attribs[1]; - - /* Position */ - bld->num_attribs = 1; - bld->mask[0] = TGSI_WRITEMASK_ZW; - bld->mode[0] = TGSI_INTERPOLATE_LINEAR; - - /* Inputs */ - tgsi_parse_init( &parse, tokens ); - while( !tgsi_parse_end_of_tokens( &parse ) ) { - tgsi_parse_token( &parse ); - - switch( parse.FullToken.Token.Type ) { - case TGSI_TOKEN_TYPE_DECLARATION: - decl = &parse.FullToken.FullDeclaration; - if( decl->Declaration.File == TGSI_FILE_INPUT ) { - unsigned first, last, mask; - unsigned attrib; - - first = decl->Range.First; - last = decl->Range.Last; - mask = decl->Declaration.UsageMask; - - for( attrib = first; attrib <= last; ++attrib ) { - bld->mask[1 + attrib] = mask; - bld->mode[1 + attrib] = decl->Declaration.Interpolate; - } - - bld->num_attribs = MAX2(bld->num_attribs, 1 + last + 1); - } - break; - - case TGSI_TOKEN_TYPE_INSTRUCTION: - case TGSI_TOKEN_TYPE_IMMEDIATE: - break; - - default: - assert( 0 ); - } - } - tgsi_parse_free( &parse ); - - coeffs_init(bld, a0_ptr, dadx_ptr, dady_ptr); - - pos_init(bld, x0, y0); - - attribs_init(bld); - - bld->xstep = xstep; - bld->ystep = ystep; - - coeffs_update(bld); -} - - -/** - * Advance the position and inputs with the xstep and ystep. - */ -void -lp_build_interp_soa_update(struct lp_build_interp_soa_context *bld) -{ - pos_update(bld); - - attribs_update(bld); -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_interp.h b/src/gallium/drivers/llvmpipe/lp_bld_interp.h deleted file mode 100644 index 9c57a10879..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_interp.h +++ /dev/null @@ -1,99 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Position and shader input interpolation. - * - * Special attention is given to the interpolation of side by side quads. - * Multiplications are made only for the first quad. Interpolation of - * inputs for posterior quads are done exclusively with additions, and - * perspective divide if necessary. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - -#ifndef LP_BLD_INTERP_H -#define LP_BLD_INTERP_H - - -#include <llvm-c/Core.h> - -#include "tgsi/tgsi_exec.h" - -#include "lp_bld_type.h" - - -struct tgsi_token; - - -struct lp_build_interp_soa_context -{ - struct lp_build_context base; - - unsigned num_attribs; - unsigned mask[1 + PIPE_MAX_SHADER_INPUTS]; - unsigned mode[1 + PIPE_MAX_SHADER_INPUTS]; - - LLVMValueRef a0 [1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; - LLVMValueRef dadx[1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; - LLVMValueRef dady[1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; - - int xstep; - int ystep; - - /* Attribute values before perspective divide */ - LLVMValueRef attribs_pre[1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; - - LLVMValueRef attribs[1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; - - /* - * Convenience pointers. Callers may access this one. - */ - const LLVMValueRef *pos; - const LLVMValueRef (*inputs)[NUM_CHANNELS]; -}; - - -void -lp_build_interp_soa_init(struct lp_build_interp_soa_context *bld, - const struct tgsi_token *tokens, - LLVMBuilderRef builder, - struct lp_type type, - LLVMValueRef a0_ptr, - LLVMValueRef dadx_ptr, - LLVMValueRef dady_ptr, - LLVMValueRef x0, - LLVMValueRef y0, - int xstep, - int ystep); - -void -lp_build_interp_soa_update(struct lp_build_interp_soa_context *bld); - - -#endif /* LP_BLD_INTERP_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_bld_intr.c b/src/gallium/drivers/llvmpipe/lp_bld_intr.c deleted file mode 100644 index 9895749d56..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_intr.c +++ /dev/null @@ -1,192 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -/** - * @file - * Helpers for emiting intrinsic calls. - * - * LLVM vanilla IR doesn't represent all basic arithmetic operations we care - * about, and it is often necessary to resort target-specific intrinsics for - * performance, convenience. - * - * Ideally we would like to stay away from target specific intrinsics and - * move all the instruction selection logic into upstream LLVM where it belongs. - * - * These functions are also used for calling C functions provided by us from - * generated LLVM code. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#include "util/u_debug.h" - -#include "lp_bld_intr.h" - - -LLVMValueRef -lp_declare_intrinsic(LLVMModuleRef module, - const char *name, - LLVMTypeRef ret_type, - LLVMTypeRef *arg_types, - unsigned num_args) -{ - LLVMTypeRef function_type; - LLVMValueRef function; - - assert(!LLVMGetNamedFunction(module, name)); - - function_type = LLVMFunctionType(ret_type, arg_types, num_args, 0); - function = LLVMAddFunction(module, name, function_type); - - LLVMSetFunctionCallConv(function, LLVMCCallConv); - LLVMSetLinkage(function, LLVMExternalLinkage); - - assert(LLVMIsDeclaration(function)); - - if(name[0] == 'l' && - name[1] == 'l' && - name[2] == 'v' && - name[3] == 'm' && - name[4] == '.') - assert(LLVMGetIntrinsicID(function)); - - return function; -} - - -LLVMValueRef -lp_build_intrinsic(LLVMBuilderRef builder, - const char *name, - LLVMTypeRef ret_type, - LLVMValueRef *args, - unsigned num_args) -{ - LLVMModuleRef module = LLVMGetGlobalParent(LLVMGetBasicBlockParent(LLVMGetInsertBlock(builder))); - LLVMValueRef function; - - function = LLVMGetNamedFunction(module, name); - if(!function) { - LLVMTypeRef arg_types[LP_MAX_FUNC_ARGS]; - unsigned i; - - assert(num_args <= LP_MAX_FUNC_ARGS); - - for(i = 0; i < num_args; ++i) { - assert(args[i]); - arg_types[i] = LLVMTypeOf(args[i]); - } - - function = lp_declare_intrinsic(module, name, ret_type, arg_types, num_args); - } - - return LLVMBuildCall(builder, function, args, num_args, ""); -} - - -LLVMValueRef -lp_build_intrinsic_unary(LLVMBuilderRef builder, - const char *name, - LLVMTypeRef ret_type, - LLVMValueRef a) -{ - return lp_build_intrinsic(builder, name, ret_type, &a, 1); -} - - -LLVMValueRef -lp_build_intrinsic_binary(LLVMBuilderRef builder, - const char *name, - LLVMTypeRef ret_type, - LLVMValueRef a, - LLVMValueRef b) -{ - LLVMValueRef args[2]; - - args[0] = a; - args[1] = b; - - return lp_build_intrinsic(builder, name, ret_type, args, 2); -} - - -LLVMValueRef -lp_build_intrinsic_map(LLVMBuilderRef builder, - const char *name, - LLVMTypeRef ret_type, - LLVMValueRef *args, - unsigned num_args) -{ - LLVMTypeRef ret_elem_type = LLVMGetElementType(ret_type); - unsigned n = LLVMGetVectorSize(ret_type); - unsigned i, j; - LLVMValueRef res; - - assert(num_args <= LP_MAX_FUNC_ARGS); - - res = LLVMGetUndef(ret_type); - for(i = 0; i < n; ++i) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); - LLVMValueRef arg_elems[LP_MAX_FUNC_ARGS]; - LLVMValueRef res_elem; - for(j = 0; j < num_args; ++j) - arg_elems[j] = LLVMBuildExtractElement(builder, args[j], index, ""); - res_elem = lp_build_intrinsic(builder, name, ret_elem_type, arg_elems, num_args); - res = LLVMBuildInsertElement(builder, res, res_elem, index, ""); - } - - return res; -} - - -LLVMValueRef -lp_build_intrinsic_map_unary(LLVMBuilderRef builder, - const char *name, - LLVMTypeRef ret_type, - LLVMValueRef a) -{ - return lp_build_intrinsic_map(builder, name, ret_type, &a, 1); -} - - -LLVMValueRef -lp_build_intrinsic_map_binary(LLVMBuilderRef builder, - const char *name, - LLVMTypeRef ret_type, - LLVMValueRef a, - LLVMValueRef b) -{ - LLVMValueRef args[2]; - - args[0] = a; - args[1] = b; - - return lp_build_intrinsic_map(builder, name, ret_type, args, 2); -} - - diff --git a/src/gallium/drivers/llvmpipe/lp_bld_intr.h b/src/gallium/drivers/llvmpipe/lp_bld_intr.h deleted file mode 100644 index f813f27074..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_intr.h +++ /dev/null @@ -1,102 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Helper functions for calling intrinsics. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#ifndef LP_BLD_INTR_H -#define LP_BLD_INTR_H - - -#include <llvm-c/Core.h> - - -/** - * Max number of arguments in an intrinsic. - */ -#define LP_MAX_FUNC_ARGS 32 - - -LLVMValueRef -lp_declare_intrinsic(LLVMModuleRef module, - const char *name, - LLVMTypeRef ret_type, - LLVMTypeRef *arg_types, - unsigned num_args); - -LLVMValueRef -lp_build_intrinsic(LLVMBuilderRef builder, - const char *name, - LLVMTypeRef ret_type, - LLVMValueRef *args, - unsigned num_args); - - -LLVMValueRef -lp_build_intrinsic_unary(LLVMBuilderRef builder, - const char *name, - LLVMTypeRef ret_type, - LLVMValueRef a); - - -LLVMValueRef -lp_build_intrinsic_binary(LLVMBuilderRef builder, - const char *name, - LLVMTypeRef ret_type, - LLVMValueRef a, - LLVMValueRef b); - - -LLVMValueRef -lp_build_intrinsic_map(LLVMBuilderRef builder, - const char *name, - LLVMTypeRef ret_type, - LLVMValueRef *args, - unsigned num_args); - - -LLVMValueRef -lp_build_intrinsic_map_unary(LLVMBuilderRef builder, - const char *name, - LLVMTypeRef ret_type, - LLVMValueRef a); - - -LLVMValueRef -lp_build_intrinsic_map_binary(LLVMBuilderRef builder, - const char *name, - LLVMTypeRef ret_type, - LLVMValueRef a, - LLVMValueRef b); - - -#endif /* !LP_BLD_INTR_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_bld_logic.c b/src/gallium/drivers/llvmpipe/lp_bld_logic.c deleted file mode 100644 index db22a8028a..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_logic.c +++ /dev/null @@ -1,396 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Helper functions for logical operations. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#include "util/u_cpu_detect.h" - -#include "lp_bld_type.h" -#include "lp_bld_const.h" -#include "lp_bld_intr.h" -#include "lp_bld_logic.h" - - -LLVMValueRef -lp_build_cmp(struct lp_build_context *bld, - unsigned func, - LLVMValueRef a, - LLVMValueRef b) -{ - const struct lp_type type = bld->type; - LLVMTypeRef vec_type = lp_build_vec_type(type); - LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); - LLVMValueRef zeros = LLVMConstNull(int_vec_type); - LLVMValueRef ones = LLVMConstAllOnes(int_vec_type); - LLVMValueRef cond; - LLVMValueRef res; - unsigned i; - - if(func == PIPE_FUNC_NEVER) - return zeros; - if(func == PIPE_FUNC_ALWAYS) - return ones; - - /* TODO: optimize the constant case */ - - /* XXX: It is not clear if we should use the ordered or unordered operators */ - -#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64) - if(type.width * type.length == 128) { - if(type.floating && util_cpu_caps.has_sse) { - LLVMValueRef args[3]; - unsigned cc; - boolean swap; - - swap = FALSE; - switch(func) { - case PIPE_FUNC_EQUAL: - cc = 0; - break; - case PIPE_FUNC_NOTEQUAL: - cc = 4; - break; - case PIPE_FUNC_LESS: - cc = 1; - break; - case PIPE_FUNC_LEQUAL: - cc = 2; - break; - case PIPE_FUNC_GREATER: - cc = 1; - swap = TRUE; - break; - case PIPE_FUNC_GEQUAL: - cc = 2; - swap = TRUE; - break; - default: - assert(0); - return bld->undef; - } - - if(swap) { - args[0] = b; - args[1] = a; - } - else { - args[0] = a; - args[1] = b; - } - - args[2] = LLVMConstInt(LLVMInt8Type(), cc, 0); - res = lp_build_intrinsic(bld->builder, - "llvm.x86.sse.cmp.ps", - vec_type, - args, 3); - res = LLVMBuildBitCast(bld->builder, res, int_vec_type, ""); - return res; - } - else if(util_cpu_caps.has_sse2) { - static const struct { - unsigned swap:1; - unsigned eq:1; - unsigned gt:1; - unsigned not:1; - } table[] = { - {0, 0, 0, 1}, /* PIPE_FUNC_NEVER */ - {1, 0, 1, 0}, /* PIPE_FUNC_LESS */ - {0, 1, 0, 0}, /* PIPE_FUNC_EQUAL */ - {0, 0, 1, 1}, /* PIPE_FUNC_LEQUAL */ - {0, 0, 1, 0}, /* PIPE_FUNC_GREATER */ - {0, 1, 0, 1}, /* PIPE_FUNC_NOTEQUAL */ - {1, 0, 1, 1}, /* PIPE_FUNC_GEQUAL */ - {0, 0, 0, 0} /* PIPE_FUNC_ALWAYS */ - }; - const char *pcmpeq; - const char *pcmpgt; - LLVMValueRef args[2]; - LLVMValueRef res; - - switch (type.width) { - case 8: - pcmpeq = "llvm.x86.sse2.pcmpeq.b"; - pcmpgt = "llvm.x86.sse2.pcmpgt.b"; - break; - case 16: - pcmpeq = "llvm.x86.sse2.pcmpeq.w"; - pcmpgt = "llvm.x86.sse2.pcmpgt.w"; - break; - case 32: - pcmpeq = "llvm.x86.sse2.pcmpeq.d"; - pcmpgt = "llvm.x86.sse2.pcmpgt.d"; - break; - default: - assert(0); - return bld->undef; - } - - /* There are no signed byte and unsigned word/dword comparison - * instructions. So flip the sign bit so that the results match. - */ - if(table[func].gt && - ((type.width == 8 && type.sign) || - (type.width != 8 && !type.sign))) { - LLVMValueRef msb = lp_build_int_const_scalar(type, (unsigned long long)1 << (type.width - 1)); - a = LLVMBuildXor(bld->builder, a, msb, ""); - b = LLVMBuildXor(bld->builder, b, msb, ""); - } - - if(table[func].swap) { - args[0] = b; - args[1] = a; - } - else { - args[0] = a; - args[1] = b; - } - - if(table[func].eq) - res = lp_build_intrinsic(bld->builder, pcmpeq, vec_type, args, 2); - else if (table[func].gt) - res = lp_build_intrinsic(bld->builder, pcmpgt, vec_type, args, 2); - else - res = LLVMConstNull(vec_type); - - if(table[func].not) - res = LLVMBuildNot(bld->builder, res, ""); - - return res; - } - } -#endif - - if(type.floating) { - LLVMRealPredicate op; - switch(func) { - case PIPE_FUNC_NEVER: - op = LLVMRealPredicateFalse; - break; - case PIPE_FUNC_ALWAYS: - op = LLVMRealPredicateTrue; - break; - case PIPE_FUNC_EQUAL: - op = LLVMRealUEQ; - break; - case PIPE_FUNC_NOTEQUAL: - op = LLVMRealUNE; - break; - case PIPE_FUNC_LESS: - op = LLVMRealULT; - break; - case PIPE_FUNC_LEQUAL: - op = LLVMRealULE; - break; - case PIPE_FUNC_GREATER: - op = LLVMRealUGT; - break; - case PIPE_FUNC_GEQUAL: - op = LLVMRealUGE; - break; - default: - assert(0); - return bld->undef; - } - -#if 0 - /* XXX: Although valid IR, no LLVM target currently support this */ - cond = LLVMBuildFCmp(bld->builder, op, a, b, ""); - res = LLVMBuildSelect(bld->builder, cond, ones, zeros, ""); -#else - debug_printf("%s: warning: using slow element-wise vector comparison\n", - __FUNCTION__); - res = LLVMGetUndef(int_vec_type); - for(i = 0; i < type.length; ++i) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); - cond = LLVMBuildFCmp(bld->builder, op, - LLVMBuildExtractElement(bld->builder, a, index, ""), - LLVMBuildExtractElement(bld->builder, b, index, ""), - ""); - cond = LLVMBuildSelect(bld->builder, cond, - LLVMConstExtractElement(ones, index), - LLVMConstExtractElement(zeros, index), - ""); - res = LLVMBuildInsertElement(bld->builder, res, cond, index, ""); - } -#endif - } - else { - LLVMIntPredicate op; - switch(func) { - case PIPE_FUNC_EQUAL: - op = LLVMIntEQ; - break; - case PIPE_FUNC_NOTEQUAL: - op = LLVMIntNE; - break; - case PIPE_FUNC_LESS: - op = type.sign ? LLVMIntSLT : LLVMIntULT; - break; - case PIPE_FUNC_LEQUAL: - op = type.sign ? LLVMIntSLE : LLVMIntULE; - break; - case PIPE_FUNC_GREATER: - op = type.sign ? LLVMIntSGT : LLVMIntUGT; - break; - case PIPE_FUNC_GEQUAL: - op = type.sign ? LLVMIntSGE : LLVMIntUGE; - break; - default: - assert(0); - return bld->undef; - } - -#if 0 - /* XXX: Although valid IR, no LLVM target currently support this */ - cond = LLVMBuildICmp(bld->builder, op, a, b, ""); - res = LLVMBuildSelect(bld->builder, cond, ones, zeros, ""); -#else - debug_printf("%s: warning: using slow element-wise vector comparison\n", - __FUNCTION__); - res = LLVMGetUndef(int_vec_type); - for(i = 0; i < type.length; ++i) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); - cond = LLVMBuildICmp(bld->builder, op, - LLVMBuildExtractElement(bld->builder, a, index, ""), - LLVMBuildExtractElement(bld->builder, b, index, ""), - ""); - cond = LLVMBuildSelect(bld->builder, cond, - LLVMConstExtractElement(ones, index), - LLVMConstExtractElement(zeros, index), - ""); - res = LLVMBuildInsertElement(bld->builder, res, cond, index, ""); - } -#endif - } - - return res; -} - - -LLVMValueRef -lp_build_select(struct lp_build_context *bld, - LLVMValueRef mask, - LLVMValueRef a, - LLVMValueRef b) -{ - struct lp_type type = bld->type; - LLVMValueRef res; - - if(a == b) - return a; - - if(type.floating) { - LLVMTypeRef int_vec_type = lp_build_int_vec_type(type); - a = LLVMBuildBitCast(bld->builder, a, int_vec_type, ""); - b = LLVMBuildBitCast(bld->builder, b, int_vec_type, ""); - } - - a = LLVMBuildAnd(bld->builder, a, mask, ""); - - /* This often gets translated to PANDN, but sometimes the NOT is - * pre-computed and stored in another constant. The best strategy depends - * on available registers, so it is not a big deal -- hopefully LLVM does - * the right decision attending the rest of the program. - */ - b = LLVMBuildAnd(bld->builder, b, LLVMBuildNot(bld->builder, mask, ""), ""); - - res = LLVMBuildOr(bld->builder, a, b, ""); - - if(type.floating) { - LLVMTypeRef vec_type = lp_build_vec_type(type); - res = LLVMBuildBitCast(bld->builder, res, vec_type, ""); - } - - return res; -} - - -LLVMValueRef -lp_build_select_aos(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b, - const boolean cond[4]) -{ - const struct lp_type type = bld->type; - const unsigned n = type.length; - unsigned i, j; - - if(a == b) - return a; - if(cond[0] && cond[1] && cond[2] && cond[3]) - return a; - if(!cond[0] && !cond[1] && !cond[2] && !cond[3]) - return b; - if(a == bld->undef || b == bld->undef) - return bld->undef; - - /* - * There are three major ways of accomplishing this: - * - with a shuffle, - * - with a select, - * - or with a bit mask. - * - * Select isn't supported for vector types yet. - * The flip between these is empirical and might need to be. - */ - if (n <= 4) { - /* - * Shuffle. - */ - LLVMTypeRef elem_type = LLVMInt32Type(); - LLVMValueRef shuffles[LP_MAX_VECTOR_LENGTH]; - - for(j = 0; j < n; j += 4) - for(i = 0; i < 4; ++i) - shuffles[j + i] = LLVMConstInt(elem_type, (cond[i] ? 0 : n) + j + i, 0); - - return LLVMBuildShuffleVector(bld->builder, a, b, LLVMConstVector(shuffles, n), ""); - } - else { -#if 0 - /* XXX: Unfortunately select of vectors do not work */ - /* Use a select */ - LLVMTypeRef elem_type = LLVMInt1Type(); - LLVMValueRef cond[LP_MAX_VECTOR_LENGTH]; - - for(j = 0; j < n; j += 4) - for(i = 0; i < 4; ++i) - cond[j + i] = LLVMConstInt(elem_type, cond[i] ? 1 : 0, 0); - - return LLVMBuildSelect(bld->builder, LLVMConstVector(cond, n), a, b, ""); -#else - LLVMValueRef mask = lp_build_const_mask_aos(type, cond); - return lp_build_select(bld, mask, a, b); -#endif - } -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_misc.cpp b/src/gallium/drivers/llvmpipe/lp_bld_misc.cpp deleted file mode 100644 index 6e79438ead..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_misc.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/************************************************************************** - * - * 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_config.h" - -#include "lp_bld_misc.h" - - -#ifndef LLVM_NATIVE_ARCH - -namespace llvm { - extern void LinkInJIT(); -} - - -void -LLVMLinkInJIT(void) -{ - llvm::LinkInJIT(); -} - - -extern "C" int X86TargetMachineModule; - - -int -LLVMInitializeNativeTarget(void) -{ -#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64) - X86TargetMachineModule = 1; -#endif - return 0; -} - - -#endif - - -/* - * Hack to allow the linking of release LLVM static libraries on a debug build. - * - * See also: - * - http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/7234ea2b-0042-42ed-b4e2-5d8644dfb57d - */ -#if defined(_MSC_VER) && defined(_DEBUG) -#include <crtdefs.h> -extern "C" { - _CRTIMP void __cdecl _invalid_parameter_noinfo(void) {} -} -#endif diff --git a/src/gallium/drivers/llvmpipe/lp_bld_pack.c b/src/gallium/drivers/llvmpipe/lp_bld_pack.c deleted file mode 100644 index bc360ad77a..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_pack.c +++ /dev/null @@ -1,418 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -/** - * @file - * Helper functions for packing/unpacking. - * - * Pack/unpacking is necessary for conversion between types of different - * bit width. - * - * They are also commonly used when an computation needs higher - * precision for the intermediate values. For example, if one needs the - * function: - * - * c = compute(a, b); - * - * to use more precision for intermediate results then one should implement it - * as: - * - * LLVMValueRef - * compute(LLVMBuilderRef builder struct lp_type type, LLVMValueRef a, LLVMValueRef b) - * { - * struct lp_type wide_type = lp_wider_type(type); - * LLVMValueRef al, ah, bl, bh, cl, ch, c; - * - * lp_build_unpack2(builder, type, wide_type, a, &al, &ah); - * lp_build_unpack2(builder, type, wide_type, b, &bl, &bh); - * - * cl = compute_half(al, bl); - * ch = compute_half(ah, bh); - * - * c = lp_build_pack2(bld->builder, wide_type, type, cl, ch); - * - * return c; - * } - * - * where compute_half() would do the computation for half the elements with - * twice the precision. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#include "util/u_debug.h" -#include "util/u_math.h" -#include "util/u_cpu_detect.h" - -#include "lp_bld_type.h" -#include "lp_bld_const.h" -#include "lp_bld_intr.h" -#include "lp_bld_arit.h" -#include "lp_bld_pack.h" - - -/** - * Build shuffle vectors that match PUNPCKLxx and PUNPCKHxx instructions. - */ -static LLVMValueRef -lp_build_const_unpack_shuffle(unsigned n, unsigned lo_hi) -{ - LLVMValueRef elems[LP_MAX_VECTOR_LENGTH]; - unsigned i, j; - - assert(n <= LP_MAX_VECTOR_LENGTH); - assert(lo_hi < 2); - - /* TODO: cache results in a static table */ - - for(i = 0, j = lo_hi*n/2; i < n; i += 2, ++j) { - elems[i + 0] = LLVMConstInt(LLVMInt32Type(), 0 + j, 0); - elems[i + 1] = LLVMConstInt(LLVMInt32Type(), n + j, 0); - } - - return LLVMConstVector(elems, n); -} - - -/** - * Build shuffle vectors that match PACKxx instructions. - */ -static LLVMValueRef -lp_build_const_pack_shuffle(unsigned n) -{ - LLVMValueRef elems[LP_MAX_VECTOR_LENGTH]; - unsigned i; - - assert(n <= LP_MAX_VECTOR_LENGTH); - - /* TODO: cache results in a static table */ - - for(i = 0; i < n; ++i) - elems[i] = LLVMConstInt(LLVMInt32Type(), 2*i, 0); - - return LLVMConstVector(elems, n); -} - - -/** - * Interleave vector elements. - * - * Matches the PUNPCKLxx and PUNPCKHxx SSE instructions. - */ -LLVMValueRef -lp_build_interleave2(LLVMBuilderRef builder, - struct lp_type type, - LLVMValueRef a, - LLVMValueRef b, - unsigned lo_hi) -{ - LLVMValueRef shuffle; - - shuffle = lp_build_const_unpack_shuffle(type.length, lo_hi); - - return LLVMBuildShuffleVector(builder, a, b, shuffle, ""); -} - - -/** - * Double the bit width. - * - * This will only change the number of bits the values are represented, not the - * values themselves. - */ -void -lp_build_unpack2(LLVMBuilderRef builder, - struct lp_type src_type, - struct lp_type dst_type, - LLVMValueRef src, - LLVMValueRef *dst_lo, - LLVMValueRef *dst_hi) -{ - LLVMValueRef msb; - LLVMTypeRef dst_vec_type; - - assert(!src_type.floating); - assert(!dst_type.floating); - assert(dst_type.width == src_type.width * 2); - assert(dst_type.length * 2 == src_type.length); - - if(dst_type.sign && src_type.sign) { - /* Replicate the sign bit in the most significant bits */ - msb = LLVMBuildAShr(builder, src, lp_build_int_const_scalar(src_type, src_type.width - 1), ""); - } - else - /* Most significant bits always zero */ - msb = lp_build_zero(src_type); - - /* Interleave bits */ - if(util_cpu_caps.little_endian) { - *dst_lo = lp_build_interleave2(builder, src_type, src, msb, 0); - *dst_hi = lp_build_interleave2(builder, src_type, src, msb, 1); - } - else { - *dst_lo = lp_build_interleave2(builder, src_type, msb, src, 0); - *dst_hi = lp_build_interleave2(builder, src_type, msb, src, 1); - } - - /* Cast the result into the new type (twice as wide) */ - - dst_vec_type = lp_build_vec_type(dst_type); - - *dst_lo = LLVMBuildBitCast(builder, *dst_lo, dst_vec_type, ""); - *dst_hi = LLVMBuildBitCast(builder, *dst_hi, dst_vec_type, ""); -} - - -/** - * Expand the bit width. - * - * This will only change the number of bits the values are represented, not the - * values themselves. - */ -void -lp_build_unpack(LLVMBuilderRef builder, - struct lp_type src_type, - struct lp_type dst_type, - LLVMValueRef src, - LLVMValueRef *dst, unsigned num_dsts) -{ - unsigned num_tmps; - unsigned i; - - /* Register width must remain constant */ - assert(src_type.width * src_type.length == dst_type.width * dst_type.length); - - /* We must not loose or gain channels. Only precision */ - assert(src_type.length == dst_type.length * num_dsts); - - num_tmps = 1; - dst[0] = src; - - while(src_type.width < dst_type.width) { - struct lp_type tmp_type = src_type; - - tmp_type.width *= 2; - tmp_type.length /= 2; - - for(i = num_tmps; i--; ) { - lp_build_unpack2(builder, src_type, tmp_type, dst[i], &dst[2*i + 0], &dst[2*i + 1]); - } - - src_type = tmp_type; - - num_tmps *= 2; - } - - assert(num_tmps == num_dsts); -} - - -/** - * Non-interleaved pack. - * - * This will move values as - * - * lo = __ l0 __ l1 __ l2 __.. __ ln - * hi = __ h0 __ h1 __ h2 __.. __ hn - * res = l0 l1 l2 .. ln h0 h1 h2 .. hn - * - * This will only change the number of bits the values are represented, not the - * values themselves. - * - * It is assumed the values are already clamped into the destination type range. - * Values outside that range will produce undefined results. Use - * lp_build_packs2 instead. - */ -LLVMValueRef -lp_build_pack2(LLVMBuilderRef builder, - struct lp_type src_type, - struct lp_type dst_type, - LLVMValueRef lo, - LLVMValueRef hi) -{ - LLVMTypeRef src_vec_type = lp_build_vec_type(src_type); - LLVMTypeRef dst_vec_type = lp_build_vec_type(dst_type); - LLVMValueRef shuffle; - LLVMValueRef res; - - dst_vec_type = lp_build_vec_type(dst_type); - - assert(!src_type.floating); - assert(!dst_type.floating); - assert(src_type.width == dst_type.width * 2); - assert(src_type.length * 2 == dst_type.length); - - if(util_cpu_caps.has_sse2 && src_type.width * src_type.length == 128) { - switch(src_type.width) { - case 32: - if(dst_type.sign) { - res = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packssdw.128", src_vec_type, lo, hi); - } - else { - if (util_cpu_caps.has_sse4_1) { - /* PACKUSDW is the only instrinsic with a consistent signature */ - return lp_build_intrinsic_binary(builder, "llvm.x86.sse41.packusdw", dst_vec_type, lo, hi); - } - else { - assert(0); - return LLVMGetUndef(dst_vec_type); - } - } - break; - - case 16: - if(dst_type.sign) - res = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packsswb.128", src_vec_type, lo, hi); - else - res = lp_build_intrinsic_binary(builder, "llvm.x86.sse2.packuswb.128", src_vec_type, lo, hi); - break; - - default: - assert(0); - return LLVMGetUndef(dst_vec_type); - break; - } - - res = LLVMBuildBitCast(builder, res, dst_vec_type, ""); - return res; - } - - lo = LLVMBuildBitCast(builder, lo, dst_vec_type, ""); - hi = LLVMBuildBitCast(builder, hi, dst_vec_type, ""); - - shuffle = lp_build_const_pack_shuffle(dst_type.length); - - res = LLVMBuildShuffleVector(builder, lo, hi, shuffle, ""); - - return res; -} - - - -/** - * Non-interleaved pack and saturate. - * - * Same as lp_build_pack2 but will saturate values so that they fit into the - * destination type. - */ -LLVMValueRef -lp_build_packs2(LLVMBuilderRef builder, - struct lp_type src_type, - struct lp_type dst_type, - LLVMValueRef lo, - LLVMValueRef hi) -{ - boolean clamp; - - assert(!src_type.floating); - assert(!dst_type.floating); - assert(src_type.sign == dst_type.sign); - assert(src_type.width == dst_type.width * 2); - assert(src_type.length * 2 == dst_type.length); - - clamp = TRUE; - - /* All X86 SSE non-interleaved pack instructions take signed inputs and - * saturate them, so no need to clamp for those cases. */ - if(util_cpu_caps.has_sse2 && - src_type.width * src_type.length == 128 && - src_type.sign) - clamp = FALSE; - - if(clamp) { - struct lp_build_context bld; - unsigned dst_bits = dst_type.sign ? dst_type.width - 1 : dst_type.width; - LLVMValueRef dst_max = lp_build_int_const_scalar(src_type, ((unsigned long long)1 << dst_bits) - 1); - lp_build_context_init(&bld, builder, src_type); - lo = lp_build_min(&bld, lo, dst_max); - hi = lp_build_min(&bld, hi, dst_max); - /* FIXME: What about lower bound? */ - } - - return lp_build_pack2(builder, src_type, dst_type, lo, hi); -} - - -/** - * Truncate the bit width. - * - * TODO: Handle saturation consistently. - */ -LLVMValueRef -lp_build_pack(LLVMBuilderRef builder, - struct lp_type src_type, - struct lp_type dst_type, - boolean clamped, - const LLVMValueRef *src, unsigned num_srcs) -{ - LLVMValueRef (*pack2)(LLVMBuilderRef builder, - struct lp_type src_type, - struct lp_type dst_type, - LLVMValueRef lo, - LLVMValueRef hi); - LLVMValueRef tmp[LP_MAX_VECTOR_LENGTH]; - unsigned i; - - - /* Register width must remain constant */ - assert(src_type.width * src_type.length == dst_type.width * dst_type.length); - - /* We must not loose or gain channels. Only precision */ - assert(src_type.length * num_srcs == dst_type.length); - - if(clamped) - pack2 = &lp_build_pack2; - else - pack2 = &lp_build_packs2; - - for(i = 0; i < num_srcs; ++i) - tmp[i] = src[i]; - - while(src_type.width > dst_type.width) { - struct lp_type tmp_type = src_type; - - tmp_type.width /= 2; - tmp_type.length *= 2; - - /* Take in consideration the sign changes only in the last step */ - if(tmp_type.width == dst_type.width) - tmp_type.sign = dst_type.sign; - - num_srcs /= 2; - - for(i = 0; i < num_srcs; ++i) - tmp[i] = pack2(builder, src_type, tmp_type, tmp[2*i + 0], tmp[2*i + 1]); - - src_type = tmp_type; - } - - assert(num_srcs == 1); - - return tmp[0]; -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_pack.h b/src/gallium/drivers/llvmpipe/lp_bld_pack.h deleted file mode 100644 index fb2a34984a..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_pack.h +++ /dev/null @@ -1,95 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Helper functions for packing/unpacking conversions. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#ifndef LP_BLD_PACK_H -#define LP_BLD_PACK_H - - -#include <llvm-c/Core.h> - - -struct lp_type; - - -LLVMValueRef -lp_build_interleave2(LLVMBuilderRef builder, - struct lp_type type, - LLVMValueRef a, - LLVMValueRef b, - unsigned lo_hi); - - -void -lp_build_unpack2(LLVMBuilderRef builder, - struct lp_type src_type, - struct lp_type dst_type, - LLVMValueRef src, - LLVMValueRef *dst_lo, - LLVMValueRef *dst_hi); - - -void -lp_build_unpack(LLVMBuilderRef builder, - struct lp_type src_type, - struct lp_type dst_type, - LLVMValueRef src, - LLVMValueRef *dst, unsigned num_dsts); - - -LLVMValueRef -lp_build_packs2(LLVMBuilderRef builder, - struct lp_type src_type, - struct lp_type dst_type, - LLVMValueRef lo, - LLVMValueRef hi); - - -LLVMValueRef -lp_build_pack2(LLVMBuilderRef builder, - struct lp_type src_type, - struct lp_type dst_type, - LLVMValueRef lo, - LLVMValueRef hi); - - -LLVMValueRef -lp_build_pack(LLVMBuilderRef builder, - struct lp_type src_type, - struct lp_type dst_type, - boolean clamped, - const LLVMValueRef *src, unsigned num_srcs); - - -#endif /* !LP_BLD_PACK_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_bld_sample.c b/src/gallium/drivers/llvmpipe/lp_bld_sample.c deleted file mode 100644 index 9003e108c1..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_sample.c +++ /dev/null @@ -1,190 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Texture sampling -- common code. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "util/u_format.h" -#include "util/u_math.h" -#include "lp_bld_debug.h" -#include "lp_bld_const.h" -#include "lp_bld_arit.h" -#include "lp_bld_type.h" -#include "lp_bld_format.h" -#include "lp_bld_sample.h" - - -void -lp_sampler_static_state(struct lp_sampler_static_state *state, - const struct pipe_texture *texture, - const struct pipe_sampler_state *sampler) -{ - memset(state, 0, sizeof *state); - - if(!texture) - return; - - if(!sampler) - return; - - state->format = texture->format; - state->target = texture->target; - state->pot_width = util_is_pot(texture->width0); - state->pot_height = util_is_pot(texture->height0); - state->pot_depth = util_is_pot(texture->depth0); - - state->wrap_s = sampler->wrap_s; - state->wrap_t = sampler->wrap_t; - state->wrap_r = sampler->wrap_r; - state->min_img_filter = sampler->min_img_filter; - state->min_mip_filter = sampler->min_mip_filter; - state->mag_img_filter = sampler->mag_img_filter; - state->compare_mode = sampler->compare_mode; - if(sampler->compare_mode != PIPE_TEX_COMPARE_NONE) { - state->compare_func = sampler->compare_func; - } - state->normalized_coords = sampler->normalized_coords; - state->prefilter = sampler->prefilter; -} - - -/** - * Gather elements from scatter positions in memory into a single vector. - * - * @param src_width src element width - * @param dst_width result element width (source will be expanded to fit) - * @param length length of the offsets, - * @param base_ptr base pointer, should be a i8 pointer type. - * @param offsets vector with offsets - */ -LLVMValueRef -lp_build_gather(LLVMBuilderRef builder, - unsigned length, - unsigned src_width, - unsigned dst_width, - LLVMValueRef base_ptr, - LLVMValueRef offsets) -{ - LLVMTypeRef src_type = LLVMIntType(src_width); - LLVMTypeRef src_ptr_type = LLVMPointerType(src_type, 0); - LLVMTypeRef dst_elem_type = LLVMIntType(dst_width); - LLVMTypeRef dst_vec_type = LLVMVectorType(dst_elem_type, length); - LLVMValueRef res; - unsigned i; - - res = LLVMGetUndef(dst_vec_type); - for(i = 0; i < length; ++i) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); - LLVMValueRef elem_offset; - LLVMValueRef elem_ptr; - LLVMValueRef elem; - - elem_offset = LLVMBuildExtractElement(builder, offsets, index, ""); - elem_ptr = LLVMBuildGEP(builder, base_ptr, &elem_offset, 1, ""); - elem_ptr = LLVMBuildBitCast(builder, elem_ptr, src_ptr_type, ""); - elem = LLVMBuildLoad(builder, elem_ptr, ""); - - assert(src_width <= dst_width); - if(src_width > dst_width) - elem = LLVMBuildTrunc(builder, elem, dst_elem_type, ""); - if(src_width < dst_width) - elem = LLVMBuildZExt(builder, elem, dst_elem_type, ""); - - res = LLVMBuildInsertElement(builder, res, elem, index, ""); - } - - return res; -} - - -/** - * Compute the offset of a pixel. - * - * x, y, y_stride are vectors - */ -LLVMValueRef -lp_build_sample_offset(struct lp_build_context *bld, - const struct util_format_description *format_desc, - LLVMValueRef x, - LLVMValueRef y, - LLVMValueRef y_stride, - LLVMValueRef data_ptr) -{ - LLVMValueRef x_stride; - LLVMValueRef offset; - - x_stride = lp_build_const_scalar(bld->type, format_desc->block.bits/8); - - if(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) { - LLVMValueRef x_lo, x_hi; - LLVMValueRef y_lo, y_hi; - LLVMValueRef x_stride_lo, x_stride_hi; - LLVMValueRef y_stride_lo, y_stride_hi; - LLVMValueRef x_offset_lo, x_offset_hi; - LLVMValueRef y_offset_lo, y_offset_hi; - LLVMValueRef offset_lo, offset_hi; - - x_lo = LLVMBuildAnd(bld->builder, x, bld->one, ""); - y_lo = LLVMBuildAnd(bld->builder, y, bld->one, ""); - - x_hi = LLVMBuildLShr(bld->builder, x, bld->one, ""); - y_hi = LLVMBuildLShr(bld->builder, y, bld->one, ""); - - x_stride_lo = x_stride; - y_stride_lo = lp_build_const_scalar(bld->type, 2*format_desc->block.bits/8); - - x_stride_hi = lp_build_const_scalar(bld->type, 4*format_desc->block.bits/8); - y_stride_hi = LLVMBuildShl(bld->builder, y_stride, bld->one, ""); - - x_offset_lo = lp_build_mul(bld, x_lo, x_stride_lo); - y_offset_lo = lp_build_mul(bld, y_lo, y_stride_lo); - offset_lo = lp_build_add(bld, x_offset_lo, y_offset_lo); - - x_offset_hi = lp_build_mul(bld, x_hi, x_stride_hi); - y_offset_hi = lp_build_mul(bld, y_hi, y_stride_hi); - offset_hi = lp_build_add(bld, x_offset_hi, y_offset_hi); - - offset = lp_build_add(bld, offset_hi, offset_lo); - } - else { - LLVMValueRef x_offset; - LLVMValueRef y_offset; - - x_offset = lp_build_mul(bld, x, x_stride); - y_offset = lp_build_mul(bld, y, y_stride); - - offset = lp_build_add(bld, x_offset, y_offset); - } - - return offset; -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_sample.h b/src/gallium/drivers/llvmpipe/lp_bld_sample.h deleted file mode 100644 index 8cb8210ca7..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_sample.h +++ /dev/null @@ -1,155 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Texture sampling. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - -#ifndef LP_BLD_SAMPLE_H -#define LP_BLD_SAMPLE_H - - -#include <llvm-c/Core.h> - -struct pipe_texture; -struct pipe_sampler_state; -struct util_format_description; -struct lp_type; -struct lp_build_context; - - -/** - * Sampler static state. - * - * These are the bits of state from pipe_texture and pipe_sampler_state that - * are embedded in the generated code. - */ -struct lp_sampler_static_state -{ - /* pipe_texture's state */ - enum pipe_format format; - unsigned target:2; - unsigned pot_width:1; - unsigned pot_height:1; - unsigned pot_depth:1; - - /* pipe_sampler_state's state */ - unsigned wrap_s:3; - unsigned wrap_t:3; - unsigned wrap_r:3; - unsigned min_img_filter:2; - unsigned min_mip_filter:2; - unsigned mag_img_filter:2; - unsigned compare_mode:1; - unsigned compare_func:3; - unsigned normalized_coords:1; - unsigned prefilter:4; -}; - - -/** - * Sampler dynamic state. - * - * These are the bits of state from pipe_texture and pipe_sampler_state that - * are computed in runtime. - * - * There are obtained through callbacks, as we don't want to tie the texture - * sampling code generation logic to any particular texture layout or pipe - * driver. - */ -struct lp_sampler_dynamic_state -{ - - /** Obtain the base texture width. */ - LLVMValueRef - (*width)( struct lp_sampler_dynamic_state *state, - LLVMBuilderRef builder, - unsigned unit); - - /** Obtain the base texture height. */ - LLVMValueRef - (*height)( struct lp_sampler_dynamic_state *state, - LLVMBuilderRef builder, - unsigned unit); - - LLVMValueRef - (*stride)( struct lp_sampler_dynamic_state *state, - LLVMBuilderRef builder, - unsigned unit); - - LLVMValueRef - (*data_ptr)( struct lp_sampler_dynamic_state *state, - LLVMBuilderRef builder, - unsigned unit); - -}; - - -/** - * Derive the sampler static state. - */ -void -lp_sampler_static_state(struct lp_sampler_static_state *state, - const struct pipe_texture *texture, - const struct pipe_sampler_state *sampler); - - -LLVMValueRef -lp_build_gather(LLVMBuilderRef builder, - unsigned length, - unsigned src_width, - unsigned dst_width, - LLVMValueRef base_ptr, - LLVMValueRef offsets); - - -LLVMValueRef -lp_build_sample_offset(struct lp_build_context *bld, - const struct util_format_description *format_desc, - LLVMValueRef x, - LLVMValueRef y, - LLVMValueRef y_stride, - LLVMValueRef data_ptr); - - -void -lp_build_sample_soa(LLVMBuilderRef builder, - const struct lp_sampler_static_state *static_state, - struct lp_sampler_dynamic_state *dynamic_state, - struct lp_type fp_type, - unsigned unit, - unsigned num_coords, - const LLVMValueRef *coords, - LLVMValueRef lodbias, - LLVMValueRef *texel); - - - -#endif /* LP_BLD_SAMPLE_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_bld_sample_soa.c b/src/gallium/drivers/llvmpipe/lp_bld_sample_soa.c deleted file mode 100644 index 5ee8d556a6..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_sample_soa.c +++ /dev/null @@ -1,594 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Texture sampling -- SoA. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "util/u_debug.h" -#include "util/u_debug_dump.h" -#include "util/u_memory.h" -#include "util/u_math.h" -#include "util/u_format.h" -#include "util/u_cpu_detect.h" -#include "lp_bld_debug.h" -#include "lp_bld_type.h" -#include "lp_bld_const.h" -#include "lp_bld_conv.h" -#include "lp_bld_arit.h" -#include "lp_bld_logic.h" -#include "lp_bld_swizzle.h" -#include "lp_bld_pack.h" -#include "lp_bld_format.h" -#include "lp_bld_sample.h" - - -/** - * Keep all information for sampling code generation in a single place. - */ -struct lp_build_sample_context -{ - LLVMBuilderRef builder; - - const struct lp_sampler_static_state *static_state; - - struct lp_sampler_dynamic_state *dynamic_state; - - const struct util_format_description *format_desc; - - /** Incoming coordinates type and build context */ - struct lp_type coord_type; - struct lp_build_context coord_bld; - - /** Integer coordinates */ - struct lp_type int_coord_type; - struct lp_build_context int_coord_bld; - - /** Output texels type and build context */ - struct lp_type texel_type; - struct lp_build_context texel_bld; -}; - - -static void -lp_build_sample_texel_soa(struct lp_build_sample_context *bld, - LLVMValueRef x, - LLVMValueRef y, - LLVMValueRef y_stride, - LLVMValueRef data_ptr, - LLVMValueRef *texel) -{ - LLVMValueRef offset; - LLVMValueRef packed; - - offset = lp_build_sample_offset(&bld->int_coord_bld, - bld->format_desc, - x, y, y_stride, - data_ptr); - - assert(bld->format_desc->block.width == 1); - assert(bld->format_desc->block.height == 1); - assert(bld->format_desc->block.bits <= bld->texel_type.width); - - packed = lp_build_gather(bld->builder, - bld->texel_type.length, - bld->format_desc->block.bits, - bld->texel_type.width, - data_ptr, offset); - - lp_build_unpack_rgba_soa(bld->builder, - bld->format_desc, - bld->texel_type, - packed, texel); -} - - -static LLVMValueRef -lp_build_sample_packed(struct lp_build_sample_context *bld, - LLVMValueRef x, - LLVMValueRef y, - LLVMValueRef y_stride, - LLVMValueRef data_ptr) -{ - LLVMValueRef offset; - - offset = lp_build_sample_offset(&bld->int_coord_bld, - bld->format_desc, - x, y, y_stride, - data_ptr); - - assert(bld->format_desc->block.width == 1); - assert(bld->format_desc->block.height == 1); - assert(bld->format_desc->block.bits <= bld->texel_type.width); - - return lp_build_gather(bld->builder, - bld->texel_type.length, - bld->format_desc->block.bits, - bld->texel_type.width, - data_ptr, offset); -} - - -static LLVMValueRef -lp_build_sample_wrap(struct lp_build_sample_context *bld, - LLVMValueRef coord, - LLVMValueRef length, - boolean is_pot, - unsigned wrap_mode) -{ - struct lp_build_context *int_coord_bld = &bld->int_coord_bld; - LLVMValueRef length_minus_one; - - length_minus_one = lp_build_sub(int_coord_bld, length, int_coord_bld->one); - - switch(wrap_mode) { - case PIPE_TEX_WRAP_REPEAT: - if(is_pot) - coord = LLVMBuildAnd(bld->builder, coord, length_minus_one, ""); - else - /* Signed remainder won't give the right results for negative - * dividends but unsigned remainder does.*/ - coord = LLVMBuildURem(bld->builder, coord, length, ""); - break; - - case PIPE_TEX_WRAP_CLAMP: - coord = lp_build_max(int_coord_bld, coord, int_coord_bld->zero); - coord = lp_build_min(int_coord_bld, coord, length_minus_one); - break; - - case PIPE_TEX_WRAP_CLAMP_TO_EDGE: - case PIPE_TEX_WRAP_CLAMP_TO_BORDER: - case PIPE_TEX_WRAP_MIRROR_REPEAT: - case PIPE_TEX_WRAP_MIRROR_CLAMP: - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: - /* FIXME */ - _debug_printf("warning: failed to translate texture wrap mode %s\n", - debug_dump_tex_wrap(wrap_mode, TRUE)); - coord = lp_build_max(int_coord_bld, coord, int_coord_bld->zero); - coord = lp_build_min(int_coord_bld, coord, length_minus_one); - break; - - default: - assert(0); - } - - return coord; -} - - -static void -lp_build_sample_2d_nearest_soa(struct lp_build_sample_context *bld, - LLVMValueRef s, - LLVMValueRef t, - LLVMValueRef width, - LLVMValueRef height, - LLVMValueRef stride, - LLVMValueRef data_ptr, - LLVMValueRef *texel) -{ - LLVMValueRef x; - LLVMValueRef y; - - x = lp_build_ifloor(&bld->coord_bld, s); - y = lp_build_ifloor(&bld->coord_bld, t); - - x = lp_build_sample_wrap(bld, x, width, bld->static_state->pot_width, bld->static_state->wrap_s); - y = lp_build_sample_wrap(bld, y, height, bld->static_state->pot_height, bld->static_state->wrap_t); - - lp_build_sample_texel_soa(bld, x, y, stride, data_ptr, texel); -} - - -static void -lp_build_sample_2d_linear_soa(struct lp_build_sample_context *bld, - LLVMValueRef s, - LLVMValueRef t, - LLVMValueRef width, - LLVMValueRef height, - LLVMValueRef stride, - LLVMValueRef data_ptr, - LLVMValueRef *texel) -{ - LLVMValueRef half; - LLVMValueRef s_ipart; - LLVMValueRef t_ipart; - LLVMValueRef s_fpart; - LLVMValueRef t_fpart; - LLVMValueRef x0, x1; - LLVMValueRef y0, y1; - LLVMValueRef neighbors[2][2][4]; - unsigned chan; - - half = lp_build_const_scalar(bld->coord_type, 0.5); - s = lp_build_sub(&bld->coord_bld, s, half); - t = lp_build_sub(&bld->coord_bld, t, half); - - s_ipart = lp_build_floor(&bld->coord_bld, s); - t_ipart = lp_build_floor(&bld->coord_bld, t); - - s_fpart = lp_build_sub(&bld->coord_bld, s, s_ipart); - t_fpart = lp_build_sub(&bld->coord_bld, t, t_ipart); - - x0 = lp_build_itrunc(&bld->coord_bld, s_ipart); - y0 = lp_build_itrunc(&bld->coord_bld, t_ipart); - - x0 = lp_build_sample_wrap(bld, x0, width, bld->static_state->pot_width, bld->static_state->wrap_s); - y0 = lp_build_sample_wrap(bld, y0, height, bld->static_state->pot_height, bld->static_state->wrap_t); - - x1 = lp_build_add(&bld->int_coord_bld, x0, bld->int_coord_bld.one); - y1 = lp_build_add(&bld->int_coord_bld, y0, bld->int_coord_bld.one); - - x1 = lp_build_sample_wrap(bld, x1, width, bld->static_state->pot_width, bld->static_state->wrap_s); - y1 = lp_build_sample_wrap(bld, y1, height, bld->static_state->pot_height, bld->static_state->wrap_t); - - lp_build_sample_texel_soa(bld, x0, y0, stride, data_ptr, neighbors[0][0]); - lp_build_sample_texel_soa(bld, x1, y0, stride, data_ptr, neighbors[0][1]); - lp_build_sample_texel_soa(bld, x0, y1, stride, data_ptr, neighbors[1][0]); - lp_build_sample_texel_soa(bld, x1, y1, stride, data_ptr, neighbors[1][1]); - - /* TODO: Don't interpolate missing channels */ - for(chan = 0; chan < 4; ++chan) { - texel[chan] = lp_build_lerp_2d(&bld->texel_bld, - s_fpart, t_fpart, - neighbors[0][0][chan], - neighbors[0][1][chan], - neighbors[1][0][chan], - neighbors[1][1][chan]); - } -} - - -static void -lp_build_rgba8_to_f32_soa(LLVMBuilderRef builder, - struct lp_type dst_type, - LLVMValueRef packed, - LLVMValueRef *rgba) -{ - LLVMValueRef mask = lp_build_int_const_scalar(dst_type, 0xff); - unsigned chan; - - /* Decode the input vector components */ - for (chan = 0; chan < 4; ++chan) { - unsigned start = chan*8; - unsigned stop = start + 8; - LLVMValueRef input; - - input = packed; - - if(start) - input = LLVMBuildLShr(builder, input, lp_build_int_const_scalar(dst_type, start), ""); - - if(stop < 32) - input = LLVMBuildAnd(builder, input, mask, ""); - - input = lp_build_unsigned_norm_to_float(builder, 8, dst_type, input); - - rgba[chan] = input; - } -} - - -static void -lp_build_sample_2d_linear_aos(struct lp_build_sample_context *bld, - LLVMValueRef s, - LLVMValueRef t, - LLVMValueRef width, - LLVMValueRef height, - LLVMValueRef stride, - LLVMValueRef data_ptr, - LLVMValueRef *texel) -{ - LLVMBuilderRef builder = bld->builder; - struct lp_build_context i32, h16, u8n; - LLVMTypeRef i32_vec_type, h16_vec_type, u8n_vec_type; - LLVMValueRef i32_c8, i32_c128, i32_c255; - LLVMValueRef s_ipart, s_fpart, s_fpart_lo, s_fpart_hi; - LLVMValueRef t_ipart, t_fpart, t_fpart_lo, t_fpart_hi; - LLVMValueRef x0, x1; - LLVMValueRef y0, y1; - LLVMValueRef neighbors[2][2]; - LLVMValueRef neighbors_lo[2][2]; - LLVMValueRef neighbors_hi[2][2]; - LLVMValueRef packed, packed_lo, packed_hi; - LLVMValueRef unswizzled[4]; - - lp_build_context_init(&i32, builder, lp_type_int(32)); - lp_build_context_init(&h16, builder, lp_type_ufixed(16)); - lp_build_context_init(&u8n, builder, lp_type_unorm(8)); - - i32_vec_type = lp_build_vec_type(i32.type); - h16_vec_type = lp_build_vec_type(h16.type); - u8n_vec_type = lp_build_vec_type(u8n.type); - - s = lp_build_mul_imm(&bld->coord_bld, s, 256); - t = lp_build_mul_imm(&bld->coord_bld, t, 256); - - s = LLVMBuildFPToSI(builder, s, i32_vec_type, ""); - t = LLVMBuildFPToSI(builder, t, i32_vec_type, ""); - - i32_c128 = lp_build_int_const_scalar(i32.type, -128); - s = LLVMBuildAdd(builder, s, i32_c128, ""); - t = LLVMBuildAdd(builder, t, i32_c128, ""); - - i32_c8 = lp_build_int_const_scalar(i32.type, 8); - s_ipart = LLVMBuildAShr(builder, s, i32_c8, ""); - t_ipart = LLVMBuildAShr(builder, t, i32_c8, ""); - - i32_c255 = lp_build_int_const_scalar(i32.type, 255); - s_fpart = LLVMBuildAnd(builder, s, i32_c255, ""); - t_fpart = LLVMBuildAnd(builder, t, i32_c255, ""); - - x0 = s_ipart; - y0 = t_ipart; - - x0 = lp_build_sample_wrap(bld, x0, width, bld->static_state->pot_width, bld->static_state->wrap_s); - y0 = lp_build_sample_wrap(bld, y0, height, bld->static_state->pot_height, bld->static_state->wrap_t); - - x1 = lp_build_add(&bld->int_coord_bld, x0, bld->int_coord_bld.one); - y1 = lp_build_add(&bld->int_coord_bld, y0, bld->int_coord_bld.one); - - x1 = lp_build_sample_wrap(bld, x1, width, bld->static_state->pot_width, bld->static_state->wrap_s); - y1 = lp_build_sample_wrap(bld, y1, height, bld->static_state->pot_height, bld->static_state->wrap_t); - - /* - * Transform 4 x i32 in - * - * s_fpart = {s0, s1, s2, s3} - * - * into 8 x i16 - * - * s_fpart = {00, s0, 00, s1, 00, s2, 00, s3} - * - * into two 8 x i16 - * - * s_fpart_lo = {s0, s0, s0, s0, s1, s1, s1, s1} - * s_fpart_hi = {s2, s2, s2, s2, s3, s3, s3, s3} - * - * and likewise for t_fpart. There is no risk of loosing precision here - * since the fractional parts only use the lower 8bits. - */ - - s_fpart = LLVMBuildBitCast(builder, s_fpart, h16_vec_type, ""); - t_fpart = LLVMBuildBitCast(builder, t_fpart, h16_vec_type, ""); - - { - LLVMTypeRef elem_type = LLVMInt32Type(); - LLVMValueRef shuffles_lo[LP_MAX_VECTOR_LENGTH]; - LLVMValueRef shuffles_hi[LP_MAX_VECTOR_LENGTH]; - LLVMValueRef shuffle_lo; - LLVMValueRef shuffle_hi; - unsigned i, j; - - for(j = 0; j < h16.type.length; j += 4) { - unsigned subindex = util_cpu_caps.little_endian ? 0 : 1; - LLVMValueRef index; - - index = LLVMConstInt(elem_type, j/2 + subindex, 0); - for(i = 0; i < 4; ++i) - shuffles_lo[j + i] = index; - - index = LLVMConstInt(elem_type, h16.type.length/2 + j/2 + subindex, 0); - for(i = 0; i < 4; ++i) - shuffles_hi[j + i] = index; - } - - shuffle_lo = LLVMConstVector(shuffles_lo, h16.type.length); - shuffle_hi = LLVMConstVector(shuffles_hi, h16.type.length); - - s_fpart_lo = LLVMBuildShuffleVector(builder, s_fpart, h16.undef, shuffle_lo, ""); - t_fpart_lo = LLVMBuildShuffleVector(builder, t_fpart, h16.undef, shuffle_lo, ""); - s_fpart_hi = LLVMBuildShuffleVector(builder, s_fpart, h16.undef, shuffle_hi, ""); - t_fpart_hi = LLVMBuildShuffleVector(builder, t_fpart, h16.undef, shuffle_hi, ""); - } - - /* - * Fetch the pixels as 4 x 32bit (rgba order might differ): - * - * rgba0 rgba1 rgba2 rgba3 - * - * bit cast them into 16 x u8 - * - * r0 g0 b0 a0 r1 g1 b1 a1 r2 g2 b2 a2 r3 g3 b3 a3 - * - * unpack them into two 8 x i16: - * - * r0 g0 b0 a0 r1 g1 b1 a1 - * r2 g2 b2 a2 r3 g3 b3 a3 - * - * The higher 8 bits of the resulting elements will be zero. - */ - - neighbors[0][0] = lp_build_sample_packed(bld, x0, y0, stride, data_ptr); - neighbors[0][1] = lp_build_sample_packed(bld, x1, y0, stride, data_ptr); - neighbors[1][0] = lp_build_sample_packed(bld, x0, y1, stride, data_ptr); - neighbors[1][1] = lp_build_sample_packed(bld, x1, y1, stride, data_ptr); - - neighbors[0][0] = LLVMBuildBitCast(builder, neighbors[0][0], u8n_vec_type, ""); - neighbors[0][1] = LLVMBuildBitCast(builder, neighbors[0][1], u8n_vec_type, ""); - neighbors[1][0] = LLVMBuildBitCast(builder, neighbors[1][0], u8n_vec_type, ""); - neighbors[1][1] = LLVMBuildBitCast(builder, neighbors[1][1], u8n_vec_type, ""); - - lp_build_unpack2(builder, u8n.type, h16.type, neighbors[0][0], &neighbors_lo[0][0], &neighbors_hi[0][0]); - lp_build_unpack2(builder, u8n.type, h16.type, neighbors[0][1], &neighbors_lo[0][1], &neighbors_hi[0][1]); - lp_build_unpack2(builder, u8n.type, h16.type, neighbors[1][0], &neighbors_lo[1][0], &neighbors_hi[1][0]); - lp_build_unpack2(builder, u8n.type, h16.type, neighbors[1][1], &neighbors_lo[1][1], &neighbors_hi[1][1]); - - /* - * Linear interpolate with 8.8 fixed point. - */ - - packed_lo = lp_build_lerp_2d(&h16, - s_fpart_lo, t_fpart_lo, - neighbors_lo[0][0], - neighbors_lo[0][1], - neighbors_lo[1][0], - neighbors_lo[1][1]); - - packed_hi = lp_build_lerp_2d(&h16, - s_fpart_hi, t_fpart_hi, - neighbors_hi[0][0], - neighbors_hi[0][1], - neighbors_hi[1][0], - neighbors_hi[1][1]); - - packed = lp_build_pack2(builder, h16.type, u8n.type, packed_lo, packed_hi); - - /* - * Convert to SoA and swizzle. - */ - - packed = LLVMBuildBitCast(builder, packed, i32_vec_type, ""); - - lp_build_rgba8_to_f32_soa(bld->builder, - bld->texel_type, - packed, unswizzled); - - lp_build_format_swizzle_soa(bld->format_desc, - bld->texel_type, unswizzled, - texel); -} - - -static void -lp_build_sample_compare(struct lp_build_sample_context *bld, - LLVMValueRef p, - LLVMValueRef *texel) -{ - struct lp_build_context *texel_bld = &bld->texel_bld; - LLVMValueRef res; - unsigned chan; - - if(bld->static_state->compare_mode == PIPE_TEX_COMPARE_NONE) - return; - - /* TODO: Compare before swizzling, to avoid redundant computations */ - res = NULL; - for(chan = 0; chan < 4; ++chan) { - LLVMValueRef cmp; - cmp = lp_build_cmp(texel_bld, bld->static_state->compare_func, p, texel[chan]); - cmp = lp_build_select(texel_bld, cmp, texel_bld->one, texel_bld->zero); - - if(res) - res = lp_build_add(texel_bld, res, cmp); - else - res = cmp; - } - - assert(res); - res = lp_build_mul(texel_bld, res, lp_build_const_scalar(texel_bld->type, 0.25)); - - /* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */ - for(chan = 0; chan < 3; ++chan) - texel[chan] = res; - texel[3] = texel_bld->one; -} - - -void -lp_build_sample_soa(LLVMBuilderRef builder, - const struct lp_sampler_static_state *static_state, - struct lp_sampler_dynamic_state *dynamic_state, - struct lp_type type, - unsigned unit, - unsigned num_coords, - const LLVMValueRef *coords, - LLVMValueRef lodbias, - LLVMValueRef *texel) -{ - struct lp_build_sample_context bld; - LLVMValueRef width; - LLVMValueRef height; - LLVMValueRef stride; - LLVMValueRef data_ptr; - LLVMValueRef s; - LLVMValueRef t; - LLVMValueRef p; - - /* Setup our build context */ - memset(&bld, 0, sizeof bld); - bld.builder = builder; - bld.static_state = static_state; - bld.dynamic_state = dynamic_state; - bld.format_desc = util_format_description(static_state->format); - bld.coord_type = type; - bld.int_coord_type = lp_int_type(type); - bld.texel_type = type; - lp_build_context_init(&bld.coord_bld, builder, bld.coord_type); - lp_build_context_init(&bld.int_coord_bld, builder, bld.int_coord_type); - lp_build_context_init(&bld.texel_bld, builder, bld.texel_type); - - /* Get the dynamic state */ - width = dynamic_state->width(dynamic_state, builder, unit); - height = dynamic_state->height(dynamic_state, builder, unit); - stride = dynamic_state->stride(dynamic_state, builder, unit); - data_ptr = dynamic_state->data_ptr(dynamic_state, builder, unit); - - s = coords[0]; - t = coords[1]; - p = coords[2]; - - width = lp_build_broadcast_scalar(&bld.int_coord_bld, width); - height = lp_build_broadcast_scalar(&bld.int_coord_bld, height); - stride = lp_build_broadcast_scalar(&bld.int_coord_bld, stride); - - if(static_state->target == PIPE_TEXTURE_1D) - t = bld.coord_bld.zero; - - if(static_state->normalized_coords) { - LLVMTypeRef coord_vec_type = lp_build_vec_type(bld.coord_type); - LLVMValueRef fp_width = LLVMBuildSIToFP(builder, width, coord_vec_type, ""); - LLVMValueRef fp_height = LLVMBuildSIToFP(builder, height, coord_vec_type, ""); - s = lp_build_mul(&bld.coord_bld, s, fp_width); - t = lp_build_mul(&bld.coord_bld, t, fp_height); - } - - switch (static_state->min_img_filter) { - case PIPE_TEX_FILTER_NEAREST: - lp_build_sample_2d_nearest_soa(&bld, s, t, width, height, stride, data_ptr, texel); - break; - case PIPE_TEX_FILTER_LINEAR: - if(lp_format_is_rgba8(bld.format_desc)) - lp_build_sample_2d_linear_aos(&bld, s, t, width, height, stride, data_ptr, texel); - else - lp_build_sample_2d_linear_soa(&bld, s, t, width, height, stride, data_ptr, texel); - break; - default: - assert(0); - } - - /* FIXME: respect static_state->min_mip_filter */; - /* FIXME: respect static_state->mag_img_filter */; - /* FIXME: respect static_state->prefilter */; - - lp_build_sample_compare(&bld, p, texel); -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_struct.c b/src/gallium/drivers/llvmpipe/lp_bld_struct.c deleted file mode 100644 index 3998ac374f..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_struct.c +++ /dev/null @@ -1,72 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -/** - * @file - * Helper functions for manipulation structures. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#include "util/u_debug.h" -#include "util/u_memory.h" - -#include "lp_bld_debug.h" -#include "lp_bld_struct.h" - - -LLVMValueRef -lp_build_struct_get_ptr(LLVMBuilderRef builder, - LLVMValueRef ptr, - unsigned member, - const char *name) -{ - LLVMValueRef indices[2]; - LLVMValueRef member_ptr; - indices[0] = LLVMConstInt(LLVMInt32Type(), 0, 0); - indices[1] = LLVMConstInt(LLVMInt32Type(), member, 0); - member_ptr = LLVMBuildGEP(builder, ptr, indices, Elements(indices), ""); - lp_build_name(member_ptr, "%s.%s_ptr", LLVMGetValueName(ptr), name); - return member_ptr; -} - - -LLVMValueRef -lp_build_struct_get(LLVMBuilderRef builder, - LLVMValueRef ptr, - unsigned member, - const char *name) -{ - LLVMValueRef member_ptr; - LLVMValueRef res; - member_ptr = lp_build_struct_get_ptr(builder, ptr, member, name); - res = LLVMBuildLoad(builder, member_ptr, ""); - lp_build_name(res, "%s.%s", LLVMGetValueName(ptr), name); - return res; -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_struct.h b/src/gallium/drivers/llvmpipe/lp_bld_struct.h deleted file mode 100644 index 740392f561..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_struct.h +++ /dev/null @@ -1,75 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Helper functions for type conversions. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#ifndef LP_BLD_STRUCT_H -#define LP_BLD_STRUCT_H - - -#include <llvm-c/Core.h> -#include <llvm-c/Target.h> - -#include "util/u_debug.h" -#include "util/u_memory.h" - - -#define LP_CHECK_STRUCT_SIZE(_ctype, _ltarget, _ltype) \ - assert(LLVMABISizeOfType(_ltarget, _ltype) == \ - sizeof(_ctype)) - -#define LP_CHECK_MEMBER_OFFSET(_ctype, _cmember, _ltarget, _ltype, _lindex) \ - assert(LLVMOffsetOfElement(_ltarget, _ltype, _lindex) == \ - offsetof(_ctype, _cmember)) - - -/** - * Get value pointer to a structure member. - */ -LLVMValueRef -lp_build_struct_get_ptr(LLVMBuilderRef builder, - LLVMValueRef ptr, - unsigned member, - const char *name); - -/** - * Get the value of a structure member. - */ -LLVMValueRef -lp_build_struct_get(LLVMBuilderRef builder, - LLVMValueRef ptr, - unsigned member, - const char *name); - - -#endif /* !LP_BLD_STRUCT_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_bld_swizzle.c b/src/gallium/drivers/llvmpipe/lp_bld_swizzle.c deleted file mode 100644 index 64e81f7b1f..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_swizzle.c +++ /dev/null @@ -1,239 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Helper functions for swizzling/shuffling. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#include "util/u_debug.h" - -#include "lp_bld_type.h" -#include "lp_bld_const.h" -#include "lp_bld_logic.h" -#include "lp_bld_swizzle.h" - - -LLVMValueRef -lp_build_broadcast(LLVMBuilderRef builder, - LLVMTypeRef vec_type, - LLVMValueRef scalar) -{ - const unsigned n = LLVMGetVectorSize(vec_type); - LLVMValueRef res; - unsigned i; - - res = LLVMGetUndef(vec_type); - for(i = 0; i < n; ++i) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); - res = LLVMBuildInsertElement(builder, res, scalar, index, ""); - } - - return res; -} - - -LLVMValueRef -lp_build_broadcast_scalar(struct lp_build_context *bld, - LLVMValueRef scalar) -{ - const struct lp_type type = bld->type; - LLVMValueRef res; - unsigned i; - - res = bld->undef; - for(i = 0; i < type.length; ++i) { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); - res = LLVMBuildInsertElement(bld->builder, res, scalar, index, ""); - } - - return res; -} - - -LLVMValueRef -lp_build_broadcast_aos(struct lp_build_context *bld, - LLVMValueRef a, - unsigned channel) -{ - const struct lp_type type = bld->type; - const unsigned n = type.length; - unsigned i, j; - - if(a == bld->undef || a == bld->zero || a == bld->one) - return a; - - /* XXX: SSE3 has PSHUFB which should be better than bitmasks, but forcing - * using shuffles here actually causes worst results. More investigation is - * needed. */ - if (n <= 4) { - /* - * Shuffle. - */ - LLVMTypeRef elem_type = LLVMInt32Type(); - LLVMValueRef shuffles[LP_MAX_VECTOR_LENGTH]; - - for(j = 0; j < n; j += 4) - for(i = 0; i < 4; ++i) - shuffles[j + i] = LLVMConstInt(elem_type, j + channel, 0); - - return LLVMBuildShuffleVector(bld->builder, a, bld->undef, LLVMConstVector(shuffles, n), ""); - } - else { - /* - * Bit mask and recursive shifts - * - * XYZW XYZW .... XYZW <= input - * 0Y00 0Y00 .... 0Y00 - * YY00 YY00 .... YY00 - * YYYY YYYY .... YYYY <= output - */ - struct lp_type type4 = type; - const char shifts[4][2] = { - { 1, 2}, - {-1, 2}, - { 1, -2}, - {-1, -2} - }; - boolean cond[4]; - unsigned i; - - memset(cond, 0, sizeof cond); - cond[channel] = 1; - - a = LLVMBuildAnd(bld->builder, a, lp_build_const_mask_aos(type, cond), ""); - - type4.width *= 4; - type4.length /= 4; - - a = LLVMBuildBitCast(bld->builder, a, lp_build_vec_type(type4), ""); - - for(i = 0; i < 2; ++i) { - LLVMValueRef tmp = NULL; - int shift = shifts[channel][i]; - -#ifdef PIPE_ARCH_LITTLE_ENDIAN - shift = -shift; -#endif - - if(shift > 0) - tmp = LLVMBuildLShr(bld->builder, a, lp_build_int_const_scalar(type4, shift*type.width), ""); - if(shift < 0) - tmp = LLVMBuildShl(bld->builder, a, lp_build_int_const_scalar(type4, -shift*type.width), ""); - - assert(tmp); - if(tmp) - a = LLVMBuildOr(bld->builder, a, tmp, ""); - } - - return LLVMBuildBitCast(bld->builder, a, lp_build_vec_type(type), ""); - } -} - - -LLVMValueRef -lp_build_swizzle1_aos(struct lp_build_context *bld, - LLVMValueRef a, - const unsigned char swizzle[4]) -{ - const unsigned n = bld->type.length; - unsigned i, j; - - if(a == bld->undef || a == bld->zero || a == bld->one) - return a; - - if(swizzle[0] == swizzle[1] && swizzle[1] == swizzle[2] && swizzle[2] == swizzle[3]) - return lp_build_broadcast_aos(bld, a, swizzle[0]); - - { - /* - * Shuffle. - */ - LLVMTypeRef elem_type = LLVMInt32Type(); - LLVMValueRef shuffles[LP_MAX_VECTOR_LENGTH]; - - for(j = 0; j < n; j += 4) - for(i = 0; i < 4; ++i) - shuffles[j + i] = LLVMConstInt(elem_type, j + swizzle[i], 0); - - return LLVMBuildShuffleVector(bld->builder, a, bld->undef, LLVMConstVector(shuffles, n), ""); - } -} - - -LLVMValueRef -lp_build_swizzle2_aos(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b, - const unsigned char swizzle[4]) -{ - const unsigned n = bld->type.length; - unsigned i, j; - - if(swizzle[0] < 4 && swizzle[1] < 4 && swizzle[2] < 4 && swizzle[3] < 4) - return lp_build_swizzle1_aos(bld, a, swizzle); - - if(a == b) { - unsigned char swizzle1[4]; - swizzle1[0] = swizzle[0] % 4; - swizzle1[1] = swizzle[1] % 4; - swizzle1[2] = swizzle[2] % 4; - swizzle1[3] = swizzle[3] % 4; - return lp_build_swizzle1_aos(bld, a, swizzle1); - } - - if(swizzle[0] % 4 == 0 && - swizzle[1] % 4 == 1 && - swizzle[2] % 4 == 2 && - swizzle[3] % 4 == 3) { - boolean cond[4]; - cond[0] = swizzle[0] / 4; - cond[1] = swizzle[1] / 4; - cond[2] = swizzle[2] / 4; - cond[3] = swizzle[3] / 4; - return lp_build_select_aos(bld, a, b, cond); - } - - { - /* - * Shuffle. - */ - LLVMTypeRef elem_type = LLVMInt32Type(); - LLVMValueRef shuffles[LP_MAX_VECTOR_LENGTH]; - - for(j = 0; j < n; j += 4) - for(i = 0; i < 4; ++i) - shuffles[j + i] = LLVMConstInt(elem_type, j + (swizzle[i] % 4) + (swizzle[i] / 4 * n), 0); - - return LLVMBuildShuffleVector(bld->builder, a, b, LLVMConstVector(shuffles, n), ""); - } -} - - diff --git a/src/gallium/drivers/llvmpipe/lp_bld_swizzle.h b/src/gallium/drivers/llvmpipe/lp_bld_swizzle.h deleted file mode 100644 index b9472127a6..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_swizzle.h +++ /dev/null @@ -1,91 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Helper functions for swizzling/shuffling. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#ifndef LP_BLD_SWIZZLE_H -#define LP_BLD_SWIZZLE_H - - -#include <llvm-c/Core.h> - - -struct lp_type; -struct lp_build_context; - - -LLVMValueRef -lp_build_broadcast(LLVMBuilderRef builder, - LLVMTypeRef vec_type, - LLVMValueRef scalar); - - -LLVMValueRef -lp_build_broadcast_scalar(struct lp_build_context *bld, - LLVMValueRef scalar); - - -/** - * Broadcast one channel of a vector composed of arrays of XYZW structures into - * all four channel. - */ -LLVMValueRef -lp_build_broadcast_aos(struct lp_build_context *bld, - LLVMValueRef a, - unsigned channel); - - -/** - * Swizzle a vector consisting of an array of XYZW structs. - * - * @param swizzle is the in [0,4[ range. - */ -LLVMValueRef -lp_build_swizzle1_aos(struct lp_build_context *bld, - LLVMValueRef a, - const unsigned char swizzle[4]); - - -/** - * Swizzle two vector consisting of an array of XYZW structs. - * - * @param swizzle is the in [0,8[ range. Values in [4,8[ range refer to b. - */ -LLVMValueRef -lp_build_swizzle2_aos(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b, - const unsigned char swizzle[4]); - - -#endif /* !LP_BLD_SWIZZLE_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_bld_tgsi.h b/src/gallium/drivers/llvmpipe/lp_bld_tgsi.h deleted file mode 100644 index eddb7a83fa..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_tgsi.h +++ /dev/null @@ -1,84 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * TGSI to LLVM IR translation. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - -#ifndef LP_BLD_TGSI_H -#define LP_BLD_TGSI_H - -#include <llvm-c/Core.h> - - -struct tgsi_token; -struct lp_type; -struct lp_build_context; -struct lp_build_mask_context; - - -/** - * Sampler code generation interface. - * - * Although texture sampling is a requirement for TGSI translation, it is - * a very different problem with several different approaches to it. This - * structure establishes an interface for texture sampling code generation, so - * that we can easily use different texture sampling strategies. - */ -struct lp_build_sampler_soa -{ - void - (*destroy)( struct lp_build_sampler_soa *sampler ); - - void - (*emit_fetch_texel)( struct lp_build_sampler_soa *sampler, - LLVMBuilderRef builder, - struct lp_type type, - unsigned unit, - unsigned num_coords, - const LLVMValueRef *coords, - LLVMValueRef lodbias, - LLVMValueRef *texel); -}; - - -void -lp_build_tgsi_soa(LLVMBuilderRef builder, - const struct tgsi_token *tokens, - struct lp_type type, - struct lp_build_mask_context *mask, - LLVMValueRef consts_ptr, - const LLVMValueRef *pos, - const LLVMValueRef (*inputs)[4], - LLVMValueRef (*outputs)[4], - struct lp_build_sampler_soa *sampler); - - -#endif /* LP_BLD_TGSI_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c b/src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c deleted file mode 100644 index fb1eda4423..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_tgsi_soa.c +++ /dev/null @@ -1,1469 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * Copyright 2007-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. - * - **************************************************************************/ - -/** - * @file - * TGSI to LLVM IR translation -- SoA. - * - * @author Jose Fonseca <jfonseca@vmware.com> - * - * Based on tgsi_sse2.c code written by Michal Krol, Keith Whitwell, - * Brian Paul, and others. - */ - -#include "pipe/p_config.h" -#include "pipe/p_shader_tokens.h" -#include "util/u_debug.h" -#include "util/u_math.h" -#include "util/u_memory.h" -#include "tgsi/tgsi_info.h" -#include "tgsi/tgsi_parse.h" -#include "tgsi/tgsi_util.h" -#include "tgsi/tgsi_exec.h" -#include "lp_bld_type.h" -#include "lp_bld_const.h" -#include "lp_bld_intr.h" -#include "lp_bld_arit.h" -#include "lp_bld_logic.h" -#include "lp_bld_swizzle.h" -#include "lp_bld_flow.h" -#include "lp_bld_tgsi.h" -#include "lp_bld_debug.h" - - -#define LP_MAX_TEMPS 256 -#define LP_MAX_IMMEDIATES 256 - - -#define FOR_EACH_CHANNEL( CHAN )\ - for (CHAN = 0; CHAN < NUM_CHANNELS; CHAN++) - -#define IS_DST0_CHANNEL_ENABLED( INST, CHAN )\ - ((INST)->Dst[0].Register.WriteMask & (1 << (CHAN))) - -#define IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )\ - if (IS_DST0_CHANNEL_ENABLED( INST, CHAN )) - -#define FOR_EACH_DST0_ENABLED_CHANNEL( INST, CHAN )\ - FOR_EACH_CHANNEL( CHAN )\ - IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN ) - -#define CHAN_X 0 -#define CHAN_Y 1 -#define CHAN_Z 2 -#define CHAN_W 3 - -#define QUAD_TOP_LEFT 0 -#define QUAD_TOP_RIGHT 1 -#define QUAD_BOTTOM_LEFT 2 -#define QUAD_BOTTOM_RIGHT 3 - - -struct lp_build_tgsi_soa_context -{ - struct lp_build_context base; - - LLVMValueRef consts_ptr; - const LLVMValueRef *pos; - const LLVMValueRef (*inputs)[NUM_CHANNELS]; - LLVMValueRef (*outputs)[NUM_CHANNELS]; - - struct lp_build_sampler_soa *sampler; - - LLVMValueRef immediates[LP_MAX_IMMEDIATES][NUM_CHANNELS]; - LLVMValueRef temps[LP_MAX_TEMPS][NUM_CHANNELS]; - - struct lp_build_mask_context *mask; -}; - - -static const unsigned char -swizzle_left[4] = { - QUAD_TOP_LEFT, QUAD_TOP_LEFT, - QUAD_BOTTOM_LEFT, QUAD_BOTTOM_LEFT -}; - -static const unsigned char -swizzle_right[4] = { - QUAD_TOP_RIGHT, QUAD_TOP_RIGHT, - QUAD_BOTTOM_RIGHT, QUAD_BOTTOM_RIGHT -}; - -static const unsigned char -swizzle_top[4] = { - QUAD_TOP_LEFT, QUAD_TOP_RIGHT, - QUAD_TOP_LEFT, QUAD_TOP_RIGHT -}; - -static const unsigned char -swizzle_bottom[4] = { - QUAD_BOTTOM_LEFT, QUAD_BOTTOM_RIGHT, - QUAD_BOTTOM_LEFT, QUAD_BOTTOM_RIGHT -}; - - -static LLVMValueRef -emit_ddx(struct lp_build_tgsi_soa_context *bld, - LLVMValueRef src) -{ - LLVMValueRef src_left = lp_build_swizzle1_aos(&bld->base, src, swizzle_left); - LLVMValueRef src_right = lp_build_swizzle1_aos(&bld->base, src, swizzle_right); - return lp_build_sub(&bld->base, src_right, src_left); -} - - -static LLVMValueRef -emit_ddy(struct lp_build_tgsi_soa_context *bld, - LLVMValueRef src) -{ - LLVMValueRef src_top = lp_build_swizzle1_aos(&bld->base, src, swizzle_top); - LLVMValueRef src_bottom = lp_build_swizzle1_aos(&bld->base, src, swizzle_bottom); - return lp_build_sub(&bld->base, src_top, src_bottom); -} - - -/** - * Register fetch. - */ -static LLVMValueRef -emit_fetch( - struct lp_build_tgsi_soa_context *bld, - const struct tgsi_full_instruction *inst, - unsigned index, - const unsigned chan_index ) -{ - const struct tgsi_full_src_register *reg = &inst->Src[index]; - unsigned swizzle = tgsi_util_get_full_src_register_swizzle( reg, chan_index ); - LLVMValueRef res; - - switch (swizzle) { - case TGSI_SWIZZLE_X: - case TGSI_SWIZZLE_Y: - case TGSI_SWIZZLE_Z: - case TGSI_SWIZZLE_W: - - switch (reg->Register.File) { - case TGSI_FILE_CONSTANT: { - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), reg->Register.Index*4 + swizzle, 0); - LLVMValueRef scalar_ptr = LLVMBuildGEP(bld->base.builder, bld->consts_ptr, &index, 1, ""); - LLVMValueRef scalar = LLVMBuildLoad(bld->base.builder, scalar_ptr, ""); - res = lp_build_broadcast_scalar(&bld->base, scalar); - break; - } - - case TGSI_FILE_IMMEDIATE: - res = bld->immediates[reg->Register.Index][swizzle]; - assert(res); - break; - - case TGSI_FILE_INPUT: - res = bld->inputs[reg->Register.Index][swizzle]; - assert(res); - break; - - case TGSI_FILE_TEMPORARY: - res = bld->temps[reg->Register.Index][swizzle]; - if(!res) - return bld->base.undef; - break; - - default: - assert( 0 ); - return bld->base.undef; - } - break; - - default: - assert( 0 ); - return bld->base.undef; - } - - switch( tgsi_util_get_full_src_register_sign_mode( reg, chan_index ) ) { - case TGSI_UTIL_SIGN_CLEAR: - res = lp_build_abs( &bld->base, res ); - break; - - case TGSI_UTIL_SIGN_SET: - /* TODO: Use bitwese OR for floating point */ - res = lp_build_abs( &bld->base, res ); - res = LLVMBuildNeg( bld->base.builder, res, "" ); - break; - - case TGSI_UTIL_SIGN_TOGGLE: - res = LLVMBuildNeg( bld->base.builder, res, "" ); - break; - - case TGSI_UTIL_SIGN_KEEP: - break; - } - - return res; -} - - -/** - * Register fetch with derivatives. - */ -static void -emit_fetch_deriv( - struct lp_build_tgsi_soa_context *bld, - const struct tgsi_full_instruction *inst, - unsigned index, - const unsigned chan_index, - LLVMValueRef *res, - LLVMValueRef *ddx, - LLVMValueRef *ddy) -{ - LLVMValueRef src; - - src = emit_fetch(bld, inst, index, chan_index); - - if(res) - *res = src; - - /* TODO: use interpolation coeffs for inputs */ - - if(ddx) - *ddx = emit_ddx(bld, src); - - if(ddy) - *ddy = emit_ddy(bld, src); -} - - -/** - * Register store. - */ -static void -emit_store( - struct lp_build_tgsi_soa_context *bld, - const struct tgsi_full_instruction *inst, - unsigned index, - unsigned chan_index, - LLVMValueRef value) -{ - const struct tgsi_full_dst_register *reg = &inst->Dst[index]; - - switch( inst->Instruction.Saturate ) { - case TGSI_SAT_NONE: - break; - - case TGSI_SAT_ZERO_ONE: - value = lp_build_max(&bld->base, value, bld->base.zero); - value = lp_build_min(&bld->base, value, bld->base.one); - break; - - case TGSI_SAT_MINUS_PLUS_ONE: - value = lp_build_max(&bld->base, value, lp_build_const_scalar(bld->base.type, -1.0)); - value = lp_build_min(&bld->base, value, bld->base.one); - break; - - default: - assert(0); - } - - switch( reg->Register.File ) { - case TGSI_FILE_OUTPUT: - bld->outputs[reg->Register.Index][chan_index] = value; - break; - - case TGSI_FILE_TEMPORARY: - bld->temps[reg->Register.Index][chan_index] = value; - break; - - case TGSI_FILE_ADDRESS: - /* FIXME */ - assert(0); - break; - - default: - assert( 0 ); - } -} - - -/** - * High-level instruction translators. - */ - - -static void -emit_tex( struct lp_build_tgsi_soa_context *bld, - const struct tgsi_full_instruction *inst, - boolean apply_lodbias, - boolean projected, - LLVMValueRef *texel) -{ - const uint unit = inst->Src[1].Register.Index; - LLVMValueRef lodbias; - LLVMValueRef oow = NULL; - LLVMValueRef coords[3]; - unsigned num_coords; - unsigned i; - - switch (inst->Texture.Texture) { - case TGSI_TEXTURE_1D: - num_coords = 1; - break; - case TGSI_TEXTURE_2D: - case TGSI_TEXTURE_RECT: - num_coords = 2; - break; - case TGSI_TEXTURE_SHADOW1D: - case TGSI_TEXTURE_SHADOW2D: - case TGSI_TEXTURE_SHADOWRECT: - case TGSI_TEXTURE_3D: - case TGSI_TEXTURE_CUBE: - num_coords = 3; - break; - default: - assert(0); - return; - } - - if(apply_lodbias) - lodbias = emit_fetch( bld, inst, 0, 3 ); - else - lodbias = bld->base.zero; - - if (projected) { - oow = emit_fetch( bld, inst, 0, 3 ); - oow = lp_build_rcp(&bld->base, oow); - } - - for (i = 0; i < num_coords; i++) { - coords[i] = emit_fetch( bld, inst, 0, i ); - if (projected) - coords[i] = lp_build_mul(&bld->base, coords[i], oow); - } - for (i = num_coords; i < 3; i++) { - coords[i] = bld->base.undef; - } - - bld->sampler->emit_fetch_texel(bld->sampler, - bld->base.builder, - bld->base.type, - unit, num_coords, coords, lodbias, - texel); -} - - -static void -emit_kil( - struct lp_build_tgsi_soa_context *bld, - const struct tgsi_full_instruction *inst ) -{ - const struct tgsi_full_src_register *reg = &inst->Src[0]; - LLVMValueRef terms[NUM_CHANNELS]; - LLVMValueRef mask; - unsigned chan_index; - - memset(&terms, 0, sizeof terms); - - FOR_EACH_CHANNEL( chan_index ) { - unsigned swizzle; - - /* Unswizzle channel */ - swizzle = tgsi_util_get_full_src_register_swizzle( reg, chan_index ); - - /* Check if the component has not been already tested. */ - assert(swizzle < NUM_CHANNELS); - if( !terms[swizzle] ) - /* TODO: change the comparison operator instead of setting the sign */ - terms[swizzle] = emit_fetch(bld, inst, 0, chan_index ); - } - - mask = NULL; - FOR_EACH_CHANNEL( chan_index ) { - if(terms[chan_index]) { - LLVMValueRef chan_mask; - - chan_mask = lp_build_cmp(&bld->base, PIPE_FUNC_GEQUAL, terms[chan_index], bld->base.zero); - - if(mask) - mask = LLVMBuildAnd(bld->base.builder, mask, chan_mask, ""); - else - mask = chan_mask; - } - } - - if(mask) - lp_build_mask_update(bld->mask, mask); -} - - -/** - * Check if inst src/dest regs use indirect addressing into temporary - * register file. - */ -static boolean -indirect_temp_reference(const struct tgsi_full_instruction *inst) -{ - uint i; - for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { - const struct tgsi_full_src_register *reg = &inst->Src[i]; - if (reg->Register.File == TGSI_FILE_TEMPORARY && - reg->Register.Indirect) - return TRUE; - } - for (i = 0; i < inst->Instruction.NumDstRegs; i++) { - const struct tgsi_full_dst_register *reg = &inst->Dst[i]; - if (reg->Register.File == TGSI_FILE_TEMPORARY && - reg->Register.Indirect) - return TRUE; - } - return FALSE; -} - - -static int -emit_instruction( - struct lp_build_tgsi_soa_context *bld, - const struct tgsi_full_instruction *inst, - const struct tgsi_opcode_info *info) -{ - unsigned chan_index; - LLVMValueRef src0, src1, src2; - LLVMValueRef tmp0, tmp1, tmp2; - LLVMValueRef tmp3 = NULL; - LLVMValueRef tmp4 = NULL; - LLVMValueRef tmp5 = NULL; - LLVMValueRef tmp6 = NULL; - LLVMValueRef tmp7 = NULL; - LLVMValueRef res; - LLVMValueRef dst0[NUM_CHANNELS]; - - /* we can't handle indirect addressing into temp register file yet */ - if (indirect_temp_reference(inst)) - return FALSE; - - assert(info->num_dst <= 1); - if(info->num_dst) { - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - dst0[chan_index] = bld->base.undef; - } - } - - switch (inst->Instruction.Opcode) { -#if 0 - case TGSI_OPCODE_ARL: - /* FIXME */ - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - tmp0 = emit_fetch( bld, inst, 0, chan_index ); - emit_flr(bld, 0, 0); - emit_f2it( bld, 0 ); - dst0[chan_index] = tmp0; - } - break; -#endif - - case TGSI_OPCODE_MOV: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - dst0[chan_index] = emit_fetch( bld, inst, 0, chan_index ); - } - break; - - case TGSI_OPCODE_LIT: - if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) ) { - dst0[CHAN_X] = bld->base.one; - } - if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) ) { - src0 = emit_fetch( bld, inst, 0, CHAN_X ); - dst0[CHAN_Y] = lp_build_max( &bld->base, src0, bld->base.zero); - } - if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) ) { - /* XMM[1] = SrcReg[0].yyyy */ - tmp1 = emit_fetch( bld, inst, 0, CHAN_Y ); - /* XMM[1] = max(XMM[1], 0) */ - tmp1 = lp_build_max( &bld->base, tmp1, bld->base.zero); - /* XMM[2] = SrcReg[0].wwww */ - tmp2 = emit_fetch( bld, inst, 0, CHAN_W ); - tmp1 = lp_build_pow( &bld->base, tmp1, tmp2); - tmp0 = emit_fetch( bld, inst, 0, CHAN_X ); - tmp2 = lp_build_cmp(&bld->base, PIPE_FUNC_GREATER, tmp0, bld->base.zero); - dst0[CHAN_Z] = lp_build_select(&bld->base, tmp2, tmp1, bld->base.zero); - } - if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_W ) ) { - dst0[CHAN_W] = bld->base.one; - } - break; - - case TGSI_OPCODE_RCP: - /* TGSI_OPCODE_RECIP */ - src0 = emit_fetch( bld, inst, 0, CHAN_X ); - res = lp_build_rcp(&bld->base, src0); - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - dst0[chan_index] = res; - } - break; - - case TGSI_OPCODE_RSQ: - /* TGSI_OPCODE_RECIPSQRT */ - src0 = emit_fetch( bld, inst, 0, CHAN_X ); - src0 = lp_build_abs(&bld->base, src0); - res = lp_build_rsqrt(&bld->base, src0); - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - dst0[chan_index] = res; - } - break; - - case TGSI_OPCODE_EXP: - if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) || - IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) || - IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z )) { - LLVMValueRef *p_exp2_int_part = NULL; - LLVMValueRef *p_frac_part = NULL; - LLVMValueRef *p_exp2 = NULL; - - src0 = emit_fetch( bld, inst, 0, CHAN_X ); - - if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X )) - p_exp2_int_part = &tmp0; - if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y )) - p_frac_part = &tmp1; - if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z )) - p_exp2 = &tmp2; - - lp_build_exp2_approx(&bld->base, src0, p_exp2_int_part, p_frac_part, p_exp2); - - if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X )) - dst0[CHAN_X] = tmp0; - if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y )) - dst0[CHAN_Y] = tmp1; - if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z )) - dst0[CHAN_Z] = tmp2; - } - /* dst.w = 1.0 */ - if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_W )) { - dst0[CHAN_W] = bld->base.one; - } - break; - - case TGSI_OPCODE_LOG: - if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) || - IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) || - IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z )) { - LLVMValueRef *p_floor_log2 = NULL; - LLVMValueRef *p_exp = NULL; - LLVMValueRef *p_log2 = NULL; - - src0 = emit_fetch( bld, inst, 0, CHAN_X ); - src0 = lp_build_abs( &bld->base, src0 ); - - if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X )) - p_floor_log2 = &tmp0; - if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y )) - p_exp = &tmp1; - if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z )) - p_log2 = &tmp2; - - lp_build_log2_approx(&bld->base, src0, p_exp, p_floor_log2, p_log2); - - /* dst.x = floor(lg2(abs(src.x))) */ - if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_X )) - dst0[CHAN_X] = tmp0; - /* dst.y = abs(src)/ex2(floor(lg2(abs(src.x)))) */ - if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y )) { - dst0[CHAN_Y] = lp_build_div( &bld->base, src0, tmp1); - } - /* dst.z = lg2(abs(src.x)) */ - if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z )) - dst0[CHAN_Z] = tmp2; - } - /* dst.w = 1.0 */ - if (IS_DST0_CHANNEL_ENABLED( inst, CHAN_W )) { - dst0[CHAN_W] = bld->base.one; - } - break; - - case TGSI_OPCODE_MUL: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - src0 = emit_fetch( bld, inst, 0, chan_index ); - src1 = emit_fetch( bld, inst, 1, chan_index ); - dst0[chan_index] = lp_build_mul(&bld->base, src0, src1); - } - break; - - case TGSI_OPCODE_ADD: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - src0 = emit_fetch( bld, inst, 0, chan_index ); - src1 = emit_fetch( bld, inst, 1, chan_index ); - dst0[chan_index] = lp_build_add(&bld->base, src0, src1); - } - break; - - case TGSI_OPCODE_DP3: - /* TGSI_OPCODE_DOT3 */ - tmp0 = emit_fetch( bld, inst, 0, CHAN_X ); - tmp1 = emit_fetch( bld, inst, 1, CHAN_X ); - tmp0 = lp_build_mul( &bld->base, tmp0, tmp1); - tmp1 = emit_fetch( bld, inst, 0, CHAN_Y ); - tmp2 = emit_fetch( bld, inst, 1, CHAN_Y ); - tmp1 = lp_build_mul( &bld->base, tmp1, tmp2); - tmp0 = lp_build_add( &bld->base, tmp0, tmp1); - tmp1 = emit_fetch( bld, inst, 0, CHAN_Z ); - tmp2 = emit_fetch( bld, inst, 1, CHAN_Z ); - tmp1 = lp_build_mul( &bld->base, tmp1, tmp2); - tmp0 = lp_build_add( &bld->base, tmp0, tmp1); - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - dst0[chan_index] = tmp0; - } - break; - - case TGSI_OPCODE_DP4: - /* TGSI_OPCODE_DOT4 */ - tmp0 = emit_fetch( bld, inst, 0, CHAN_X ); - tmp1 = emit_fetch( bld, inst, 1, CHAN_X ); - tmp0 = lp_build_mul( &bld->base, tmp0, tmp1); - tmp1 = emit_fetch( bld, inst, 0, CHAN_Y ); - tmp2 = emit_fetch( bld, inst, 1, CHAN_Y ); - tmp1 = lp_build_mul( &bld->base, tmp1, tmp2); - tmp0 = lp_build_add( &bld->base, tmp0, tmp1); - tmp1 = emit_fetch( bld, inst, 0, CHAN_Z ); - tmp2 = emit_fetch( bld, inst, 1, CHAN_Z ); - tmp1 = lp_build_mul( &bld->base, tmp1, tmp2); - tmp0 = lp_build_add( &bld->base, tmp0, tmp1); - tmp1 = emit_fetch( bld, inst, 0, CHAN_W ); - tmp2 = emit_fetch( bld, inst, 1, CHAN_W ); - tmp1 = lp_build_mul( &bld->base, tmp1, tmp2); - tmp0 = lp_build_add( &bld->base, tmp0, tmp1); - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - dst0[chan_index] = tmp0; - } - break; - - case TGSI_OPCODE_DST: - IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) { - dst0[CHAN_X] = bld->base.one; - } - IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) { - tmp0 = emit_fetch( bld, inst, 0, CHAN_Y ); - tmp1 = emit_fetch( bld, inst, 1, CHAN_Y ); - dst0[CHAN_Y] = lp_build_mul( &bld->base, tmp0, tmp1); - } - IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) { - dst0[CHAN_Z] = emit_fetch( bld, inst, 0, CHAN_Z ); - } - IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_W ) { - dst0[CHAN_W] = emit_fetch( bld, inst, 1, CHAN_W ); - } - break; - - case TGSI_OPCODE_MIN: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - src0 = emit_fetch( bld, inst, 0, chan_index ); - src1 = emit_fetch( bld, inst, 1, chan_index ); - dst0[chan_index] = lp_build_min( &bld->base, src0, src1 ); - } - break; - - case TGSI_OPCODE_MAX: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - src0 = emit_fetch( bld, inst, 0, chan_index ); - src1 = emit_fetch( bld, inst, 1, chan_index ); - dst0[chan_index] = lp_build_max( &bld->base, src0, src1 ); - } - break; - - case TGSI_OPCODE_SLT: - /* TGSI_OPCODE_SETLT */ - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - src0 = emit_fetch( bld, inst, 0, chan_index ); - src1 = emit_fetch( bld, inst, 1, chan_index ); - tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_LESS, src0, src1 ); - dst0[chan_index] = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero ); - } - break; - - case TGSI_OPCODE_SGE: - /* TGSI_OPCODE_SETGE */ - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - src0 = emit_fetch( bld, inst, 0, chan_index ); - src1 = emit_fetch( bld, inst, 1, chan_index ); - tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_GEQUAL, src0, src1 ); - dst0[chan_index] = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero ); - } - break; - - case TGSI_OPCODE_MAD: - /* TGSI_OPCODE_MADD */ - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - tmp0 = emit_fetch( bld, inst, 0, chan_index ); - tmp1 = emit_fetch( bld, inst, 1, chan_index ); - tmp2 = emit_fetch( bld, inst, 2, chan_index ); - tmp0 = lp_build_mul( &bld->base, tmp0, tmp1); - tmp0 = lp_build_add( &bld->base, tmp0, tmp2); - dst0[chan_index] = tmp0; - } - break; - - case TGSI_OPCODE_SUB: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - tmp0 = emit_fetch( bld, inst, 0, chan_index ); - tmp1 = emit_fetch( bld, inst, 1, chan_index ); - dst0[chan_index] = lp_build_sub( &bld->base, tmp0, tmp1); - } - break; - - case TGSI_OPCODE_LRP: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - src0 = emit_fetch( bld, inst, 0, chan_index ); - src1 = emit_fetch( bld, inst, 1, chan_index ); - src2 = emit_fetch( bld, inst, 2, chan_index ); - tmp0 = lp_build_sub( &bld->base, src1, src2 ); - tmp0 = lp_build_mul( &bld->base, src0, tmp0 ); - dst0[chan_index] = lp_build_add( &bld->base, tmp0, src2 ); - } - break; - - case TGSI_OPCODE_CND: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - src0 = emit_fetch( bld, inst, 0, chan_index ); - src1 = emit_fetch( bld, inst, 1, chan_index ); - src2 = emit_fetch( bld, inst, 2, chan_index ); - tmp1 = lp_build_const_scalar(bld->base.type, 0.5); - tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_GREATER, src2, tmp1); - dst0[chan_index] = lp_build_select( &bld->base, tmp0, src0, src1 ); - } - break; - - case TGSI_OPCODE_DP2A: - tmp0 = emit_fetch( bld, inst, 0, CHAN_X ); /* xmm0 = src[0].x */ - tmp1 = emit_fetch( bld, inst, 1, CHAN_X ); /* xmm1 = src[1].x */ - tmp0 = lp_build_mul( &bld->base, tmp0, tmp1); /* xmm0 = xmm0 * xmm1 */ - tmp1 = emit_fetch( bld, inst, 0, CHAN_Y ); /* xmm1 = src[0].y */ - tmp2 = emit_fetch( bld, inst, 1, CHAN_Y ); /* xmm2 = src[1].y */ - tmp1 = lp_build_mul( &bld->base, tmp1, tmp2); /* xmm1 = xmm1 * xmm2 */ - tmp0 = lp_build_add( &bld->base, tmp0, tmp1); /* xmm0 = xmm0 + xmm1 */ - tmp1 = emit_fetch( bld, inst, 2, CHAN_X ); /* xmm1 = src[2].x */ - tmp0 = lp_build_add( &bld->base, tmp0, tmp1); /* xmm0 = xmm0 + xmm1 */ - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - dst0[chan_index] = tmp0; /* dest[ch] = xmm0 */ - } - break; - - case TGSI_OPCODE_FRC: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - src0 = emit_fetch( bld, inst, 0, chan_index ); - tmp0 = lp_build_floor(&bld->base, src0); - tmp0 = lp_build_sub(&bld->base, src0, tmp0); - dst0[chan_index] = tmp0; - } - break; - - case TGSI_OPCODE_CLAMP: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - tmp0 = emit_fetch( bld, inst, 0, chan_index ); - src1 = emit_fetch( bld, inst, 1, chan_index ); - src2 = emit_fetch( bld, inst, 2, chan_index ); - tmp0 = lp_build_max(&bld->base, tmp0, src1); - tmp0 = lp_build_min(&bld->base, tmp0, src2); - dst0[chan_index] = tmp0; - } - break; - - case TGSI_OPCODE_FLR: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - tmp0 = emit_fetch( bld, inst, 0, chan_index ); - dst0[chan_index] = lp_build_floor(&bld->base, tmp0); - } - break; - - case TGSI_OPCODE_ROUND: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - tmp0 = emit_fetch( bld, inst, 0, chan_index ); - dst0[chan_index] = lp_build_round(&bld->base, tmp0); - } - break; - - case TGSI_OPCODE_EX2: { - tmp0 = emit_fetch( bld, inst, 0, CHAN_X ); - tmp0 = lp_build_exp2( &bld->base, tmp0); - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - dst0[chan_index] = tmp0; - } - break; - } - - case TGSI_OPCODE_LG2: - tmp0 = emit_fetch( bld, inst, 0, CHAN_X ); - tmp0 = lp_build_log2( &bld->base, tmp0); - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - dst0[chan_index] = tmp0; - } - break; - - case TGSI_OPCODE_POW: - src0 = emit_fetch( bld, inst, 0, CHAN_X ); - src1 = emit_fetch( bld, inst, 1, CHAN_X ); - res = lp_build_pow( &bld->base, src0, src1 ); - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - dst0[chan_index] = res; - } - break; - - case TGSI_OPCODE_XPD: - if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) || - IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) ) { - tmp1 = emit_fetch( bld, inst, 1, CHAN_Z ); - tmp3 = emit_fetch( bld, inst, 0, CHAN_Z ); - } - if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) || - IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) ) { - tmp0 = emit_fetch( bld, inst, 0, CHAN_Y ); - tmp4 = emit_fetch( bld, inst, 1, CHAN_Y ); - } - IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) { - tmp2 = tmp0; - tmp2 = lp_build_mul( &bld->base, tmp2, tmp1); - tmp5 = tmp3; - tmp5 = lp_build_mul( &bld->base, tmp5, tmp4); - tmp2 = lp_build_sub( &bld->base, tmp2, tmp5); - dst0[CHAN_X] = tmp2; - } - if( IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) || - IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) ) { - tmp2 = emit_fetch( bld, inst, 1, CHAN_X ); - tmp5 = emit_fetch( bld, inst, 0, CHAN_X ); - } - IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) { - tmp3 = lp_build_mul( &bld->base, tmp3, tmp2); - tmp1 = lp_build_mul( &bld->base, tmp1, tmp5); - tmp3 = lp_build_sub( &bld->base, tmp3, tmp1); - dst0[CHAN_Y] = tmp3; - } - IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) { - tmp5 = lp_build_mul( &bld->base, tmp5, tmp4); - tmp0 = lp_build_mul( &bld->base, tmp0, tmp2); - tmp5 = lp_build_sub( &bld->base, tmp5, tmp0); - dst0[CHAN_Z] = tmp5; - } - IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_W ) { - dst0[CHAN_W] = bld->base.one; - } - break; - - case TGSI_OPCODE_ABS: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - tmp0 = emit_fetch( bld, inst, 0, chan_index ); - dst0[chan_index] = lp_build_abs( &bld->base, tmp0 ); - } - break; - - case TGSI_OPCODE_RCC: - /* deprecated? */ - assert(0); - return 0; - - case TGSI_OPCODE_DPH: - tmp0 = emit_fetch( bld, inst, 0, CHAN_X ); - tmp1 = emit_fetch( bld, inst, 1, CHAN_X ); - tmp0 = lp_build_mul( &bld->base, tmp0, tmp1); - tmp1 = emit_fetch( bld, inst, 0, CHAN_Y ); - tmp2 = emit_fetch( bld, inst, 1, CHAN_Y ); - tmp1 = lp_build_mul( &bld->base, tmp1, tmp2); - tmp0 = lp_build_add( &bld->base, tmp0, tmp1); - tmp1 = emit_fetch( bld, inst, 0, CHAN_Z ); - tmp2 = emit_fetch( bld, inst, 1, CHAN_Z ); - tmp1 = lp_build_mul( &bld->base, tmp1, tmp2); - tmp0 = lp_build_add( &bld->base, tmp0, tmp1); - tmp1 = emit_fetch( bld, inst, 1, CHAN_W ); - tmp0 = lp_build_add( &bld->base, tmp0, tmp1); - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - dst0[chan_index] = tmp0; - } - break; - - case TGSI_OPCODE_COS: - tmp0 = emit_fetch( bld, inst, 0, CHAN_X ); - tmp0 = lp_build_cos( &bld->base, tmp0 ); - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - dst0[chan_index] = tmp0; - } - break; - - case TGSI_OPCODE_DDX: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - emit_fetch_deriv( bld, inst, 0, chan_index, NULL, &dst0[chan_index], NULL); - } - break; - - case TGSI_OPCODE_DDY: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - emit_fetch_deriv( bld, inst, 0, chan_index, NULL, NULL, &dst0[chan_index]); - } - break; - - case TGSI_OPCODE_KILP: - /* predicated kill */ - /* FIXME */ - return 0; - break; - - case TGSI_OPCODE_KIL: - /* conditional kill */ - emit_kil( bld, inst ); - break; - - case TGSI_OPCODE_PK2H: - return 0; - break; - - case TGSI_OPCODE_PK2US: - return 0; - break; - - case TGSI_OPCODE_PK4B: - return 0; - break; - - case TGSI_OPCODE_PK4UB: - return 0; - break; - - case TGSI_OPCODE_RFL: - return 0; - break; - - case TGSI_OPCODE_SEQ: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - src0 = emit_fetch( bld, inst, 0, chan_index ); - src1 = emit_fetch( bld, inst, 1, chan_index ); - tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_EQUAL, src0, src1 ); - dst0[chan_index] = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero ); - } - break; - - case TGSI_OPCODE_SFL: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - dst0[chan_index] = bld->base.zero; - } - break; - - case TGSI_OPCODE_SGT: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - src0 = emit_fetch( bld, inst, 0, chan_index ); - src1 = emit_fetch( bld, inst, 1, chan_index ); - tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_GREATER, src0, src1 ); - dst0[chan_index] = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero ); - } - break; - - case TGSI_OPCODE_SIN: - tmp0 = emit_fetch( bld, inst, 0, CHAN_X ); - tmp0 = lp_build_sin( &bld->base, tmp0 ); - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - dst0[chan_index] = tmp0; - } - break; - - case TGSI_OPCODE_SLE: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - src0 = emit_fetch( bld, inst, 0, chan_index ); - src1 = emit_fetch( bld, inst, 1, chan_index ); - tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_LEQUAL, src0, src1 ); - dst0[chan_index] = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero ); - } - break; - - case TGSI_OPCODE_SNE: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - src0 = emit_fetch( bld, inst, 0, chan_index ); - src1 = emit_fetch( bld, inst, 1, chan_index ); - tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_NOTEQUAL, src0, src1 ); - dst0[chan_index] = lp_build_select( &bld->base, tmp0, bld->base.one, bld->base.zero ); - } - break; - - case TGSI_OPCODE_STR: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - dst0[chan_index] = bld->base.one; - } - break; - - case TGSI_OPCODE_TEX: - emit_tex( bld, inst, FALSE, FALSE, dst0 ); - break; - - case TGSI_OPCODE_TXD: - /* FIXME */ - return 0; - break; - - case TGSI_OPCODE_UP2H: - /* deprecated */ - assert (0); - return 0; - break; - - case TGSI_OPCODE_UP2US: - /* deprecated */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_UP4B: - /* deprecated */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_UP4UB: - /* deprecated */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_X2D: - /* deprecated? */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_ARA: - /* deprecated */ - assert(0); - return 0; - break; - -#if 0 - case TGSI_OPCODE_ARR: - /* FIXME */ - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - tmp0 = emit_fetch( bld, inst, 0, chan_index ); - emit_rnd( bld, 0, 0 ); - emit_f2it( bld, 0 ); - dst0[chan_index] = tmp0; - } - break; -#endif - - case TGSI_OPCODE_BRA: - /* deprecated */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_CAL: - /* FIXME */ - return 0; - break; - - case TGSI_OPCODE_RET: - /* FIXME */ - return 0; - break; - - case TGSI_OPCODE_END: - break; - - case TGSI_OPCODE_SSG: - /* TGSI_OPCODE_SGN */ - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - tmp0 = emit_fetch( bld, inst, 0, chan_index ); - dst0[chan_index] = lp_build_sgn( &bld->base, tmp0 ); - } - break; - - case TGSI_OPCODE_CMP: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - src0 = emit_fetch( bld, inst, 0, chan_index ); - src1 = emit_fetch( bld, inst, 1, chan_index ); - src2 = emit_fetch( bld, inst, 2, chan_index ); - tmp0 = lp_build_cmp( &bld->base, PIPE_FUNC_LESS, src0, bld->base.zero ); - dst0[chan_index] = lp_build_select( &bld->base, tmp0, src1, src2); - } - break; - - case TGSI_OPCODE_SCS: - IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_X ) { - tmp0 = emit_fetch( bld, inst, 0, CHAN_X ); - dst0[CHAN_X] = lp_build_cos( &bld->base, tmp0 ); - } - IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Y ) { - tmp0 = emit_fetch( bld, inst, 0, CHAN_X ); - dst0[CHAN_Y] = lp_build_sin( &bld->base, tmp0 ); - } - IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_Z ) { - dst0[CHAN_Z] = bld->base.zero; - } - IF_IS_DST0_CHANNEL_ENABLED( inst, CHAN_W ) { - dst0[CHAN_W] = bld->base.one; - } - break; - - case TGSI_OPCODE_TXB: - emit_tex( bld, inst, TRUE, FALSE, dst0 ); - break; - - case TGSI_OPCODE_NRM: - /* fall-through */ - case TGSI_OPCODE_NRM4: - /* 3 or 4-component normalization */ - { - uint dims = (inst->Instruction.Opcode == TGSI_OPCODE_NRM) ? 3 : 4; - - if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_X) || - IS_DST0_CHANNEL_ENABLED(inst, CHAN_Y) || - IS_DST0_CHANNEL_ENABLED(inst, CHAN_Z) || - (IS_DST0_CHANNEL_ENABLED(inst, CHAN_W) && dims == 4)) { - - /* NOTE: Cannot use xmm regs 2/3 here (see emit_rsqrt() above). */ - - /* xmm4 = src.x */ - /* xmm0 = src.x * src.x */ - tmp0 = emit_fetch(bld, inst, 0, CHAN_X); - if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_X)) { - tmp4 = tmp0; - } - tmp0 = lp_build_mul( &bld->base, tmp0, tmp0); - - /* xmm5 = src.y */ - /* xmm0 = xmm0 + src.y * src.y */ - tmp1 = emit_fetch(bld, inst, 0, CHAN_Y); - if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_Y)) { - tmp5 = tmp1; - } - tmp1 = lp_build_mul( &bld->base, tmp1, tmp1); - tmp0 = lp_build_add( &bld->base, tmp0, tmp1); - - /* xmm6 = src.z */ - /* xmm0 = xmm0 + src.z * src.z */ - tmp1 = emit_fetch(bld, inst, 0, CHAN_Z); - if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_Z)) { - tmp6 = tmp1; - } - tmp1 = lp_build_mul( &bld->base, tmp1, tmp1); - tmp0 = lp_build_add( &bld->base, tmp0, tmp1); - - if (dims == 4) { - /* xmm7 = src.w */ - /* xmm0 = xmm0 + src.w * src.w */ - tmp1 = emit_fetch(bld, inst, 0, CHAN_W); - if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_W)) { - tmp7 = tmp1; - } - tmp1 = lp_build_mul( &bld->base, tmp1, tmp1); - tmp0 = lp_build_add( &bld->base, tmp0, tmp1); - } - - /* xmm1 = 1 / sqrt(xmm0) */ - tmp1 = lp_build_rsqrt( &bld->base, tmp0); - - /* dst.x = xmm1 * src.x */ - if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_X)) { - dst0[CHAN_X] = lp_build_mul( &bld->base, tmp4, tmp1); - } - - /* dst.y = xmm1 * src.y */ - if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_Y)) { - dst0[CHAN_Y] = lp_build_mul( &bld->base, tmp5, tmp1); - } - - /* dst.z = xmm1 * src.z */ - if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_Z)) { - dst0[CHAN_Z] = lp_build_mul( &bld->base, tmp6, tmp1); - } - - /* dst.w = xmm1 * src.w */ - if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_X) && dims == 4) { - dst0[CHAN_W] = lp_build_mul( &bld->base, tmp7, tmp1); - } - } - - /* dst.w = 1.0 */ - if (IS_DST0_CHANNEL_ENABLED(inst, CHAN_W) && dims == 3) { - dst0[CHAN_W] = bld->base.one; - } - } - break; - - case TGSI_OPCODE_DIV: - /* deprecated */ - assert( 0 ); - return 0; - break; - - case TGSI_OPCODE_DP2: - tmp0 = emit_fetch( bld, inst, 0, CHAN_X ); /* xmm0 = src[0].x */ - tmp1 = emit_fetch( bld, inst, 1, CHAN_X ); /* xmm1 = src[1].x */ - tmp0 = lp_build_mul( &bld->base, tmp0, tmp1); /* xmm0 = xmm0 * xmm1 */ - tmp1 = emit_fetch( bld, inst, 0, CHAN_Y ); /* xmm1 = src[0].y */ - tmp2 = emit_fetch( bld, inst, 1, CHAN_Y ); /* xmm2 = src[1].y */ - tmp1 = lp_build_mul( &bld->base, tmp1, tmp2); /* xmm1 = xmm1 * xmm2 */ - tmp0 = lp_build_add( &bld->base, tmp0, tmp1); /* xmm0 = xmm0 + xmm1 */ - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - dst0[chan_index] = tmp0; /* dest[ch] = xmm0 */ - } - break; - - case TGSI_OPCODE_TXL: - emit_tex( bld, inst, TRUE, FALSE, dst0 ); - break; - - case TGSI_OPCODE_TXP: - emit_tex( bld, inst, FALSE, TRUE, dst0 ); - break; - - case TGSI_OPCODE_BRK: - /* FIXME */ - return 0; - break; - - case TGSI_OPCODE_IF: - /* FIXME */ - return 0; - break; - - case TGSI_OPCODE_BGNFOR: - /* deprecated */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_REP: - /* deprecated */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_ELSE: - /* FIXME */ - return 0; - break; - - case TGSI_OPCODE_ENDIF: - /* FIXME */ - return 0; - break; - - case TGSI_OPCODE_ENDFOR: - /* deprecated */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_ENDREP: - /* deprecated */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_PUSHA: - /* deprecated? */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_POPA: - /* deprecated? */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_CEIL: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - tmp0 = emit_fetch( bld, inst, 0, chan_index ); - dst0[chan_index] = lp_build_ceil(&bld->base, tmp0); - } - break; - - case TGSI_OPCODE_I2F: - /* deprecated? */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_NOT: - /* deprecated? */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_TRUNC: - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - tmp0 = emit_fetch( bld, inst, 0, chan_index ); - dst0[chan_index] = lp_build_trunc(&bld->base, tmp0); - } - break; - - case TGSI_OPCODE_SHL: - /* deprecated? */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_ISHR: - /* deprecated? */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_AND: - /* deprecated? */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_OR: - /* deprecated? */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_MOD: - /* deprecated? */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_XOR: - /* deprecated? */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_SAD: - /* deprecated? */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_TXF: - /* deprecated? */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_TXQ: - /* deprecated? */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_CONT: - /* deprecated? */ - assert(0); - return 0; - break; - - case TGSI_OPCODE_EMIT: - return 0; - break; - - case TGSI_OPCODE_ENDPRIM: - return 0; - break; - - case TGSI_OPCODE_NOP: - break; - - default: - return 0; - } - - if(info->num_dst) { - FOR_EACH_DST0_ENABLED_CHANNEL( inst, chan_index ) { - emit_store( bld, inst, 0, chan_index, dst0[chan_index]); - } - } - - return 1; -} - - -void -lp_build_tgsi_soa(LLVMBuilderRef builder, - const struct tgsi_token *tokens, - struct lp_type type, - struct lp_build_mask_context *mask, - LLVMValueRef consts_ptr, - const LLVMValueRef *pos, - const LLVMValueRef (*inputs)[NUM_CHANNELS], - LLVMValueRef (*outputs)[NUM_CHANNELS], - struct lp_build_sampler_soa *sampler) -{ - struct lp_build_tgsi_soa_context bld; - struct tgsi_parse_context parse; - uint num_immediates = 0; - unsigned i; - - /* Setup build context */ - memset(&bld, 0, sizeof bld); - lp_build_context_init(&bld.base, builder, type); - bld.mask = mask; - bld.pos = pos; - bld.inputs = inputs; - bld.outputs = outputs; - bld.consts_ptr = consts_ptr; - bld.sampler = sampler; - - tgsi_parse_init( &parse, tokens ); - - while( !tgsi_parse_end_of_tokens( &parse ) ) { - tgsi_parse_token( &parse ); - - switch( parse.FullToken.Token.Type ) { - case TGSI_TOKEN_TYPE_DECLARATION: - /* Inputs already interpolated */ - break; - - case TGSI_TOKEN_TYPE_INSTRUCTION: - { - unsigned opcode = parse.FullToken.FullInstruction.Instruction.Opcode; - const struct tgsi_opcode_info *info = tgsi_get_opcode_info(opcode); - if (!emit_instruction( &bld, &parse.FullToken.FullInstruction, info )) - _debug_printf("warning: failed to translate tgsi opcode %s to LLVM\n", - info ? info->mnemonic : "<invalid>"); - } - - break; - - case TGSI_TOKEN_TYPE_IMMEDIATE: - /* simply copy the immediate values into the next immediates[] slot */ - { - const uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1; - assert(size <= 4); - assert(num_immediates < LP_MAX_IMMEDIATES); - for( i = 0; i < size; ++i ) - bld.immediates[num_immediates][i] = - lp_build_const_scalar(type, parse.FullToken.FullImmediate.u[i].Float); - for( i = size; i < 4; ++i ) - bld.immediates[num_immediates][i] = bld.base.undef; - num_immediates++; - } - break; - - default: - assert( 0 ); - } - } - - tgsi_parse_free( &parse ); -} - diff --git a/src/gallium/drivers/llvmpipe/lp_bld_type.c b/src/gallium/drivers/llvmpipe/lp_bld_type.c deleted file mode 100644 index 1320a26721..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_type.c +++ /dev/null @@ -1,201 +0,0 @@ -/************************************************************************** - * - * 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_debug.h" - -#include "lp_bld_type.h" -#include "lp_bld_const.h" - - -LLVMTypeRef -lp_build_elem_type(struct lp_type type) -{ - if (type.floating) { - switch(type.width) { - case 32: - return LLVMFloatType(); - break; - case 64: - return LLVMDoubleType(); - break; - default: - assert(0); - return LLVMFloatType(); - } - } - else { - return LLVMIntType(type.width); - } -} - - -LLVMTypeRef -lp_build_vec_type(struct lp_type type) -{ - LLVMTypeRef elem_type = lp_build_elem_type(type); - return LLVMVectorType(elem_type, type.length); -} - - -/** - * This function is a mirror of lp_build_elem_type() above. - * - * XXX: I'm not sure if it wouldn't be easier/efficient to just recreate the - * type and check for identity. - */ -boolean -lp_check_elem_type(struct lp_type type, LLVMTypeRef elem_type) -{ - LLVMTypeKind elem_kind; - - assert(elem_type); - if(!elem_type) - return FALSE; - - elem_kind = LLVMGetTypeKind(elem_type); - - if (type.floating) { - switch(type.width) { - case 32: - if(elem_kind != LLVMFloatTypeKind) - return FALSE; - break; - case 64: - if(elem_kind != LLVMDoubleTypeKind) - return FALSE; - break; - default: - assert(0); - return FALSE; - } - } - else { - if(elem_kind != LLVMIntegerTypeKind) - return FALSE; - - if(LLVMGetIntTypeWidth(elem_type) != type.width) - return FALSE; - } - - return TRUE; -} - - -boolean -lp_check_vec_type(struct lp_type type, LLVMTypeRef vec_type) -{ - LLVMTypeRef elem_type; - - assert(vec_type); - if(!vec_type) - return FALSE; - - if(LLVMGetTypeKind(vec_type) != LLVMVectorTypeKind) - return FALSE; - - if(LLVMGetVectorSize(vec_type) != type.length) - return FALSE; - - elem_type = LLVMGetElementType(vec_type); - - return lp_check_elem_type(type, elem_type); -} - - -boolean -lp_check_value(struct lp_type type, LLVMValueRef val) -{ - LLVMTypeRef vec_type; - - assert(val); - if(!val) - return FALSE; - - vec_type = LLVMTypeOf(val); - - return lp_check_vec_type(type, vec_type); -} - - -LLVMTypeRef -lp_build_int_elem_type(struct lp_type type) -{ - return LLVMIntType(type.width); -} - - -LLVMTypeRef -lp_build_int_vec_type(struct lp_type type) -{ - LLVMTypeRef elem_type = lp_build_int_elem_type(type); - return LLVMVectorType(elem_type, type.length); -} - - -struct lp_type -lp_int_type(struct lp_type type) -{ - struct lp_type res_type; - - memset(&res_type, 0, sizeof res_type); - res_type.width = type.width; - res_type.length = type.length; - - return res_type; -} - - -/** - * Return the type with twice the bit width (hence half the number of elements). - */ -struct lp_type -lp_wider_type(struct lp_type type) -{ - struct lp_type res_type; - - memcpy(&res_type, &type, sizeof res_type); - res_type.width *= 2; - res_type.length /= 2; - - assert(res_type.length); - - return res_type; -} - - -void -lp_build_context_init(struct lp_build_context *bld, - LLVMBuilderRef builder, - struct lp_type type) -{ - bld->builder = builder; - bld->type = type; - bld->undef = lp_build_undef(type); - bld->zero = lp_build_zero(type); - bld->one = lp_build_one(type); -} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_type.h b/src/gallium/drivers/llvmpipe/lp_bld_type.h deleted file mode 100644 index 2fb233d335..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_bld_type.h +++ /dev/null @@ -1,269 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 VMware, Inc. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -/** - * @file - * Convenient representation of SIMD types. - * - * @author Jose Fonseca <jfonseca@vmware.com> - */ - - -#ifndef LP_BLD_TYPE_H -#define LP_BLD_TYPE_H - - -#include <llvm-c/Core.h> - -#include <pipe/p_compiler.h> - - -/** - * Native SIMD register width. - * - * 128 for all architectures we care about. - */ -#define LP_NATIVE_VECTOR_WIDTH 128 - -/** - * Several functions can only cope with vectors of length up to this value. - * You may need to increase that value if you want to represent bigger vectors. - */ -#define LP_MAX_VECTOR_LENGTH 16 - - -/** - * The LLVM type system can't conveniently express all the things we care about - * on the types used for intermediate computations, such as signed vs unsigned, - * normalized values, or fixed point. - */ -struct lp_type { - /** - * Floating-point. Cannot be used with fixed. Integer numbers are - * represented by this zero. - */ - unsigned floating:1; - - /** - * Fixed-point. Cannot be used with floating. Integer numbers are - * represented by this zero. - */ - unsigned fixed:1; - - /** - * Whether it can represent negative values or not. - * - * If this is not set for floating point, it means that all values are - * assumed to be positive. - */ - unsigned sign:1; - - /** - * Whether values are normalized to fit [0, 1] interval, or [-1, 1] - * interval for signed types. - * - * For integer types it means the representable integer range should be - * interpreted as the interval above. - * - * For floating and fixed point formats it means the values should be - * clamped to the interval above. - */ - unsigned norm:1; - - /** - * Element width. - * - * For fixed point values, the fixed point is assumed to be at half the - * width. - */ - unsigned width:14; - - /** - * Vector length. - * - * width*length should be a power of two greater or equal to eight. - * - * @sa LP_MAX_VECTOR_LENGTH - */ - unsigned length:14; -}; - - -/** - * We need most of the information here in order to correctly and efficiently - * translate an arithmetic operation into LLVM IR. Putting it here avoids the - * trouble of passing it as parameters. - */ -struct lp_build_context -{ - LLVMBuilderRef builder; - - /** - * This not only describes the input/output LLVM types, but also whether - * to normalize/clamp the results. - */ - struct lp_type type; - - /** Same as lp_build_undef(type) */ - LLVMValueRef undef; - - /** Same as lp_build_zero(type) */ - LLVMValueRef zero; - - /** Same as lp_build_one(type) */ - LLVMValueRef one; -}; - - -static INLINE struct lp_type -lp_type_float(unsigned width) -{ - struct lp_type res_type; - - memset(&res_type, 0, sizeof res_type); - res_type.floating = TRUE; - res_type.sign = TRUE; - res_type.width = width; - res_type.length = LP_NATIVE_VECTOR_WIDTH / width; - - return res_type; -} - - -static INLINE struct lp_type -lp_type_int(unsigned width) -{ - struct lp_type res_type; - - memset(&res_type, 0, sizeof res_type); - res_type.sign = TRUE; - res_type.width = width; - res_type.length = LP_NATIVE_VECTOR_WIDTH / width; - - return res_type; -} - - -static INLINE struct lp_type -lp_type_uint(unsigned width) -{ - struct lp_type res_type; - - memset(&res_type, 0, sizeof res_type); - res_type.width = width; - res_type.length = LP_NATIVE_VECTOR_WIDTH / width; - - return res_type; -} - - -static INLINE struct lp_type -lp_type_unorm(unsigned width) -{ - struct lp_type res_type; - - memset(&res_type, 0, sizeof res_type); - res_type.norm = TRUE; - res_type.width = width; - res_type.length = LP_NATIVE_VECTOR_WIDTH / width; - - return res_type; -} - - -static INLINE struct lp_type -lp_type_fixed(unsigned width) -{ - struct lp_type res_type; - - memset(&res_type, 0, sizeof res_type); - res_type.sign = TRUE; - res_type.fixed = TRUE; - res_type.width = width; - res_type.length = LP_NATIVE_VECTOR_WIDTH / width; - - return res_type; -} - - -static INLINE struct lp_type -lp_type_ufixed(unsigned width) -{ - struct lp_type res_type; - - memset(&res_type, 0, sizeof res_type); - res_type.fixed = TRUE; - res_type.width = width; - res_type.length = LP_NATIVE_VECTOR_WIDTH / width; - - return res_type; -} - - -LLVMTypeRef -lp_build_elem_type(struct lp_type type); - - -LLVMTypeRef -lp_build_vec_type(struct lp_type type); - - -boolean -lp_check_elem_type(struct lp_type type, LLVMTypeRef elem_type); - - -boolean -lp_check_vec_type(struct lp_type type, LLVMTypeRef vec_type); - - -boolean -lp_check_value(struct lp_type type, LLVMValueRef val); - - -LLVMTypeRef -lp_build_int_elem_type(struct lp_type type); - - -LLVMTypeRef -lp_build_int_vec_type(struct lp_type type); - - -struct lp_type -lp_int_type(struct lp_type type); - - -struct lp_type -lp_wider_type(struct lp_type type); - - -void -lp_build_context_init(struct lp_build_context *bld, - LLVMBuilderRef builder, - struct lp_type type); - - -#endif /* !LP_BLD_TYPE_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_buffer.c b/src/gallium/drivers/llvmpipe/lp_buffer.c index 66f1f8e138..9eda972081 100644 --- a/src/gallium/drivers/llvmpipe/lp_buffer.c +++ b/src/gallium/drivers/llvmpipe/lp_buffer.c @@ -26,12 +26,12 @@ **************************************************************************/ +#include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_math.h" #include "lp_winsys.h" #include "lp_screen.h" -#include "lp_texture.h" #include "lp_buffer.h" @@ -108,32 +108,6 @@ llvmpipe_user_buffer_create(struct pipe_screen *screen, } -static void -llvmpipe_fence_reference(struct pipe_screen *screen, - struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence) -{ -} - - -static int -llvmpipe_fence_signalled(struct pipe_screen *screen, - struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - -static int -llvmpipe_fence_finish(struct pipe_screen *screen, - struct pipe_fence_handle *fence, - unsigned flag) -{ - return 0; -} - - void llvmpipe_init_screen_buffer_funcs(struct pipe_screen *screen) { @@ -142,9 +116,4 @@ llvmpipe_init_screen_buffer_funcs(struct pipe_screen *screen) screen->buffer_map = llvmpipe_buffer_map; screen->buffer_unmap = llvmpipe_buffer_unmap; screen->buffer_destroy = llvmpipe_buffer_destroy; - - screen->fence_reference = llvmpipe_fence_reference; - screen->fence_signalled = llvmpipe_fence_signalled; - screen->fence_finish = llvmpipe_fence_finish; - } diff --git a/src/gallium/drivers/llvmpipe/lp_clear.c b/src/gallium/drivers/llvmpipe/lp_clear.c index 08d9f2e273..3e8c410925 100644 --- a/src/gallium/drivers/llvmpipe/lp_clear.c +++ b/src/gallium/drivers/llvmpipe/lp_clear.c @@ -33,12 +33,9 @@ #include "pipe/p_defines.h" -#include "util/u_pack_color.h" #include "lp_clear.h" #include "lp_context.h" -#include "lp_surface.h" -#include "lp_state.h" -#include "lp_tile_cache.h" +#include "lp_setup.h" /** @@ -46,37 +43,16 @@ * No masking, no scissor (clear entire buffer). */ void -llvmpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba, - double depth, unsigned stencil) +llvmpipe_clear(struct pipe_context *pipe, + unsigned buffers, + const float *rgba, + double depth, + unsigned stencil) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); - union util_color uc; - unsigned cv; - uint i; if (llvmpipe->no_rast) return; -#if 0 - llvmpipe_update_derived(llvmpipe); /* not needed?? */ -#endif - - if (buffers & PIPE_CLEAR_COLOR) { - for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++) { - struct pipe_surface *ps = llvmpipe->framebuffer.cbufs[i]; - - util_pack_color(rgba, ps->format, &uc); - lp_tile_cache_clear(llvmpipe->cbuf_cache[i], rgba, uc.ui); - } - llvmpipe->dirty_render_cache = TRUE; - } - - if (buffers & PIPE_CLEAR_DEPTHSTENCIL) { - struct pipe_surface *ps = llvmpipe->framebuffer.zsbuf; - - cv = util_pack_z_stencil(ps->format, depth, stencil); - - /* non-cached surface */ - pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, cv); - } + lp_setup_clear( llvmpipe->setup, rgba, depth, stencil, buffers ); } diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c index 1cc3c9227c..43d610631d 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.c +++ b/src/gallium/drivers/llvmpipe/lp_context.c @@ -33,70 +33,22 @@ #include "draw/draw_context.h" #include "draw/draw_vbuf.h" #include "pipe/p_defines.h" +#include "util/u_inlines.h" #include "util/u_math.h" #include "util/u_memory.h" #include "lp_clear.h" #include "lp_context.h" #include "lp_flush.h" -#include "lp_prim_vbuf.h" +#include "lp_perf.h" #include "lp_state.h" #include "lp_surface.h" -#include "lp_tile_cache.h" -#include "lp_tex_cache.h" #include "lp_texture.h" #include "lp_winsys.h" #include "lp_query.h" +#include "lp_setup.h" -/** - * Map any drawing surfaces which aren't already mapped - */ -void -llvmpipe_map_transfers(struct llvmpipe_context *lp) -{ - struct pipe_screen *screen = lp->pipe.screen; - struct pipe_surface *zsbuf = lp->framebuffer.zsbuf; - unsigned i; - - for (i = 0; i < lp->framebuffer.nr_cbufs; i++) { - lp_tile_cache_map_transfers(lp->cbuf_cache[i]); - } - - if(zsbuf) { - if(!lp->zsbuf_transfer) - lp->zsbuf_transfer = screen->get_tex_transfer(screen, zsbuf->texture, - zsbuf->face, zsbuf->level, zsbuf->zslice, - PIPE_TRANSFER_READ_WRITE, - 0, 0, zsbuf->width, zsbuf->height); - if(lp->zsbuf_transfer && !lp->zsbuf_map) - lp->zsbuf_map = screen->transfer_map(screen, lp->zsbuf_transfer); - - } -} - - -/** - * Unmap any mapped drawing surfaces - */ -void -llvmpipe_unmap_transfers(struct llvmpipe_context *lp) -{ - uint i; - - for (i = 0; i < lp->framebuffer.nr_cbufs; i++) { - lp_tile_cache_unmap_transfers(lp->cbuf_cache[i]); - } - - if(lp->zsbuf_transfer) { - struct pipe_screen *screen = lp->pipe.screen; - - if(lp->zsbuf_map) { - screen->transfer_unmap(screen, lp->zsbuf_transfer); - lp->zsbuf_map = NULL; - } - } -} static void llvmpipe_destroy( struct pipe_context *pipe ) @@ -104,28 +56,30 @@ static void llvmpipe_destroy( struct pipe_context *pipe ) struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); uint i; + lp_print_counters(); + + /* This will also destroy llvmpipe->setup: + */ if (llvmpipe->draw) draw_destroy( llvmpipe->draw ); for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { - lp_destroy_tile_cache(llvmpipe->cbuf_cache[i]); pipe_surface_reference(&llvmpipe->framebuffer.cbufs[i], NULL); } + pipe_surface_reference(&llvmpipe->framebuffer.zsbuf, NULL); for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { - lp_destroy_tex_tile_cache(llvmpipe->tex_cache[i]); pipe_texture_reference(&llvmpipe->texture[i], NULL); } for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { - lp_destroy_tex_tile_cache(llvmpipe->vertex_tex_cache[i]); pipe_texture_reference(&llvmpipe->vertex_textures[i], NULL); } for (i = 0; i < Elements(llvmpipe->constants); i++) { - if (llvmpipe->constants[i].buffer) { - pipe_buffer_reference(&llvmpipe->constants[i].buffer, NULL); + if (llvmpipe->constants[i]) { + pipe_buffer_reference(&llvmpipe->constants[i], NULL); } } @@ -138,33 +92,8 @@ llvmpipe_is_texture_referenced( struct pipe_context *pipe, unsigned face, unsigned level) { struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); - unsigned i; - - /* check if any of the bound drawing surfaces are this texture */ - if(llvmpipe->dirty_render_cache) { - for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++) { - if(llvmpipe->framebuffer.cbufs[i] && - llvmpipe->framebuffer.cbufs[i]->texture == texture) - return PIPE_REFERENCED_FOR_WRITE; - } - if(llvmpipe->framebuffer.zsbuf && - llvmpipe->framebuffer.zsbuf->texture == texture) - return PIPE_REFERENCED_FOR_WRITE; - } - /* check if any of the tex_cache textures are this texture */ - for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { - if (llvmpipe->tex_cache[i] && - llvmpipe->tex_cache[i]->texture == texture) - return PIPE_REFERENCED_FOR_READ; - } - for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) { - if (llvmpipe->vertex_tex_cache[i] && - llvmpipe->vertex_tex_cache[i]->texture == texture) - return PIPE_REFERENCED_FOR_READ; - } - - return PIPE_UNREFERENCED; + return lp_setup_is_texture_referenced(llvmpipe->setup, texture); } static unsigned int @@ -175,10 +104,9 @@ llvmpipe_is_buffer_referenced( struct pipe_context *pipe, } struct pipe_context * -llvmpipe_create( struct pipe_screen *screen ) +llvmpipe_create_context( struct pipe_screen *screen, void *priv ) { struct llvmpipe_context *llvmpipe; - uint i; llvmpipe = align_malloc(sizeof(struct llvmpipe_context), 16); if (!llvmpipe) @@ -190,6 +118,7 @@ llvmpipe_create( struct pipe_screen *screen ) llvmpipe->pipe.winsys = screen->winsys; llvmpipe->pipe.screen = screen; + llvmpipe->pipe.priv = priv; llvmpipe->pipe.destroy = llvmpipe_destroy; /* state setters */ @@ -242,19 +171,6 @@ llvmpipe_create( struct pipe_screen *screen ) llvmpipe->pipe.is_buffer_referenced = llvmpipe_is_buffer_referenced; llvmpipe_init_query_funcs( llvmpipe ); - llvmpipe_init_texture_funcs( llvmpipe ); - - /* - * Alloc caches for accessing drawing surfaces and textures. - */ - for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) - llvmpipe->cbuf_cache[i] = lp_create_tile_cache( screen ); - - for (i = 0; i < PIPE_MAX_SAMPLERS; i++) - llvmpipe->tex_cache[i] = lp_create_tex_tile_cache( screen ); - for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) - llvmpipe->vertex_tex_cache[i] = lp_create_tex_tile_cache(screen); - /* * Create drawing context and plug our rendering stage into it. @@ -268,19 +184,11 @@ llvmpipe_create( struct pipe_screen *screen ) if (debug_get_bool_option( "LP_NO_RAST", FALSE )) llvmpipe->no_rast = TRUE; - llvmpipe->vbuf_backend = lp_create_vbuf_backend(llvmpipe); - if (!llvmpipe->vbuf_backend) - goto fail; - - llvmpipe->vbuf = draw_vbuf_stage(llvmpipe->draw, llvmpipe->vbuf_backend); - if (!llvmpipe->vbuf) + llvmpipe->setup = lp_setup_create( screen, + llvmpipe->draw ); + if (!llvmpipe->setup) goto fail; - draw_set_rasterize_stage(llvmpipe->draw, llvmpipe->vbuf); - draw_set_render(llvmpipe->draw, llvmpipe->vbuf_backend); - - - /* plug in AA line/point stages */ draw_install_aaline_stage(llvmpipe->draw, &llvmpipe->pipe); draw_install_aapoint_stage(llvmpipe->draw, &llvmpipe->pipe); @@ -292,6 +200,8 @@ llvmpipe_create( struct pipe_screen *screen ) lp_init_surface_functions(llvmpipe); + lp_reset_counters(); + return &llvmpipe->pipe; fail: diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index 6411797cf5..3bde485ac0 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -42,12 +42,10 @@ struct llvmpipe_vbuf_render; struct draw_context; struct draw_stage; -struct llvmpipe_tile_cache; -struct llvmpipe_tex_tile_cache; struct lp_fragment_shader; struct lp_vertex_shader; struct lp_blend_state; - +struct setup_context; struct llvmpipe_context { struct pipe_context pipe; /**< base class */ @@ -62,9 +60,9 @@ struct llvmpipe_context { const struct lp_vertex_shader *vs; /** Other rendering state */ - struct pipe_blend_color blend_color[4][16]; + struct pipe_blend_color blend_color; struct pipe_clip_state clip; - struct pipe_constant_buffer constants[PIPE_SHADER_TYPES]; + struct pipe_buffer *constants[PIPE_SHADER_TYPES]; struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple poly_stipple; struct pipe_scissor_state scissor; @@ -94,52 +92,26 @@ struct llvmpipe_context { /** Vertex format */ struct vertex_info vertex_info; - struct vertex_info vertex_info_vbuf; /** Which vertex shader output slot contains point size */ int psize_slot; - /* The reduced version of the primitive supplied by the state - * tracker. - */ - unsigned reduced_api_prim; - - /* The reduced primitive after unfilled triangles, wide-line - * decomposition, etc, are taken into account. This is the - * primitive actually rasterized. - */ - unsigned reduced_prim; - - /** Derived from scissor and surface bounds: */ - struct pipe_scissor_state cliprect; - - unsigned line_stipple_counter; + /** The tiling engine */ + struct setup_context *setup; /** The primitive drawing context */ struct draw_context *draw; - /** Draw module backend */ - struct vbuf_render *vbuf_backend; - struct draw_stage *vbuf; - - boolean dirty_render_cache; - - struct llvmpipe_tile_cache *cbuf_cache[PIPE_MAX_COLOR_BUFS]; - - /* TODO: we shouldn't be using external interfaces internally like this */ - struct pipe_transfer *zsbuf_transfer; - uint8_t *zsbuf_map; - unsigned tex_timestamp; - struct llvmpipe_tex_tile_cache *tex_cache[PIPE_MAX_SAMPLERS]; - struct llvmpipe_tex_tile_cache *vertex_tex_cache[PIPE_MAX_VERTEX_SAMPLERS]; + boolean no_rast; - unsigned no_rast : 1; - - struct lp_jit_context jit_context; }; +struct pipe_context * +llvmpipe_create_context( struct pipe_screen *screen, void *priv ); + + static INLINE struct llvmpipe_context * llvmpipe_context( struct pipe_context *pipe ) { diff --git a/src/gallium/drivers/llvmpipe/lp_debug.h b/src/gallium/drivers/llvmpipe/lp_debug.h index 74b2757494..ee81814361 100644 --- a/src/gallium/drivers/llvmpipe/lp_debug.h +++ b/src/gallium/drivers/llvmpipe/lp_debug.h @@ -45,6 +45,11 @@ st_print_current(void); #define DEBUG_QUERY 0x40 #define DEBUG_SCREEN 0x80 #define DEBUG_JIT 0x100 +#define DEBUG_SHOW_TILES 0x200 +#define DEBUG_SHOW_SUBTILES 0x400 +#define DEBUG_COUNTERS 0x800 +#define DEBUG_NO_LLVM_OPT 0x1000 + #ifdef DEBUG extern int LP_DEBUG; diff --git a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c index c152b4413f..3dd68d5794 100644 --- a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c +++ b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c @@ -33,8 +33,6 @@ #include "pipe/p_defines.h" #include "pipe/p_context.h" -#include "pipe/internal/p_winsys_screen.h" -#include "pipe/p_inlines.h" #include "util/u_prim.h" #include "lp_buffer.h" @@ -70,13 +68,9 @@ llvmpipe_draw_range_elements(struct pipe_context *pipe, struct draw_context *draw = lp->draw; unsigned i; - lp->reduced_api_prim = u_reduced_prim(mode); - if (lp->dirty) llvmpipe_update_derived( lp ); - llvmpipe_map_transfers(lp); - /* * Map vertex buffers */ @@ -118,10 +112,6 @@ llvmpipe_draw_range_elements(struct pipe_context *pipe, * internally when this condition is seen?) */ draw_flush(draw); - - /* Note: leave drawing surfaces mapped */ - - lp->dirty_render_cache = TRUE; } diff --git a/src/gallium/drivers/llvmpipe/lp_fence.c b/src/gallium/drivers/llvmpipe/lp_fence.c new file mode 100644 index 0000000000..525c117f31 --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_fence.c @@ -0,0 +1,110 @@ +/************************************************************************** + * + * 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 "util/u_memory.h" +#include "util/u_inlines.h" +#include "lp_fence.h" + + +struct lp_fence * +lp_fence_create(unsigned rank) +{ + struct lp_fence *fence = CALLOC_STRUCT(lp_fence); + + pipe_reference_init(&fence->reference, 1); + + pipe_mutex_init(fence->mutex); + pipe_condvar_init(fence->signalled); + + fence->rank = rank; + + return fence; +} + + +static void +lp_fence_destroy(struct lp_fence *fence) +{ + pipe_mutex_destroy(fence->mutex); + pipe_condvar_destroy(fence->signalled); + FREE(fence); +} + + +static void +llvmpipe_fence_reference(struct pipe_screen *screen, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ + struct lp_fence *old = (struct lp_fence *) *ptr; + struct lp_fence *f = (struct lp_fence *) fence; + + if (pipe_reference(&old->reference, &f->reference)) { + lp_fence_destroy(old); + } +} + + +static int +llvmpipe_fence_signalled(struct pipe_screen *screen, + struct pipe_fence_handle *fence, + unsigned flag) +{ + struct lp_fence *f = (struct lp_fence *) fence; + + return f->count == f->rank; +} + + +static int +llvmpipe_fence_finish(struct pipe_screen *screen, + struct pipe_fence_handle *fence_handle, + unsigned flag) +{ + struct lp_fence *fence = (struct lp_fence *) fence_handle; + + pipe_mutex_lock(fence->mutex); + while (fence->count < fence->rank) { + pipe_condvar_wait(fence->signalled, fence->mutex); + } + pipe_mutex_unlock(fence->mutex); + + return 0; +} + + + + +void +llvmpipe_init_screen_fence_funcs(struct pipe_screen *screen) +{ + screen->fence_reference = llvmpipe_fence_reference; + screen->fence_signalled = llvmpipe_fence_signalled; + screen->fence_finish = llvmpipe_fence_finish; +} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_debug.h b/src/gallium/drivers/llvmpipe/lp_fence.h index 583e6132b4..c90e6de423 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_debug.h +++ b/src/gallium/drivers/llvmpipe/lp_fence.h @@ -26,39 +26,35 @@ **************************************************************************/ -#ifndef LP_BLD_DEBUG_H -#define LP_BLD_DEBUG_H +#ifndef LP_FENCE_H +#define LP_FENCE_H -#include <llvm-c/Core.h> +#include "os/os_thread.h" +#include "pipe/p_state.h" -#include "pipe/p_compiler.h" -#include "util/u_string.h" +struct pipe_screen; -static INLINE void -lp_build_name(LLVMValueRef val, const char *format, ...) + +struct lp_fence { -#ifdef DEBUG - char name[32]; - va_list ap; - va_start(ap, format); - util_vsnprintf(name, sizeof name, format, ap); - va_end(ap); - LLVMSetValueName(val, name); -#else - (void)val; - (void)format; -#endif -} + struct pipe_reference reference; + + pipe_mutex mutex; + pipe_condvar signalled; + + unsigned rank; + unsigned count; +}; -boolean -lp_check_alignment(const void *ptr, unsigned alignment); +struct lp_fence * +lp_fence_create(unsigned rank); void -lp_disassemble(const void* func); +llvmpipe_init_screen_fence_funcs(struct pipe_screen *screen); -#endif /* !LP_BLD_DEBUG_H */ +#endif /* LP_FENCE_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_flush.c b/src/gallium/drivers/llvmpipe/lp_flush.c index cd8381fe30..bf832433be 100644 --- a/src/gallium/drivers/llvmpipe/lp_flush.c +++ b/src/gallium/drivers/llvmpipe/lp_flush.c @@ -34,11 +34,7 @@ #include "draw/draw_context.h" #include "lp_flush.h" #include "lp_context.h" -#include "lp_surface.h" -#include "lp_state.h" -#include "lp_tile_cache.h" -#include "lp_tex_cache.h" -#include "lp_winsys.h" +#include "lp_setup.h" void @@ -47,56 +43,52 @@ llvmpipe_flush( struct pipe_context *pipe, struct pipe_fence_handle **fence ) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); - uint i; draw_flush(llvmpipe->draw); - if (flags & PIPE_FLUSH_SWAPBUFFERS) { - /* If this is a swapbuffers, just flush color buffers. - * - * The zbuffer changes are not discarded, but held in the cache - * in the hope that a later clear will wipe them out. - */ - for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++) - if (llvmpipe->cbuf_cache[i]) { - lp_tile_cache_map_transfers(llvmpipe->cbuf_cache[i]); - lp_flush_tile_cache(llvmpipe->cbuf_cache[i]); - } + if (fence) { + if ((flags & (PIPE_FLUSH_SWAPBUFFERS | + PIPE_FLUSH_RENDER_CACHE))) { + /* if we're going to flush the setup/rasterization modules, emit + * a fence. + * XXX this (and the code below) may need fine tuning... + */ + *fence = lp_setup_fence( llvmpipe->setup ); + } + else { + *fence = NULL; + } + } - /* Need this call for hardware buffers before swapbuffers. - * - * there should probably be another/different flush-type function - * that's called before swapbuffers because we don't always want - * to unmap surfaces when flushing. - */ - llvmpipe_unmap_transfers(llvmpipe); + /* XXX the lp_setup_flush(flags) param is not a bool, and it's ignored + * at this time! + */ + if (flags & PIPE_FLUSH_SWAPBUFFERS) { + lp_setup_flush( llvmpipe->setup, FALSE ); } else if (flags & PIPE_FLUSH_RENDER_CACHE) { - for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++) - if (llvmpipe->cbuf_cache[i]) { - lp_tile_cache_map_transfers(llvmpipe->cbuf_cache[i]); - lp_flush_tile_cache(llvmpipe->cbuf_cache[i]); - } - - /* FIXME: untile zsbuf! */ - - llvmpipe->dirty_render_cache = FALSE; + lp_setup_flush( llvmpipe->setup, TRUE ); } /* Enable to dump BMPs of the color/depth buffers each frame */ #if 0 - if(flags & PIPE_FLUSH_FRAME) { + if (flags & PIPE_FLUSH_FRAME) { static unsigned frame_no = 1; - static char filename[256]; - util_snprintf(filename, sizeof(filename), "cbuf_%u.bmp", frame_no); - debug_dump_surface_bmp(filename, llvmpipe->framebuffer.cbufs[0]); - util_snprintf(filename, sizeof(filename), "zsbuf_%u.bmp", frame_no); - debug_dump_surface_bmp(filename, llvmpipe->framebuffer.zsbuf); + char filename[256]; + unsigned i; + + for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++) { + util_snprintf(filename, sizeof(filename), "cbuf%u_%u", i, frame_no); + debug_dump_surface(filename, llvmpipe->framebuffer.cbufs[i]); + } + + if (0) { + util_snprintf(filename, sizeof(filename), "zsbuf_%u", frame_no); + debug_dump_surface(filename, llvmpipe->framebuffer.zsbuf); + } + ++frame_no; } #endif - - if (fence) - *fence = NULL; } diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c index 4ef0783f3e..27b54c5959 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.c +++ b/src/gallium/drivers/llvmpipe/lp_jit.c @@ -37,9 +37,10 @@ #include "util/u_memory.h" #include "util/u_cpu_detect.h" +#include "lp_debug.h" #include "lp_screen.h" -#include "lp_bld_intr.h" -#include "lp_bld_misc.h" +#include "gallivm/lp_bld_intr.h" +#include "gallivm/lp_bld_misc.h" #include "lp_jit.h" @@ -79,13 +80,16 @@ lp_jit_init_globals(struct llvmpipe_screen *screen) /* struct lp_jit_context */ { - LLVMTypeRef elem_types[4]; + LLVMTypeRef elem_types[8]; LLVMTypeRef context_type; elem_types[0] = LLVMPointerType(LLVMFloatType(), 0); /* constants */ - elem_types[1] = LLVMFloatType(); /* alpha_ref_value */ - elem_types[2] = LLVMPointerType(LLVMInt8Type(), 0); /* blend_color */ - elem_types[3] = LLVMArrayType(texture_type, PIPE_MAX_SAMPLERS); /* textures */ + elem_types[1] = LLVMFloatType(); /* alpha_ref_value */ elem_types[2] = LLVMFloatType(); /* scissor_xmin */ + elem_types[3] = LLVMFloatType(); /* scissor_ymin */ + elem_types[4] = LLVMFloatType(); /* scissor_xmax */ + elem_types[5] = LLVMFloatType(); /* scissor_ymax */ + elem_types[6] = LLVMPointerType(LLVMInt8Type(), 0); /* blend_color */ + elem_types[7] = LLVMArrayType(texture_type, PIPE_MAX_SAMPLERS); /* textures */ context_type = LLVMStructType(elem_types, Elements(elem_types), 0); @@ -93,8 +97,16 @@ lp_jit_init_globals(struct llvmpipe_screen *screen) screen->target, context_type, 0); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, alpha_ref_value, screen->target, context_type, 1); - LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, blend_color, + LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_xmin, screen->target, context_type, 2); + LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_ymin, + screen->target, context_type, 3); + LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_xmax, + screen->target, context_type, 4); + LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_ymax, + screen->target, context_type, 5); + LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, blend_color, + screen->target, context_type, 6); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, textures, screen->target, context_type, LP_JIT_CONTEXT_TEXTURES_INDEX); @@ -154,20 +166,23 @@ lp_jit_screen_init(struct llvmpipe_screen *screen) screen->pass = LLVMCreateFunctionPassManager(screen->provider); LLVMAddTargetData(screen->target, screen->pass); - /* These are the passes currently listed in llvm-c/Transforms/Scalar.h, - * but there are more on SVN. */ - /* TODO: Add more passes */ - LLVMAddConstantPropagationPass(screen->pass); - if(util_cpu_caps.has_sse4_1) { - /* FIXME: There is a bug in this pass, whereby the combination of fptosi - * and sitofp (necessary for trunc/floor/ceil/round implementation) - * somehow becomes invalid code. - */ - LLVMAddInstructionCombiningPass(screen->pass); + + if ((LP_DEBUG & DEBUG_NO_LLVM_OPT) == 0) { + /* These are the passes currently listed in llvm-c/Transforms/Scalar.h, + * but there are more on SVN. */ + /* TODO: Add more passes */ + LLVMAddConstantPropagationPass(screen->pass); + if(util_cpu_caps.has_sse4_1) { + /* FIXME: There is a bug in this pass, whereby the combination of fptosi + * and sitofp (necessary for trunc/floor/ceil/round implementation) + * somehow becomes invalid code. + */ + LLVMAddInstructionCombiningPass(screen->pass); + } + LLVMAddPromoteMemoryToRegisterPass(screen->pass); + LLVMAddGVNPass(screen->pass); + LLVMAddCFGSimplificationPass(screen->pass); } - LLVMAddPromoteMemoryToRegisterPass(screen->pass); - LLVMAddGVNPass(screen->pass); - LLVMAddCFGSimplificationPass(screen->pass); lp_jit_init_globals(screen); } diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h index 277b690c02..8df3015d4b 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.h +++ b/src/gallium/drivers/llvmpipe/lp_jit.h @@ -36,7 +36,7 @@ #define LP_JIT_H -#include "lp_bld_struct.h" +#include "gallivm/lp_bld_struct.h" #include "pipe/p_state.h" @@ -79,6 +79,9 @@ struct lp_jit_context float alpha_ref_value; + /** floats, not ints */ + float scissor_xmin, scissor_ymin, scissor_xmax, scissor_ymax; + /* FIXME: store (also?) in floats */ uint8_t *blend_color; @@ -92,25 +95,43 @@ struct lp_jit_context #define lp_jit_context_alpha_ref_value(_builder, _ptr) \ lp_build_struct_get(_builder, _ptr, 1, "alpha_ref_value") +#define lp_jit_context_scissor_xmin_value(_builder, _ptr) \ + lp_build_struct_get(_builder, _ptr, 2, "scissor_xmin") + +#define lp_jit_context_scissor_ymin_value(_builder, _ptr) \ + lp_build_struct_get(_builder, _ptr, 3, "scissor_ymin") + +#define lp_jit_context_scissor_xmax_value(_builder, _ptr) \ + lp_build_struct_get(_builder, _ptr, 4, "scissor_xmax") + +#define lp_jit_context_scissor_ymax_value(_builder, _ptr) \ + lp_build_struct_get(_builder, _ptr, 5, "scissor_ymax") + #define lp_jit_context_blend_color(_builder, _ptr) \ - lp_build_struct_get(_builder, _ptr, 2, "blend_color") + lp_build_struct_get(_builder, _ptr, 6, "blend_color") -#define LP_JIT_CONTEXT_TEXTURES_INDEX 3 +#define LP_JIT_CONTEXT_TEXTURES_INDEX 7 #define lp_jit_context_textures(_builder, _ptr) \ lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CONTEXT_TEXTURES_INDEX, "textures") typedef void -(*lp_jit_frag_func)(struct lp_jit_context *context, +(*lp_jit_frag_func)(const struct lp_jit_context *context, uint32_t x, uint32_t y, const void *a0, const void *dadx, const void *dady, - uint32_t *mask, - void *color, - void *depth); + uint8_t **color, + void *depth, + const int32_t c1, + const int32_t c2, + const int32_t c3, + const int32_t *step1, + const int32_t *step2, + const int32_t *step3); + void lp_jit_screen_cleanup(struct llvmpipe_screen *screen); diff --git a/src/gallium/drivers/llvmpipe/lp_perf.c b/src/gallium/drivers/llvmpipe/lp_perf.c new file mode 100644 index 0000000000..a316597675 --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_perf.c @@ -0,0 +1,95 @@ +/************************************************************************** + * + * 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_debug.h" +#include "lp_debug.h" +#include "lp_perf.h" + + + +struct lp_counters lp_count; + + +void +lp_reset_counters(void) +{ + memset(&lp_count, 0, sizeof(lp_count)); +} + + +void +lp_print_counters(void) +{ + if (LP_DEBUG & DEBUG_COUNTERS) { + unsigned total_64, total_16, total_4; + float p1, p2, p3; + + debug_printf("llvmpipe: nr_triangles: %9u\n", lp_count.nr_tris); + debug_printf("llvmpipe: nr_culled_triangles: %9u\n", lp_count.nr_culled_tris); + + total_64 = (lp_count.nr_empty_64 + + lp_count.nr_fully_covered_64 + + lp_count.nr_partially_covered_64); + + p1 = 100.0 * (float) lp_count.nr_empty_64 / (float) total_64; + p2 = 100.0 * (float) lp_count.nr_fully_covered_64 / (float) total_64; + p3 = 100.0 * (float) lp_count.nr_partially_covered_64 / (float) total_64; + + debug_printf("llvmpipe: nr_empty_64x64: %9u (%2.0f%% of %u)\n", lp_count.nr_empty_64, p1, total_64); + debug_printf("llvmpipe: nr_fully_covered_64x64: %9u (%2.0f%% of %u)\n", lp_count.nr_fully_covered_64, p2, total_64); + debug_printf("llvmpipe: nr_partially_covered_64x64: %9u (%2.0f%% of %u)\n", lp_count.nr_partially_covered_64, p3, total_64); + + total_16 = (lp_count.nr_empty_16 + + lp_count.nr_fully_covered_16 + + lp_count.nr_partially_covered_16); + + p1 = 100.0 * (float) lp_count.nr_empty_16 / (float) total_16; + p2 = 100.0 * (float) lp_count.nr_fully_covered_16 / (float) total_16; + p3 = 100.0 * (float) lp_count.nr_partially_covered_16 / (float) total_16; + + debug_printf("llvmpipe: nr_empty_16x16: %9u (%2.0f%% of %u)\n", lp_count.nr_empty_16, p1, total_16); + debug_printf("llvmpipe: nr_fully_covered_16x16: %9u (%2.0f%% of %u)\n", lp_count.nr_fully_covered_16, p2, total_16); + debug_printf("llvmpipe: nr_partially_covered_16x16: %9u (%2.0f%% of %u)\n", lp_count.nr_partially_covered_16, p3, total_16); + + total_4 = (lp_count.nr_empty_4 + lp_count.nr_non_empty_4); + + p1 = 100.0 * (float) lp_count.nr_empty_4 / (float) total_4; + p2 = 100.0 * (float) lp_count.nr_non_empty_4 / (float) total_4; + + debug_printf("llvmpipe: nr_empty_4x4: %9u (%2.0f%% of %u)\n", lp_count.nr_empty_4, p1, total_4); + debug_printf("llvmpipe: nr_non_empty_4x4: %9u (%2.0f%% of %u)\n", lp_count.nr_non_empty_4, p2, total_4); + + debug_printf("llvmpipe: nr_color_tile_clear: %9u\n", lp_count.nr_color_tile_clear); + debug_printf("llvmpipe: nr_color_tile_load: %9u\n", lp_count.nr_color_tile_load); + debug_printf("llvmpipe: nr_color_tile_store: %9u\n", lp_count.nr_color_tile_store); + + debug_printf("llvmpipe: nr_llvm_compiles: %u\n", lp_count.nr_llvm_compiles); + debug_printf("llvmpipe: total LLVM compile time: %.2f sec\n", lp_count.llvm_compile_time / 1000000.0); + debug_printf("llvmpipe: average LLVM compile time: %.2f sec\n", lp_count.llvm_compile_time / 1000000.0 / lp_count.nr_llvm_compiles); + + } +} diff --git a/src/gallium/drivers/llvmpipe/lp_bld_logic.h b/src/gallium/drivers/llvmpipe/lp_perf.h index d67500ef70..a9629dae3c 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_logic.h +++ b/src/gallium/drivers/llvmpipe/lp_perf.h @@ -26,47 +26,57 @@ **************************************************************************/ /** - * @file - * Helper functions for logical operations. - * - * @author Jose Fonseca <jfonseca@vmware.com> + * Performance / statistic counters, etc. */ -#ifndef LP_BLD_LOGIC_H -#define LP_BLD_LOGIC_H +#ifndef LP_PERF_H +#define LP_PERF_H + +/** + * Various counters + */ +struct lp_counters +{ + unsigned nr_tris; + unsigned nr_culled_tris; + unsigned nr_empty_64; + unsigned nr_fully_covered_64; + unsigned nr_partially_covered_64; + unsigned nr_empty_16; + unsigned nr_fully_covered_16; + unsigned nr_partially_covered_16; + unsigned nr_empty_4; + unsigned nr_non_empty_4; + unsigned nr_llvm_compiles; + int64_t llvm_compile_time; /**< total, in microseconds */ -#include <llvm-c/Core.h> + unsigned nr_color_tile_clear; + unsigned nr_color_tile_load; + unsigned nr_color_tile_store; +}; -#include "pipe/p_defines.h" /* For PIPE_FUNC_xxx */ +extern struct lp_counters lp_count; -struct lp_type; -struct lp_build_context; +/** Increment the named counter (only for debug builds) */ +#ifdef DEBUG +#define LP_COUNT(counter) lp_count.counter++ +#define LP_COUNT_ADD(counter, incr) lp_count.counter += (incr) +#else +#define LP_COUNT(counter) +#define LP_COUNT_ADD(counter, incr) (void) incr +#endif -/** - * @param func is one of PIPE_FUNC_xxx - */ -LLVMValueRef -lp_build_cmp(struct lp_build_context *bld, - unsigned func, - LLVMValueRef a, - LLVMValueRef b); +extern void +lp_reset_counters(void); -LLVMValueRef -lp_build_select(struct lp_build_context *bld, - LLVMValueRef mask, - LLVMValueRef a, - LLVMValueRef b); -LLVMValueRef -lp_build_select_aos(struct lp_build_context *bld, - LLVMValueRef a, - LLVMValueRef b, - const boolean cond[4]); +extern void +lp_print_counters(void); -#endif /* !LP_BLD_LOGIC_H */ +#endif /* LP_PERF_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_prim_vbuf.c b/src/gallium/drivers/llvmpipe/lp_prim_vbuf.c deleted file mode 100644 index e8e2e2524a..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_prim_vbuf.c +++ /dev/null @@ -1,563 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 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. - * - **************************************************************************/ - -/** - * Interface between 'draw' module's output and the llvmpipe rasterizer/setup - * code. When the 'draw' module has finished filling a vertex buffer, the - * draw_arrays() functions below will be called. Loop over the vertices and - * call the point/line/tri setup functions. - * - * Authors - * Brian Paul - */ - - -#include "lp_context.h" -#include "lp_setup.h" -#include "lp_state.h" -#include "lp_prim_vbuf.h" -#include "draw/draw_context.h" -#include "draw/draw_vbuf.h" -#include "util/u_memory.h" -#include "util/u_prim.h" - - -#define LP_MAX_VBUF_INDEXES 1024 -#define LP_MAX_VBUF_SIZE 4096 - -typedef const float (*cptrf4)[4]; - -/** - * Subclass of vbuf_render. - */ -struct llvmpipe_vbuf_render -{ - struct vbuf_render base; - struct llvmpipe_context *llvmpipe; - struct setup_context *setup; - - uint prim; - uint vertex_size; - uint nr_vertices; - uint vertex_buffer_size; - void *vertex_buffer; -}; - - -/** cast wrapper */ -static struct llvmpipe_vbuf_render * -llvmpipe_vbuf_render(struct vbuf_render *vbr) -{ - return (struct llvmpipe_vbuf_render *) vbr; -} - - - - - - - -static const struct vertex_info * -lp_vbuf_get_vertex_info(struct vbuf_render *vbr) -{ - struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr); - return llvmpipe_get_vbuf_vertex_info(cvbr->llvmpipe); -} - - -static boolean -lp_vbuf_allocate_vertices(struct vbuf_render *vbr, - ushort vertex_size, ushort nr_vertices) -{ - struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr); - unsigned size = vertex_size * nr_vertices; - - if (cvbr->vertex_buffer_size < size) { - align_free(cvbr->vertex_buffer); - cvbr->vertex_buffer = align_malloc(size, 16); - cvbr->vertex_buffer_size = size; - } - - cvbr->vertex_size = vertex_size; - cvbr->nr_vertices = nr_vertices; - - return cvbr->vertex_buffer != NULL; -} - -static void -lp_vbuf_release_vertices(struct vbuf_render *vbr) -{ - /* keep the old allocation for next time */ -} - -static void * -lp_vbuf_map_vertices(struct vbuf_render *vbr) -{ - struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr); - return cvbr->vertex_buffer; -} - -static void -lp_vbuf_unmap_vertices(struct vbuf_render *vbr, - ushort min_index, - ushort max_index ) -{ - struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr); - assert( cvbr->vertex_buffer_size >= (max_index+1) * cvbr->vertex_size ); - (void) cvbr; - /* do nothing */ -} - - -static boolean -lp_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim) -{ - struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr); - struct setup_context *setup_ctx = cvbr->setup; - - llvmpipe_setup_prepare( setup_ctx ); - - cvbr->llvmpipe->reduced_prim = u_reduced_prim(prim); - cvbr->prim = prim; - return TRUE; - -} - - -static INLINE cptrf4 get_vert( const void *vertex_buffer, - int index, - int stride ) -{ - return (cptrf4)((char *)vertex_buffer + index * stride); -} - - -/** - * draw elements / indexed primitives - */ -static void -lp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) -{ - struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr); - struct llvmpipe_context *llvmpipe = cvbr->llvmpipe; - const unsigned stride = llvmpipe->vertex_info_vbuf.size * sizeof(float); - const void *vertex_buffer = cvbr->vertex_buffer; - struct setup_context *setup_ctx = cvbr->setup; - unsigned i; - - switch (cvbr->prim) { - case PIPE_PRIM_POINTS: - for (i = 0; i < nr; i++) { - llvmpipe_setup_point( setup_ctx, - get_vert(vertex_buffer, indices[i-0], stride) ); - } - break; - - case PIPE_PRIM_LINES: - for (i = 1; i < nr; i += 2) { - llvmpipe_setup_line( setup_ctx, - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); - } - break; - - case PIPE_PRIM_LINE_STRIP: - for (i = 1; i < nr; i ++) { - llvmpipe_setup_line( setup_ctx, - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); - } - break; - - case PIPE_PRIM_LINE_LOOP: - for (i = 1; i < nr; i ++) { - llvmpipe_setup_line( setup_ctx, - get_vert(vertex_buffer, indices[i-1], stride), - get_vert(vertex_buffer, indices[i-0], stride) ); - } - if (nr) { - llvmpipe_setup_line( setup_ctx, - get_vert(vertex_buffer, indices[nr-1], stride), - get_vert(vertex_buffer, indices[0], stride) ); - } - break; - - case PIPE_PRIM_TRIANGLES: - if (llvmpipe->rasterizer->flatshade_first) { - for (i = 2; i < nr; i += 3) { - llvmpipe_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 { - for (i = 2; i < nr; i += 3) { - llvmpipe_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: - if (llvmpipe->rasterizer->flatshade_first) { - for (i = 2; i < nr; i += 1) { - llvmpipe_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 { - for (i = 2; i < nr; i += 1) { - llvmpipe_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: - if (llvmpipe->rasterizer->flatshade_first) { - for (i = 2; i < nr; i += 1) { - llvmpipe_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 { - for (i = 2; i < nr; i += 1) { - llvmpipe_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: - if (llvmpipe->rasterizer->flatshade_first) { - for (i = 3; i < nr; i += 4) { - llvmpipe_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) ); - llvmpipe_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 { - for (i = 3; i < nr; i += 4) { - llvmpipe_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) ); - - llvmpipe_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: - if (llvmpipe->rasterizer->flatshade_first) { - for (i = 3; i < nr; i += 2) { - llvmpipe_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)); - llvmpipe_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 { - for (i = 3; i < nr; i += 2) { - llvmpipe_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) ); - llvmpipe_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) { - llvmpipe_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[0], stride) ); - } - break; - - default: - assert(0); - } -} - - -/** - * This function is hit when the draw module is working in pass-through mode. - * It's up to us to convert the vertex array into point/line/tri prims. - */ -static void -lp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) -{ - struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr); - struct llvmpipe_context *llvmpipe = cvbr->llvmpipe; - struct setup_context *setup_ctx = cvbr->setup; - const unsigned stride = llvmpipe->vertex_info_vbuf.size * sizeof(float); - const void *vertex_buffer = - (void *) get_vert(cvbr->vertex_buffer, start, stride); - unsigned i; - - switch (cvbr->prim) { - case PIPE_PRIM_POINTS: - for (i = 0; i < nr; i++) { - llvmpipe_setup_point( setup_ctx, - get_vert(vertex_buffer, i-0, stride) ); - } - break; - - case PIPE_PRIM_LINES: - for (i = 1; i < nr; i += 2) { - llvmpipe_setup_line( setup_ctx, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride) ); - } - break; - - case PIPE_PRIM_LINE_STRIP: - for (i = 1; i < nr; i ++) { - llvmpipe_setup_line( setup_ctx, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride) ); - } - break; - - case PIPE_PRIM_LINE_LOOP: - for (i = 1; i < nr; i ++) { - llvmpipe_setup_line( setup_ctx, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride) ); - } - if (nr) { - llvmpipe_setup_line( setup_ctx, - get_vert(vertex_buffer, nr-1, stride), - get_vert(vertex_buffer, 0, stride) ); - } - break; - - case PIPE_PRIM_TRIANGLES: - if (llvmpipe->rasterizer->flatshade_first) { - for (i = 2; i < nr; i += 3) { - llvmpipe_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 { - for (i = 2; i < nr; i += 3) { - llvmpipe_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: - if (llvmpipe->rasterizer->flatshade_first) { - for (i = 2; i < nr; i++) { - llvmpipe_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 { - for (i = 2; i < nr; i++) { - llvmpipe_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: - if (llvmpipe->rasterizer->flatshade_first) { - for (i = 2; i < nr; i += 1) { - llvmpipe_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 { - for (i = 2; i < nr; i += 1) { - llvmpipe_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: - if (llvmpipe->rasterizer->flatshade_first) { - for (i = 3; i < nr; i += 4) { - llvmpipe_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) ); - llvmpipe_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 { - for (i = 3; i < nr; i += 4) { - llvmpipe_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) ); - llvmpipe_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: - if (llvmpipe->rasterizer->flatshade_first) { - for (i = 3; i < nr; i += 2) { - llvmpipe_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) ); - llvmpipe_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 { - for (i = 3; i < nr; i += 2) { - llvmpipe_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) ); - llvmpipe_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; - - 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) { - llvmpipe_setup_tri( setup_ctx, - get_vert(vertex_buffer, i-1, stride), - get_vert(vertex_buffer, i-0, stride), - get_vert(vertex_buffer, 0, stride) ); - } - break; - - default: - assert(0); - } -} - - - -static void -lp_vbuf_destroy(struct vbuf_render *vbr) -{ - struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr); - llvmpipe_setup_destroy_context(cvbr->setup); - FREE(cvbr); -} - - -/** - * Create the post-transform vertex handler for the given context. - */ -struct vbuf_render * -lp_create_vbuf_backend(struct llvmpipe_context *lp) -{ - struct llvmpipe_vbuf_render *cvbr = CALLOC_STRUCT(llvmpipe_vbuf_render); - - assert(lp->draw); - - - cvbr->base.max_indices = LP_MAX_VBUF_INDEXES; - cvbr->base.max_vertex_buffer_bytes = LP_MAX_VBUF_SIZE; - - cvbr->base.get_vertex_info = lp_vbuf_get_vertex_info; - cvbr->base.allocate_vertices = lp_vbuf_allocate_vertices; - cvbr->base.map_vertices = lp_vbuf_map_vertices; - cvbr->base.unmap_vertices = lp_vbuf_unmap_vertices; - cvbr->base.set_primitive = lp_vbuf_set_primitive; - cvbr->base.draw = lp_vbuf_draw; - cvbr->base.draw_arrays = lp_vbuf_draw_arrays; - cvbr->base.release_vertices = lp_vbuf_release_vertices; - cvbr->base.destroy = lp_vbuf_destroy; - - cvbr->llvmpipe = lp; - - cvbr->setup = llvmpipe_setup_create_context(cvbr->llvmpipe); - - return &cvbr->base; -} diff --git a/src/gallium/drivers/llvmpipe/lp_quad.h b/src/gallium/drivers/llvmpipe/lp_quad.h deleted file mode 100644 index 7eb05de77a..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_quad.h +++ /dev/null @@ -1,114 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 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. - * - **************************************************************************/ - -/* Authors: Keith Whitwell <keith@tungstengraphics.com> - */ - -#ifndef LP_QUAD_H -#define LP_QUAD_H - -#include "pipe/p_state.h" -#include "tgsi/tgsi_exec.h" - - -#define QUAD_PRIM_POINT 1 -#define QUAD_PRIM_LINE 2 -#define QUAD_PRIM_TRI 3 - - -/* The rasterizer generates 2x2 quads of fragment and feeds them to - * the current fp_machine (see below). - * Remember that Y=0=top with Y increasing down the window. - */ -#define QUAD_TOP_LEFT 0 -#define QUAD_TOP_RIGHT 1 -#define QUAD_BOTTOM_LEFT 2 -#define QUAD_BOTTOM_RIGHT 3 - -#define MASK_TOP_LEFT (1 << QUAD_TOP_LEFT) -#define MASK_TOP_RIGHT (1 << QUAD_TOP_RIGHT) -#define MASK_BOTTOM_LEFT (1 << QUAD_BOTTOM_LEFT) -#define MASK_BOTTOM_RIGHT (1 << QUAD_BOTTOM_RIGHT) -#define MASK_ALL 0xf - - -/** - * Quad stage inputs (pos, coverage, front/back face, etc) - */ -struct quad_header_input -{ - int x0, y0; /**< quad window pos, always even */ - float coverage[QUAD_SIZE]; /**< fragment coverage for antialiasing */ - unsigned facing:1; /**< Front (0) or back (1) facing? */ - unsigned prim:2; /**< QUAD_PRIM_POINT, LINE, TRI */ -}; - - -/** - * Quad stage inputs/outputs. - */ -struct quad_header_inout -{ - unsigned mask:4; -}; - - -/** - * Quad stage outputs (color & depth). - */ -struct quad_header_output -{ - /** colors in SOA format (rrrr, gggg, bbbb, aaaa) */ - float ALIGN16_ATTRIB color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS][QUAD_SIZE]; -}; - - -/** - * Input interpolation coefficients - */ -struct quad_interp_coef -{ - float ALIGN16_ATTRIB a0[1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; - float ALIGN16_ATTRIB dadx[1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; - float ALIGN16_ATTRIB dady[1 + PIPE_MAX_SHADER_INPUTS][NUM_CHANNELS]; -}; - - -/** - * Encodes everything we need to know about a 2x2 pixel block. Uses - * "Channel-Serial" or "SoA" layout. - */ -struct quad_header { - struct quad_header_input input; - struct quad_header_inout inout; - - /* Redundant/duplicated: - */ - const struct quad_interp_coef *coef; -}; - -#endif /* LP_QUAD_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c new file mode 100644 index 0000000000..5ae323fd96 --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -0,0 +1,1036 @@ +/************************************************************************** + * + * 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 <limits.h> +#include "util/u_memory.h" +#include "util/u_math.h" +#include "util/u_cpu_detect.h" +#include "util/u_surface.h" + +#include "lp_scene_queue.h" +#include "lp_debug.h" +#include "lp_fence.h" +#include "lp_perf.h" +#include "lp_rast.h" +#include "lp_rast_priv.h" +#include "lp_tile_soa.h" +#include "gallivm/lp_bld_debug.h" +#include "lp_scene.h" + + +/** + * Begin the rasterization phase. + * Map the framebuffer surfaces. Initialize the 'rast' state. + */ +static boolean +lp_rast_begin( struct lp_rasterizer *rast, + const struct pipe_framebuffer_state *fb, + boolean write_color, + boolean write_zstencil ) +{ + struct pipe_screen *screen = rast->screen; + struct pipe_surface *cbuf, *zsbuf; + int i; + + LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__); + + util_copy_framebuffer_state(&rast->state.fb, fb); + + rast->state.write_zstencil = write_zstencil; + rast->state.write_color = write_color; + + rast->check_for_clipped_tiles = (fb->width % TILE_SIZE != 0 || + fb->height % TILE_SIZE != 0); + + + for (i = 0; i < rast->state.fb.nr_cbufs; i++) { + cbuf = rast->state.fb.cbufs[i]; + if (cbuf) { + rast->cbuf_transfer[i] = screen->get_tex_transfer(rast->screen, + cbuf->texture, + cbuf->face, + cbuf->level, + cbuf->zslice, + PIPE_TRANSFER_READ_WRITE, + 0, 0, + cbuf->width, + cbuf->height); + if (!rast->cbuf_transfer[i]) + goto fail; + + rast->cbuf_map[i] = screen->transfer_map(rast->screen, + rast->cbuf_transfer[i]); + if (!rast->cbuf_map[i]) + goto fail; + } + } + + zsbuf = rast->state.fb.zsbuf; + if (zsbuf) { + rast->zsbuf_transfer = screen->get_tex_transfer(rast->screen, + zsbuf->texture, + zsbuf->face, + zsbuf->level, + zsbuf->zslice, + PIPE_TRANSFER_READ_WRITE, + 0, 0, + zsbuf->width, + zsbuf->height); + if (!rast->zsbuf_transfer) + goto fail; + + rast->zsbuf_map = screen->transfer_map(rast->screen, + rast->zsbuf_transfer); + if (!rast->zsbuf_map) + goto fail; + } + + return TRUE; + +fail: + /* Unmap and release transfers? + */ + return FALSE; +} + + +/** + * Finish the rasterization phase. + * Unmap framebuffer surfaces. + */ +static void +lp_rast_end( struct lp_rasterizer *rast ) +{ + struct pipe_screen *screen = rast->screen; + unsigned i; + + for (i = 0; i < rast->state.fb.nr_cbufs; i++) { + if (rast->cbuf_map[i]) + screen->transfer_unmap(screen, rast->cbuf_transfer[i]); + + if (rast->cbuf_transfer[i]) + screen->tex_transfer_destroy(rast->cbuf_transfer[i]); + + rast->cbuf_transfer[i] = NULL; + rast->cbuf_map[i] = NULL; + } + + if (rast->zsbuf_map) + screen->transfer_unmap(screen, rast->zsbuf_transfer); + + if (rast->zsbuf_transfer) + screen->tex_transfer_destroy(rast->zsbuf_transfer); + + rast->zsbuf_transfer = NULL; + rast->zsbuf_map = NULL; +} + + +/** + * Begining rasterization of a tile. + * \param x window X position of the tile, in pixels + * \param y window Y position of the tile, in pixels + */ +static void +lp_rast_start_tile( struct lp_rasterizer *rast, + unsigned thread_index, + unsigned x, unsigned y ) +{ + LP_DBG(DEBUG_RAST, "%s %d,%d\n", __FUNCTION__, x, y); + + rast->tasks[thread_index].x = x; + rast->tasks[thread_index].y = y; +} + + +/** + * Clear the rasterizer's current color tile. + * This is a bin command called during bin processing. + */ +void lp_rast_clear_color( struct lp_rasterizer *rast, + unsigned thread_index, + const union lp_rast_cmd_arg arg ) +{ + const uint8_t *clear_color = arg.clear_color; + uint8_t **color_tile = rast->tasks[thread_index].tile.color; + unsigned i; + + LP_DBG(DEBUG_RAST, "%s 0x%x,0x%x,0x%x,0x%x\n", __FUNCTION__, + clear_color[0], + clear_color[1], + clear_color[2], + clear_color[3]); + + if (clear_color[0] == clear_color[1] && + clear_color[1] == clear_color[2] && + clear_color[2] == clear_color[3]) { + /* clear to grayscale value {x, x, x, x} */ + for (i = 0; i < rast->state.fb.nr_cbufs; i++) { + memset(color_tile[i], clear_color[0], TILE_SIZE * TILE_SIZE * 4); + } + } + else { + /* Non-gray color. + * Note: if the swizzled tile layout changes (see TILE_PIXEL) this code + * will need to change. It'll be pretty obvious when clearing no longer + * works. + */ + const unsigned chunk = TILE_SIZE / 4; + for (i = 0; i < rast->state.fb.nr_cbufs; i++) { + uint8_t *c = color_tile[i]; + unsigned j; + for (j = 0; j < 4 * TILE_SIZE; j++) { + memset(c, clear_color[0], chunk); + c += chunk; + memset(c, clear_color[1], chunk); + c += chunk; + memset(c, clear_color[2], chunk); + c += chunk; + memset(c, clear_color[3], chunk); + c += chunk; + } + assert(c - color_tile[i] == TILE_SIZE * TILE_SIZE * 4); + } + } + + LP_COUNT(nr_color_tile_clear); +} + + +/** + * Clear the rasterizer's current z/stencil tile. + * This is a bin command called during bin processing. + */ +void lp_rast_clear_zstencil( struct lp_rasterizer *rast, + unsigned thread_index, + const union lp_rast_cmd_arg arg) +{ + unsigned i; + uint32_t *depth_tile = rast->tasks[thread_index].tile.depth; + + LP_DBG(DEBUG_RAST, "%s 0x%x\n", __FUNCTION__, arg.clear_zstencil); + + for (i = 0; i < TILE_SIZE * TILE_SIZE; i++) + depth_tile[i] = arg.clear_zstencil; +} + + +/** + * Load tile color from the framebuffer surface. + * This is a bin command called during bin processing. + */ +void lp_rast_load_color( struct lp_rasterizer *rast, + unsigned thread_index, + const union lp_rast_cmd_arg arg) +{ + struct lp_rasterizer_task *task = &rast->tasks[thread_index]; + const unsigned x = task->x; + const unsigned y = task->y; + unsigned i; + + LP_DBG(DEBUG_RAST, "%s at %u, %u\n", __FUNCTION__, x, y); + + for (i = 0; i < rast->state.fb.nr_cbufs; i++) { + struct pipe_transfer *transfer = rast->cbuf_transfer[i]; + int w = TILE_SIZE; + int h = TILE_SIZE; + + if (x >= transfer->width) + continue; + + if (y >= transfer->height) + continue; + + assert(w >= 0); + assert(h >= 0); + assert(w <= TILE_SIZE); + assert(h <= TILE_SIZE); + + lp_tile_read_4ub(transfer->texture->format, + task->tile.color[i], + rast->cbuf_map[i], + transfer->stride, + x, y, + w, h); + + LP_COUNT(nr_color_tile_load); + } +} + + +static void +lp_tile_read_z32(uint32_t *tile, + const uint8_t *map, + unsigned map_stride, + unsigned x0, unsigned y0, unsigned w, unsigned h) +{ + unsigned x, y; + const uint8_t *map_row = map + y0*map_stride; + for (y = 0; y < h; ++y) { + const uint32_t *map_pixel = (uint32_t *)(map_row + x0*4); + for (x = 0; x < w; ++x) { + *tile++ = *map_pixel++; + } + map_row += map_stride; + } +} + +/** + * Load tile z/stencil from the framebuffer surface. + * This is a bin command called during bin processing. + */ +void lp_rast_load_zstencil( struct lp_rasterizer *rast, + unsigned thread_index, + const union lp_rast_cmd_arg arg ) +{ + struct lp_rasterizer_task *task = &rast->tasks[thread_index]; + const unsigned x = task->x; + const unsigned y = task->y; + unsigned w = TILE_SIZE; + unsigned h = TILE_SIZE; + + if (x + w > rast->state.fb.width) + w -= x + w - rast->state.fb.width; + + if (y + h > rast->state.fb.height) + h -= y + h - rast->state.fb.height; + + LP_DBG(DEBUG_RAST, "%s %d,%d %dx%d\n", __FUNCTION__, x, y, w, h); + + assert(rast->zsbuf_transfer->texture->format == PIPE_FORMAT_Z32_UNORM); + lp_tile_read_z32(task->tile.depth, + rast->zsbuf_map, + rast->zsbuf_transfer->stride, + x, y, w, h); +} + + +void lp_rast_set_state( struct lp_rasterizer *rast, + unsigned thread_index, + const union lp_rast_cmd_arg arg ) +{ + const struct lp_rast_state *state = arg.set_state; + + LP_DBG(DEBUG_RAST, "%s %p\n", __FUNCTION__, (void *) state); + + /* just set the current state pointer for this rasterizer */ + rast->tasks[thread_index].current_state = state; +} + + + +/** + * Run the shader on all blocks in a tile. This is used when a tile is + * completely contained inside a triangle. + * This is a bin command called during bin processing. + */ +void lp_rast_shade_tile( struct lp_rasterizer *rast, + unsigned thread_index, + const union lp_rast_cmd_arg arg ) +{ + struct lp_rasterizer_task *task = &rast->tasks[thread_index]; + const struct lp_rast_state *state = task->current_state; + struct lp_rast_tile *tile = &task->tile; + const struct lp_rast_shader_inputs *inputs = arg.shade_tile; + const unsigned tile_x = task->x; + const unsigned tile_y = task->y; + unsigned x, y; + + LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__); + + /* render the whole 64x64 tile in 4x4 chunks */ + for (y = 0; y < TILE_SIZE; y += 4){ + for (x = 0; x < TILE_SIZE; x += 4) { + uint8_t *color[PIPE_MAX_COLOR_BUFS]; + uint32_t *depth; + unsigned block_offset, i; + + /* offset of the 16x16 pixel block within the tile */ + block_offset = ((y / 4) * (16 * 16) + (x / 4) * 16); + + /* color buffer */ + for (i = 0; i < rast->state.fb.nr_cbufs; i++) + color[i] = tile->color[i] + 4 * block_offset; + + /* depth buffer */ + depth = tile->depth + block_offset; + + /* run shader */ + state->jit_function[0]( &state->jit_context, + tile_x + x, tile_y + y, + inputs->a0, + inputs->dadx, + inputs->dady, + color, + depth, + INT_MIN, INT_MIN, INT_MIN, + NULL, NULL, NULL ); + } + } +} + + +/** + * Compute shading for a 4x4 block of pixels. + * This is a bin command called during bin processing. + */ +void lp_rast_shade_quads( struct lp_rasterizer *rast, + unsigned thread_index, + const struct lp_rast_shader_inputs *inputs, + unsigned x, unsigned y, + int32_t c1, int32_t c2, int32_t c3) +{ + struct lp_rasterizer_task *task = &rast->tasks[thread_index]; + const struct lp_rast_state *state = task->current_state; + struct lp_rast_tile *tile = &task->tile; + uint8_t *color[PIPE_MAX_COLOR_BUFS]; + void *depth; + unsigned i; + unsigned ix, iy; + int block_offset; + +#ifdef DEBUG + assert(state); + + /* Sanity checks */ + assert(x % TILE_VECTOR_WIDTH == 0); + assert(y % TILE_VECTOR_HEIGHT == 0); + + assert((x % 4) == 0); + assert((y % 4) == 0); +#endif + + ix = x % TILE_SIZE; + iy = y % TILE_SIZE; + + /* offset of the 16x16 pixel block within the tile */ + block_offset = ((iy / 4) * (16 * 16) + (ix / 4) * 16); + + /* color buffer */ + for (i = 0; i < rast->state.fb.nr_cbufs; i++) + color[i] = tile->color[i] + 4 * block_offset; + + /* depth buffer */ + depth = tile->depth + block_offset; + + + +#ifdef DEBUG + assert(lp_check_alignment(tile->depth, 16)); + assert(lp_check_alignment(tile->color[0], 16)); + assert(lp_check_alignment(state->jit_context.blend_color, 16)); + + assert(lp_check_alignment(inputs->step[0], 16)); + assert(lp_check_alignment(inputs->step[1], 16)); + assert(lp_check_alignment(inputs->step[2], 16)); +#endif + + /* run shader */ + state->jit_function[1]( &state->jit_context, + x, y, + inputs->a0, + inputs->dadx, + inputs->dady, + color, + depth, + c1, c2, c3, + inputs->step[0], inputs->step[1], inputs->step[2]); +} + + +/** + * Set top row and left column of the tile's pixels to white. For debugging. + */ +static void +outline_tile(uint8_t *tile) +{ + const uint8_t val = 0xff; + unsigned i; + + for (i = 0; i < TILE_SIZE; i++) { + TILE_PIXEL(tile, i, 0, 0) = val; + TILE_PIXEL(tile, i, 0, 1) = val; + TILE_PIXEL(tile, i, 0, 2) = val; + TILE_PIXEL(tile, i, 0, 3) = val; + + TILE_PIXEL(tile, 0, i, 0) = val; + TILE_PIXEL(tile, 0, i, 1) = val; + TILE_PIXEL(tile, 0, i, 2) = val; + TILE_PIXEL(tile, 0, i, 3) = val; + } +} + + +/** + * Draw grid of gray lines at 16-pixel intervals across the tile to + * show the sub-tile boundaries. For debugging. + */ +static void +outline_subtiles(uint8_t *tile) +{ + const uint8_t val = 0x80; + const unsigned step = 16; + unsigned i, j; + + for (i = 0; i < TILE_SIZE; i += step) { + for (j = 0; j < TILE_SIZE; j++) { + TILE_PIXEL(tile, i, j, 0) = val; + TILE_PIXEL(tile, i, j, 1) = val; + TILE_PIXEL(tile, i, j, 2) = val; + TILE_PIXEL(tile, i, j, 3) = val; + + TILE_PIXEL(tile, j, i, 0) = val; + TILE_PIXEL(tile, j, i, 1) = val; + TILE_PIXEL(tile, j, i, 2) = val; + TILE_PIXEL(tile, j, i, 3) = val; + } + } + + outline_tile(tile); +} + + + +/** + * Write the rasterizer's color tile to the framebuffer. + */ +static void lp_rast_store_color( struct lp_rasterizer *rast, + unsigned thread_index) +{ + struct lp_rasterizer_task *task = &rast->tasks[thread_index]; + const unsigned x = task->x; + const unsigned y = task->y; + unsigned i; + + for (i = 0; i < rast->state.fb.nr_cbufs; i++) { + struct pipe_transfer *transfer = rast->cbuf_transfer[i]; + int w = TILE_SIZE; + int h = TILE_SIZE; + + if (x >= transfer->width) + continue; + + if (y >= transfer->height) + continue; + + LP_DBG(DEBUG_RAST, "%s [%u] %d,%d %dx%d\n", __FUNCTION__, + thread_index, x, y, w, h); + + if (LP_DEBUG & DEBUG_SHOW_SUBTILES) + outline_subtiles(task->tile.color[i]); + else if (LP_DEBUG & DEBUG_SHOW_TILES) + outline_tile(task->tile.color[i]); + + lp_tile_write_4ub(transfer->texture->format, + task->tile.color[i], + rast->cbuf_map[i], + transfer->stride, + x, y, + w, h); + + LP_COUNT(nr_color_tile_store); + } +} + + +static void +lp_tile_write_z32(const uint32_t *src, uint8_t *dst, unsigned dst_stride, + unsigned x0, unsigned y0, unsigned w, unsigned h) +{ + unsigned x, y; + uint8_t *dst_row = dst + y0*dst_stride; + for (y = 0; y < h; ++y) { + uint32_t *dst_pixel = (uint32_t *)(dst_row + x0*4); + for (x = 0; x < w; ++x) { + *dst_pixel++ = *src++; + } + dst_row += dst_stride; + } +} + +/** + * Write the rasterizer's z/stencil tile to the framebuffer. + */ +static void lp_rast_store_zstencil( struct lp_rasterizer *rast, + unsigned thread_index ) +{ + struct lp_rasterizer_task *task = &rast->tasks[thread_index]; + const unsigned x = task->x; + const unsigned y = task->y; + unsigned w = TILE_SIZE; + unsigned h = TILE_SIZE; + + if (x + w > rast->state.fb.width) + w -= x + w - rast->state.fb.width; + + if (y + h > rast->state.fb.height) + h -= y + h - rast->state.fb.height; + + LP_DBG(DEBUG_RAST, "%s %d,%d %dx%d\n", __FUNCTION__, x, y, w, h); + + assert(rast->zsbuf_transfer->texture->format == PIPE_FORMAT_Z32_UNORM); + lp_tile_write_z32(task->tile.depth, + rast->zsbuf_map, + rast->zsbuf_transfer->stride, + x, y, w, h); +} + + +/** + * Write the rasterizer's tiles to the framebuffer. + */ +static void +lp_rast_end_tile( struct lp_rasterizer *rast, + unsigned thread_index ) +{ + LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__); + + if (rast->state.write_color) + lp_rast_store_color(rast, thread_index); + + if (rast->state.write_zstencil) + lp_rast_store_zstencil(rast, thread_index); +} + + +/** + * Signal on a fence. This is called during bin execution/rasterization. + * Called per thread. + */ +void lp_rast_fence( struct lp_rasterizer *rast, + unsigned thread_index, + const union lp_rast_cmd_arg arg ) +{ + struct lp_fence *fence = arg.fence; + + pipe_mutex_lock( fence->mutex ); + + fence->count++; + assert(fence->count <= fence->rank); + + LP_DBG(DEBUG_RAST, "%s count=%u rank=%u\n", __FUNCTION__, + fence->count, fence->rank); + + pipe_condvar_signal( fence->signalled ); + + pipe_mutex_unlock( fence->mutex ); +} + + +/** + * When all the threads are done rasterizing a scene, one thread will + * call this function to reset the scene and put it onto the empty queue. + */ +static void +release_scene( struct lp_rasterizer *rast, + struct lp_scene *scene ) +{ + util_unreference_framebuffer_state( &scene->fb ); + + lp_scene_reset( scene ); + lp_scene_enqueue( rast->empty_scenes, scene ); + rast->curr_scene = NULL; +} + + +/** + * Rasterize commands for a single bin. + * \param x, y position of the bin's tile in the framebuffer + * Must be called between lp_rast_begin() and lp_rast_end(). + * Called per thread. + */ +static void +rasterize_bin( struct lp_rasterizer *rast, + unsigned thread_index, + const struct cmd_bin *bin, + int x, int y) +{ + const struct cmd_block_list *commands = &bin->commands; + struct cmd_block *block; + unsigned k; + + lp_rast_start_tile( rast, thread_index, x, y ); + + /* simply execute each of the commands in the block list */ + for (block = commands->head; block; block = block->next) { + for (k = 0; k < block->count; k++) { + block->cmd[k]( rast, thread_index, block->arg[k] ); + } + } + + lp_rast_end_tile( rast, thread_index ); +} + + +#define RAST(x) { lp_rast_##x, #x } + +static struct { + lp_rast_cmd cmd; + const char *name; +} cmd_names[] = +{ + RAST(load_color), + RAST(load_zstencil), + RAST(clear_color), + RAST(clear_zstencil), + RAST(triangle), + RAST(shade_tile), + RAST(set_state), + RAST(fence), +}; + +static void +debug_bin( const struct cmd_bin *bin ) +{ + const struct cmd_block *head = bin->commands.head; + int i, j; + + for (i = 0; i < head->count; i++) { + debug_printf("%d: ", i); + for (j = 0; j < Elements(cmd_names); j++) { + if (head->cmd[i] == cmd_names[j].cmd) { + debug_printf("%s\n", cmd_names[j].name); + break; + } + } + if (j == Elements(cmd_names)) + debug_printf("...other\n"); + } + +} + +/* An empty bin is one that just loads the contents of the tile and + * stores them again unchanged. This typically happens when bins have + * been flushed for some reason in the middle of a frame, or when + * incremental updates are being made to a render target. + * + * Try to avoid doing pointless work in this case. + */ +static boolean +is_empty_bin( const struct cmd_bin *bin ) +{ + const struct cmd_block *head = bin->commands.head; + int i; + + if (0) + debug_bin(bin); + + /* We emit at most two load-tile commands at the start of the first + * command block. In addition we seem to emit a couple of + * set-state commands even in empty bins. + * + * As a heuristic, if a bin has more than 4 commands, consider it + * non-empty. + */ + if (head->next != NULL || + head->count > 4) { + return FALSE; + } + + for (i = 0; i < head->count; i++) + if (head->cmd[i] != lp_rast_load_color && + head->cmd[i] != lp_rast_load_zstencil && + head->cmd[i] != lp_rast_set_state) { + return FALSE; + } + + return TRUE; +} + + + +/** + * Rasterize/execute all bins within a scene. + * Called per thread. + */ +static void +rasterize_scene( struct lp_rasterizer *rast, + unsigned thread_index, + struct lp_scene *scene, + bool write_depth ) +{ + /* loop over scene bins, rasterize each */ +#if 0 + { + unsigned i, j; + for (i = 0; i < scene->tiles_x; i++) { + for (j = 0; j < scene->tiles_y; j++) { + struct cmd_bin *bin = lp_get_bin(scene, i, j); + rasterize_bin( rast, thread_index, + bin, i * TILE_SIZE, j * TILE_SIZE ); + } + } + } +#else + { + struct cmd_bin *bin; + int x, y; + + assert(scene); + while ((bin = lp_scene_bin_iter_next(scene, &x, &y))) { + if (!is_empty_bin( bin )) + rasterize_bin( rast, thread_index, bin, x * TILE_SIZE, y * TILE_SIZE); + } + } +#endif +} + + +/** + * Called by setup module when it has something for us to render. + */ +void +lp_rasterize_scene( struct lp_rasterizer *rast, + struct lp_scene *scene, + const struct pipe_framebuffer_state *fb, + bool write_depth ) +{ + boolean debug = false; + + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); + + if (debug) { + unsigned x, y; + debug_printf("rasterize scene:\n"); + debug_printf(" data size: %u\n", lp_scene_data_size(scene)); + for (y = 0; y < scene->tiles_y; y++) { + for (x = 0; x < scene->tiles_x; x++) { + debug_printf(" bin %u, %u size: %u\n", x, y, + lp_scene_bin_size(scene, x, y)); + } + } + } + + /* save framebuffer state in the bin */ + util_copy_framebuffer_state(&scene->fb, fb); + scene->write_depth = write_depth; + + if (rast->num_threads == 0) { + /* no threading */ + + lp_rast_begin( rast, fb, + fb->nr_cbufs != 0, /* always write color if cbufs present */ + fb->zsbuf != NULL && write_depth ); + + lp_scene_bin_iter_begin( scene ); + rasterize_scene( rast, 0, scene, write_depth ); + + release_scene( rast, scene ); + + lp_rast_end( rast ); + } + else { + /* threaded rendering! */ + unsigned i; + + lp_scene_enqueue( rast->full_scenes, scene ); + + /* signal the threads that there's work to do */ + for (i = 0; i < rast->num_threads; i++) { + pipe_semaphore_signal(&rast->tasks[i].work_ready); + } + + /* wait for work to complete */ + for (i = 0; i < rast->num_threads; i++) { + pipe_semaphore_wait(&rast->tasks[i].work_done); + } + } + + LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__); +} + + +/** + * This is the thread's main entrypoint. + * It's a simple loop: + * 1. wait for work + * 2. do work + * 3. signal that we're done + */ +static PIPE_THREAD_ROUTINE( thread_func, init_data ) +{ + struct lp_rasterizer_task *task = (struct lp_rasterizer_task *) init_data; + struct lp_rasterizer *rast = task->rast; + boolean debug = false; + + while (1) { + /* wait for work */ + if (debug) + debug_printf("thread %d waiting for work\n", task->thread_index); + pipe_semaphore_wait(&task->work_ready); + + if (task->thread_index == 0) { + /* thread[0]: + * - get next scene to rasterize + * - map the framebuffer surfaces + */ + const struct pipe_framebuffer_state *fb; + boolean write_depth; + + rast->curr_scene = lp_scene_dequeue( rast->full_scenes, TRUE ); + + lp_scene_bin_iter_begin( rast->curr_scene ); + + fb = &rast->curr_scene->fb; + write_depth = rast->curr_scene->write_depth; + + lp_rast_begin( rast, fb, + fb->nr_cbufs != 0, + fb->zsbuf != NULL && write_depth ); + } + + /* Wait for all threads to get here so that threads[1+] don't + * get a null rast->curr_scene pointer. + */ + pipe_barrier_wait( &rast->barrier ); + + /* do work */ + if (debug) + debug_printf("thread %d doing work\n", task->thread_index); + rasterize_scene(rast, + task->thread_index, + rast->curr_scene, + rast->curr_scene->write_depth); + + /* wait for all threads to finish with this scene */ + pipe_barrier_wait( &rast->barrier ); + + if (task->thread_index == 0) { + /* thread[0]: + * - release the scene object + * - unmap the framebuffer surfaces + */ + release_scene( rast, rast->curr_scene ); + lp_rast_end( rast ); + } + + /* signal done with work */ + if (debug) + debug_printf("thread %d done working\n", task->thread_index); + pipe_semaphore_signal(&task->work_done); + } + + return NULL; +} + + +/** + * Initialize semaphores and spawn the threads. + */ +static void +create_rast_threads(struct lp_rasterizer *rast) +{ + unsigned i; + +#ifdef PIPE_OS_WINDOWS + /* Multithreading not supported on windows until conditions and barriers are + * properly implemented. */ + rast->num_threads = 0; +#else + rast->num_threads = util_cpu_caps.nr_cpus; + rast->num_threads = debug_get_num_option("LP_NUM_THREADS", rast->num_threads); + rast->num_threads = MIN2(rast->num_threads, MAX_THREADS); +#endif + + /* NOTE: if num_threads is zero, we won't use any threads */ + for (i = 0; i < rast->num_threads; i++) { + pipe_semaphore_init(&rast->tasks[i].work_ready, 0); + pipe_semaphore_init(&rast->tasks[i].work_done, 0); + rast->threads[i] = pipe_thread_create(thread_func, + (void *) &rast->tasks[i]); + } +} + + + +/** + * Create new lp_rasterizer. + * \param empty the queue to put empty scenes on after we've finished + * processing them. + */ +struct lp_rasterizer * +lp_rast_create( struct pipe_screen *screen, struct lp_scene_queue *empty ) +{ + struct lp_rasterizer *rast; + unsigned i, cbuf; + + rast = CALLOC_STRUCT(lp_rasterizer); + if(!rast) + return NULL; + + rast->screen = screen; + + rast->empty_scenes = empty; + rast->full_scenes = lp_scene_queue_create(); + + for (i = 0; i < Elements(rast->tasks); i++) { + struct lp_rasterizer_task *task = &rast->tasks[i]; + + for (cbuf = 0; cbuf < PIPE_MAX_COLOR_BUFS; cbuf++ ) + task->tile.color[cbuf] = align_malloc(TILE_SIZE * TILE_SIZE * 4, 16); + + task->tile.depth = align_malloc(TILE_SIZE * TILE_SIZE * 4, 16); + task->rast = rast; + task->thread_index = i; + } + + create_rast_threads(rast); + + /* for synchronizing rasterization threads */ + pipe_barrier_init( &rast->barrier, rast->num_threads ); + + return rast; +} + + +/* Shutdown: + */ +void lp_rast_destroy( struct lp_rasterizer *rast ) +{ + unsigned i, cbuf; + + util_unreference_framebuffer_state(&rast->state.fb); + + for (i = 0; i < Elements(rast->tasks); i++) { + align_free(rast->tasks[i].tile.depth); + for (cbuf = 0; cbuf < PIPE_MAX_COLOR_BUFS; cbuf++ ) + align_free(rast->tasks[i].tile.color[cbuf]); + } + + /* for synchronizing rasterization threads */ + pipe_barrier_destroy( &rast->barrier ); + + FREE(rast); +} + + +/** Return number of rasterization threads */ +unsigned +lp_rast_get_num_threads( struct lp_rasterizer *rast ) +{ + return rast->num_threads; +} diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h new file mode 100644 index 0000000000..34da73eb50 --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_rast.h @@ -0,0 +1,236 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +/** + * The rast code is concerned with rasterization of command bins. + * Each screen tile has a bin associated with it. To render the + * scene we iterate over the tile bins and execute the commands + * in each bin. + * We'll do that with multiple threads... + */ + + +#ifndef LP_RAST_H +#define LP_RAST_H + +#include "pipe/p_compiler.h" +#include "lp_jit.h" + + +struct lp_rasterizer; +struct lp_scene; +struct lp_scene_queue; +struct lp_fence; +struct cmd_bin; +struct pipe_screen; + +/** For sub-pixel positioning */ +#define FIXED_ORDER 4 +#define FIXED_ONE (1<<FIXED_ORDER) + + +/** + * Rasterization state. + * Objects of this type are put into the shared data bin and pointed + * to by commands in the per-tile bins. + */ +struct lp_rast_state { + /* State for the shader. This also contains state which feeds into + * the fragment shader, such as blend color and alpha ref value. + */ + struct lp_jit_context jit_context; + + /* The shader itself. Probably we also need to pass a pointer to + * the tile color/z/stencil data somehow: + * jit_function[0] skips the triangle in/out test code + * jit_function[1] does triangle in/out testing + */ + lp_jit_frag_func jit_function[2]; + + boolean opaque; +}; + + +/** + * Coefficients necessary to run the shader at a given location. + * First coefficient is position. + * These pointers point into the bin data buffer. + */ +struct lp_rast_shader_inputs { + float (*a0)[4]; + float (*dadx)[4]; + float (*dady)[4]; + + /* edge/step info for 3 edges and 4x4 block of pixels */ + PIPE_ALIGN_VAR(16) int step[3][16]; +}; + + +/** + * Rasterization information for a triangle known to be in this bin, + * plus inputs to run the shader: + * These fields are tile- and bin-independent. + * Objects of this type are put into the setup_context::data buffer. + */ +struct lp_rast_triangle { + /* one-pixel sized trivial accept offsets for each plane */ + int ei1; + int ei2; + int ei3; + + /* one-pixel sized trivial reject offsets for each plane */ + int eo1; + int eo2; + int eo3; + + /* y deltas for vertex pairs (in fixed pt) */ + int dy12; + int dy23; + int dy31; + + /* x deltas for vertex pairs (in fixed pt) */ + int dx12; + int dx23; + int dx31; + + /* edge function values at minx,miny ?? */ + int c1, c2, c3; + + /* inputs for the shader */ + PIPE_ALIGN_VAR(16) struct lp_rast_shader_inputs inputs; +}; + + + +struct lp_rasterizer *lp_rast_create( struct pipe_screen *screen, + struct lp_scene_queue *empty ); + +void lp_rast_destroy( struct lp_rasterizer * ); + +unsigned lp_rast_get_num_threads( struct lp_rasterizer * ); + +void lp_rasterize_scene( struct lp_rasterizer *rast, + struct lp_scene *scene, + const struct pipe_framebuffer_state *fb, + bool write_depth ); + + + +union lp_rast_cmd_arg { + const struct lp_rast_shader_inputs *shade_tile; + const struct lp_rast_triangle *triangle; + const struct lp_rast_state *set_state; + uint8_t clear_color[4]; + unsigned clear_zstencil; + struct lp_fence *fence; +}; + + +/* Cast wrappers. Hopefully these compile to noops! + */ +static INLINE union lp_rast_cmd_arg +lp_rast_arg_inputs( const struct lp_rast_shader_inputs *shade_tile ) +{ + union lp_rast_cmd_arg arg; + arg.shade_tile = shade_tile; + return arg; +} + +static INLINE union lp_rast_cmd_arg +lp_rast_arg_triangle( const struct lp_rast_triangle *triangle ) +{ + union lp_rast_cmd_arg arg; + arg.triangle = triangle; + return arg; +} + +static INLINE union lp_rast_cmd_arg +lp_rast_arg_state( const struct lp_rast_state *state ) +{ + union lp_rast_cmd_arg arg; + arg.set_state = state; + return arg; +} + +static INLINE union lp_rast_cmd_arg +lp_rast_arg_fence( struct lp_fence *fence ) +{ + union lp_rast_cmd_arg arg; + arg.fence = fence; + return arg; +} + + +static INLINE union lp_rast_cmd_arg +lp_rast_arg_null( void ) +{ + union lp_rast_cmd_arg arg; + arg.set_state = NULL; + return arg; +} + + + +/** + * Binnable Commands. + * These get put into bins by the setup code and are called when + * the bins are executed. + */ + +void lp_rast_clear_color( struct lp_rasterizer *, + unsigned thread_index, + const union lp_rast_cmd_arg ); + +void lp_rast_clear_zstencil( struct lp_rasterizer *, + unsigned thread_index, + const union lp_rast_cmd_arg ); + +void lp_rast_load_color( struct lp_rasterizer *, + unsigned thread_index, + const union lp_rast_cmd_arg ); + +void lp_rast_load_zstencil( struct lp_rasterizer *, + unsigned thread_index, + const union lp_rast_cmd_arg ); + +void lp_rast_set_state( struct lp_rasterizer *, + unsigned thread_index, + const union lp_rast_cmd_arg ); + +void lp_rast_triangle( struct lp_rasterizer *, + unsigned thread_index, + const union lp_rast_cmd_arg ); + +void lp_rast_shade_tile( struct lp_rasterizer *, + unsigned thread_index, + const union lp_rast_cmd_arg ); + +void lp_rast_fence( struct lp_rasterizer *, + unsigned thread_index, + const union lp_rast_cmd_arg ); + +#endif diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h new file mode 100644 index 0000000000..71e3a301e6 --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h @@ -0,0 +1,172 @@ +/************************************************************************** + * + * 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 LP_RAST_PRIV_H +#define LP_RAST_PRIV_H + +#include "os/os_thread.h" +#include "lp_rast.h" +#include "lp_tile_soa.h" + + +#define MAX_THREADS 8 /* XXX probably temporary here */ + + +struct pipe_transfer; +struct pipe_screen; +struct lp_rasterizer; + + +/** + * A tile's color and depth memory. + * We can choose whatever layout for the internal tile storage we prefer. + */ +struct lp_rast_tile +{ + uint8_t *color[PIPE_MAX_COLOR_BUFS]; + + uint32_t *depth; +}; + + +/** + * Per-thread rasterization state + */ +struct lp_rasterizer_task +{ + struct lp_rast_tile tile; /** Tile color/z/stencil memory */ + + unsigned x, y; /**< Pos of this tile in framebuffer, in pixels */ + + const struct lp_rast_state *current_state; + + /** "back" pointer */ + struct lp_rasterizer *rast; + + /** "my" index */ + unsigned thread_index; + + pipe_semaphore work_ready; + pipe_semaphore work_done; +}; + + +/** + * This is the state required while rasterizing tiles. + * Note that this contains per-thread information too. + * The tile size is TILE_SIZE x TILE_SIZE pixels. + */ +struct lp_rasterizer +{ + boolean clipped_tile; + boolean check_for_clipped_tiles; + + /* Framebuffer stuff + */ + struct pipe_screen *screen; + struct pipe_transfer *cbuf_transfer[PIPE_MAX_COLOR_BUFS]; + struct pipe_transfer *zsbuf_transfer; + void *cbuf_map[PIPE_MAX_COLOR_BUFS]; + void *zsbuf_map; + + struct { + struct pipe_framebuffer_state fb; + boolean write_color; + boolean write_zstencil; + unsigned clear_color; + unsigned clear_depth; + char clear_stencil; + } state; + + /** The incoming queue of scenes ready to rasterize */ + struct lp_scene_queue *full_scenes; + /** The outgoing queue of processed scenes to return to setup modulee */ + struct lp_scene_queue *empty_scenes; + + /** The scene currently being rasterized by the threads */ + struct lp_scene *curr_scene; + + /** A task object for each rasterization thread */ + struct lp_rasterizer_task tasks[MAX_THREADS]; + + unsigned num_threads; + pipe_thread threads[MAX_THREADS]; + + /** For synchronizing the rasterization threads */ + pipe_barrier barrier; +}; + + +void lp_rast_shade_quads( struct lp_rasterizer *rast, + unsigned thread_index, + const struct lp_rast_shader_inputs *inputs, + unsigned x, unsigned y, + int32_t c1, int32_t c2, int32_t c3); + + +/** + * Shade all pixels in a 4x4 block. The fragment code omits the + * triangle in/out tests. + * \param x, y location of 4x4 block in window coords + */ +static INLINE void +lp_rast_shade_quads_all( struct lp_rasterizer *rast, + unsigned thread_index, + const struct lp_rast_shader_inputs *inputs, + unsigned x, unsigned y ) +{ + const struct lp_rast_state *state = rast->tasks[thread_index].current_state; + struct lp_rast_tile *tile = &rast->tasks[thread_index].tile; + const unsigned ix = x % TILE_SIZE, iy = y % TILE_SIZE; + uint8_t *color[PIPE_MAX_COLOR_BUFS]; + void *depth; + unsigned block_offset, i; + + /* offset of the containing 16x16 pixel block within the tile */ + block_offset = (iy / 4) * (16 * 16) + (ix / 4) * 16; + + /* color buffer */ + for (i = 0; i < rast->state.fb.nr_cbufs; i++) + color[i] = tile->color[i] + 4 * block_offset; + + /* depth buffer */ + depth = tile->depth + block_offset; + + /* run shader */ + state->jit_function[0]( &state->jit_context, + x, y, + inputs->a0, + inputs->dadx, + inputs->dady, + color, + depth, + INT_MIN, INT_MIN, INT_MIN, + NULL, NULL, NULL ); +} + + +#endif diff --git a/src/gallium/drivers/llvmpipe/lp_rast_tri.c b/src/gallium/drivers/llvmpipe/lp_rast_tri.c new file mode 100644 index 0000000000..3f76f159df --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_rast_tri.c @@ -0,0 +1,251 @@ +/************************************************************************** + * + * Copyright 2007-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. + * + **************************************************************************/ + +/* + * Rasterization for binned triangles within a tile + */ + +#include <limits.h> +#include "util/u_math.h" +#include "lp_debug.h" +#include "lp_perf.h" +#include "lp_rast_priv.h" +#include "lp_tile_soa.h" + + +/** + * Map an index in [0,15] to an x,y position, multiplied by 4. + * This is used to get the position of each subtile in a 4x4 + * grid of edge step values. + * Note: we can use some bit twiddling to compute these values instead + * of using a look-up table, but there's no measurable performance + * difference. + */ +static const int pos_table4[16][2] = { + { 0, 0 }, + { 4, 0 }, + { 0, 4 }, + { 4, 4 }, + { 8, 0 }, + { 12, 0 }, + { 8, 4 }, + { 12, 4 }, + { 0, 8 }, + { 4, 8 }, + { 0, 12 }, + { 4, 12 }, + { 8, 8 }, + { 12, 8 }, + { 8, 12 }, + { 12, 12 } +}; + + +static const int pos_table16[16][2] = { + { 0, 0 }, + { 16, 0 }, + { 0, 16 }, + { 16, 16 }, + { 32, 0 }, + { 48, 0 }, + { 32, 16 }, + { 48, 16 }, + { 0, 32 }, + { 16, 32 }, + { 0, 48 }, + { 16, 48 }, + { 32, 32 }, + { 48, 32 }, + { 32, 48 }, + { 48, 48 } +}; + + +/** + * Shade all pixels in a 4x4 block. + */ +static void +block_full_4( struct lp_rasterizer_task *rast_task, + const struct lp_rast_triangle *tri, + int x, int y ) +{ + lp_rast_shade_quads_all(rast_task->rast, + rast_task->thread_index, + &tri->inputs, + x, y); +} + + +/** + * Shade all pixels in a 16x16 block. + */ +static void +block_full_16( struct lp_rasterizer_task *rast_task, + const struct lp_rast_triangle *tri, + int x, int y ) +{ + unsigned ix, iy; + assert(x % 16 == 0); + assert(y % 16 == 0); + for (iy = 0; iy < 16; iy += 4) + for (ix = 0; ix < 16; ix += 4) + block_full_4(rast_task, tri, x + ix, y + iy); +} + + +/** + * Pass the 4x4 pixel block to the shader function. + * Determination of which of the 16 pixels lies inside the triangle + * will be done as part of the fragment shader. + */ +static void +do_block_4( struct lp_rasterizer_task *rast_task, + const struct lp_rast_triangle *tri, + int x, int y, + int c1, + int c2, + int c3 ) +{ + lp_rast_shade_quads(rast_task->rast, + rast_task->thread_index, + &tri->inputs, + x, y, + -c1, -c2, -c3); +} + + +/** + * Evaluate a 16x16 block of pixels to determine which 4x4 subblocks are in/out + * of the triangle's bounds. + */ +static void +do_block_16( struct lp_rasterizer_task *rast_task, + const struct lp_rast_triangle *tri, + int x, int y, + int c1, + int c2, + int c3 ) +{ + const int eo1 = tri->eo1 * 4; + const int eo2 = tri->eo2 * 4; + const int eo3 = tri->eo3 * 4; + const int *step0 = tri->inputs.step[0]; + const int *step1 = tri->inputs.step[1]; + const int *step2 = tri->inputs.step[2]; + int i; + + assert(x % 16 == 0); + assert(y % 16 == 0); + + for (i = 0; i < 16; i++) { + int cx1 = c1 + step0[i] * 4; + int cx2 = c2 + step1[i] * 4; + int cx3 = c3 + step2[i] * 4; + + if (cx1 + eo1 < 0 || + cx2 + eo2 < 0 || + cx3 + eo3 < 0) { + /* the block is completely outside the triangle - nop */ + LP_COUNT(nr_empty_4); + } + else { + int px = x + pos_table4[i][0]; + int py = y + pos_table4[i][1]; + /* Don't bother testing if the 4x4 block is entirely in/out of + * the triangle. It's a little faster to do it in the jit code. + */ + LP_COUNT(nr_non_empty_4); + do_block_4(rast_task, tri, px, py, cx1, cx2, cx3); + } + } +} + + +/** + * Scan the tile in chunks and figure out which pixels to rasterize + * for this triangle. + */ +void +lp_rast_triangle( struct lp_rasterizer *rast, + unsigned thread_index, + const union lp_rast_cmd_arg arg ) +{ + struct lp_rasterizer_task *rast_task = &rast->tasks[thread_index]; + const struct lp_rast_triangle *tri = arg.triangle; + + int x = rast_task->x; + int y = rast_task->y; + unsigned i; + + int c1 = tri->c1 + tri->dx12 * y - tri->dy12 * x; + int c2 = tri->c2 + tri->dx23 * y - tri->dy23 * x; + int c3 = tri->c3 + tri->dx31 * y - tri->dy31 * x; + + int ei1 = tri->ei1 * 16; + int ei2 = tri->ei2 * 16; + int ei3 = tri->ei3 * 16; + + int eo1 = tri->eo1 * 16; + int eo2 = tri->eo2 * 16; + int eo3 = tri->eo3 * 16; + + LP_DBG(DEBUG_RAST, "lp_rast_triangle\n"); + + /* Walk over the tile to build a list of 4x4 pixel blocks which will + * be filled/shaded. We do this at two granularities: 16x16 blocks + * and then 4x4 blocks. + */ + for (i = 0; i < 16; i++) { + int cx1 = c1 + (tri->inputs.step[0][i] * 16); + int cx2 = c2 + (tri->inputs.step[1][i] * 16); + int cx3 = c3 + (tri->inputs.step[2][i] * 16); + + if (cx1 + eo1 < 0 || + cx2 + eo2 < 0 || + cx3 + eo3 < 0) { + /* the block is completely outside the triangle - nop */ + LP_COUNT(nr_empty_16); + } + else { + int px = x + pos_table16[i][0]; + int py = y + pos_table16[i][1]; + + if (cx1 + ei1 > 0 && + cx2 + ei2 > 0 && + cx3 + ei3 > 0) { + /* the block is completely inside the triangle */ + LP_COUNT(nr_fully_covered_16); + block_full_16(rast_task, tri, px, py); + } + else { + /* the block is partially in/out of the triangle */ + LP_COUNT(nr_partially_covered_16); + do_block_16(rast_task, tri, px, py, cx1, cx2, cx3); + } + } + } +} diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c new file mode 100644 index 0000000000..b7116297ec --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_scene.c @@ -0,0 +1,392 @@ +/************************************************************************** + * + * 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_math.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "util/u_simple_list.h" +#include "lp_scene.h" + + +struct lp_scene * +lp_scene_create(void) +{ + struct lp_scene *scene = CALLOC_STRUCT(lp_scene); + if (scene) + lp_scene_init(scene); + return scene; +} + + +void +lp_scene_destroy(struct lp_scene *scene) +{ + lp_scene_reset(scene); + lp_scene_free_bin_data(scene); + FREE(scene); +} + + +void +lp_scene_init(struct lp_scene *scene) +{ + unsigned i, j; + for (i = 0; i < TILES_X; i++) + for (j = 0; j < TILES_Y; j++) { + struct cmd_bin *bin = lp_scene_get_bin(scene, i, j); + bin->commands.head = bin->commands.tail = CALLOC_STRUCT(cmd_block); + } + + scene->data.head = + scene->data.tail = CALLOC_STRUCT(data_block); + + make_empty_list(&scene->textures); + + pipe_mutex_init(scene->mutex); +} + + +/** + * Check if the scene's bins are all empty. + * For debugging purposes. + */ +boolean +lp_scene_is_empty(struct lp_scene *scene ) +{ + unsigned x, y; + + for (y = 0; y < TILES_Y; y++) { + for (x = 0; x < TILES_X; x++) { + const struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); + const struct cmd_block_list *list = &bin->commands; + if (list->head != list->tail || list->head->count > 0) { + return FALSE; + } + } + } + return TRUE; +} + + +void +lp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y) +{ + struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); + struct cmd_block_list *list = &bin->commands; + struct cmd_block *block; + struct cmd_block *tmp; + + for (block = list->head; block != list->tail; block = tmp) { + tmp = block->next; + FREE(block); + } + + assert(list->tail->next == NULL); + list->head = list->tail; + list->head->count = 0; +} + + +/** + * Set scene to empty state. + */ +void +lp_scene_reset(struct lp_scene *scene ) +{ + unsigned i, j; + + /* Free all but last binner command lists: + */ + for (i = 0; i < scene->tiles_x; i++) { + for (j = 0; j < scene->tiles_y; j++) { + lp_scene_bin_reset(scene, i, j); + } + } + + assert(lp_scene_is_empty(scene)); + + /* Free all but last binned data block: + */ + { + struct data_block_list *list = &scene->data; + struct data_block *block, *tmp; + + for (block = list->head; block != list->tail; block = tmp) { + tmp = block->next; + FREE(block); + } + + assert(list->tail->next == NULL); + list->head = list->tail; + list->head->used = 0; + } + + /* Release texture refs + */ + { + struct texture_ref *ref, *next, *ref_list = &scene->textures; + for (ref = ref_list->next; ref != ref_list; ref = next) { + next = next_elem(ref); + pipe_texture_reference(&ref->texture, NULL); + FREE(ref); + } + make_empty_list(ref_list); + } +} + + +/** + * Free all data associated with the given bin, but don't free(scene). + */ +void +lp_scene_free_bin_data(struct lp_scene *scene) +{ + unsigned i, j; + + for (i = 0; i < TILES_X; i++) + for (j = 0; j < TILES_Y; j++) { + struct cmd_bin *bin = lp_scene_get_bin(scene, i, j); + /* lp_reset_scene() should have been already called */ + assert(bin->commands.head == bin->commands.tail); + FREE(bin->commands.head); + bin->commands.head = NULL; + bin->commands.tail = NULL; + } + + FREE(scene->data.head); + scene->data.head = NULL; + + pipe_mutex_destroy(scene->mutex); +} + + +void +lp_scene_set_framebuffer_size( struct lp_scene *scene, + unsigned width, unsigned height ) +{ + assert(lp_scene_is_empty(scene)); + + scene->tiles_x = align(width, TILE_SIZE) / TILE_SIZE; + scene->tiles_y = align(height, TILE_SIZE) / TILE_SIZE; +} + + +void +lp_bin_new_cmd_block( struct cmd_block_list *list ) +{ + struct cmd_block *block = MALLOC_STRUCT(cmd_block); + list->tail->next = block; + list->tail = block; + block->next = NULL; + block->count = 0; +} + + +void +lp_bin_new_data_block( struct data_block_list *list ) +{ + struct data_block *block = MALLOC_STRUCT(data_block); + list->tail->next = block; + list->tail = block; + block->next = NULL; + block->used = 0; +} + + +/** Return number of bytes used for all bin data within a scene */ +unsigned +lp_scene_data_size( const struct lp_scene *scene ) +{ + unsigned size = 0; + const struct data_block *block; + for (block = scene->data.head; block; block = block->next) { + size += block->used; + } + return size; +} + + +/** Return number of bytes used for a single bin */ +unsigned +lp_scene_bin_size( const struct lp_scene *scene, unsigned x, unsigned y ) +{ + struct cmd_bin *bin = lp_scene_get_bin((struct lp_scene *) scene, x, y); + const struct cmd_block *cmd; + unsigned size = 0; + for (cmd = bin->commands.head; cmd; cmd = cmd->next) { + size += (cmd->count * + (sizeof(lp_rast_cmd) + sizeof(union lp_rast_cmd_arg))); + } + return size; +} + + +/** + * Add a reference to a texture by the scene. + */ +void +lp_scene_texture_reference( struct lp_scene *scene, + struct pipe_texture *texture ) +{ + struct texture_ref *ref = CALLOC_STRUCT(texture_ref); + if (ref) { + struct texture_ref *ref_list = &scene->textures; + pipe_texture_reference(&ref->texture, texture); + insert_at_tail(ref_list, ref); + } +} + + +/** + * Does this scene have a reference to the given texture? + */ +boolean +lp_scene_is_texture_referenced( const struct lp_scene *scene, + const struct pipe_texture *texture ) +{ + const struct texture_ref *ref_list = &scene->textures; + const struct texture_ref *ref; + foreach (ref, ref_list) { + if (ref->texture == texture) + return TRUE; + } + return FALSE; +} + + +/** + * Return last command in the bin + */ +static lp_rast_cmd +lp_get_last_command( const struct cmd_bin *bin ) +{ + const struct cmd_block *tail = bin->commands.tail; + const unsigned i = tail->count; + if (i > 0) + return tail->cmd[i - 1]; + else + return NULL; +} + + +/** + * Replace the arg of the last command in the bin. + */ +static void +lp_replace_last_command_arg( struct cmd_bin *bin, + const union lp_rast_cmd_arg arg ) +{ + struct cmd_block *tail = bin->commands.tail; + const unsigned i = tail->count; + assert(i > 0); + tail->arg[i - 1] = arg; +} + + + +/** + * Put a state-change command into all bins. + * If we find that the last command in a bin was also a state-change + * command, we can simply replace that one with the new one. + */ +void +lp_scene_bin_state_command( struct lp_scene *scene, + lp_rast_cmd cmd, + const union lp_rast_cmd_arg arg ) +{ + unsigned i, j; + for (i = 0; i < scene->tiles_x; i++) { + for (j = 0; j < scene->tiles_y; j++) { + struct cmd_bin *bin = lp_scene_get_bin(scene, i, j); + lp_rast_cmd last_cmd = lp_get_last_command(bin); + if (last_cmd == cmd) { + lp_replace_last_command_arg(bin, arg); + } + else { + lp_scene_bin_command( scene, i, j, cmd, arg ); + } + } + } +} + + +/** advance curr_x,y to the next bin */ +static boolean +next_bin(struct lp_scene *scene) +{ + scene->curr_x++; + if (scene->curr_x >= scene->tiles_x) { + scene->curr_x = 0; + scene->curr_y++; + } + if (scene->curr_y >= scene->tiles_y) { + /* no more bins */ + return FALSE; + } + return TRUE; +} + + +void +lp_scene_bin_iter_begin( struct lp_scene *scene ) +{ + scene->curr_x = scene->curr_y = -1; +} + + +/** + * Return pointer to next bin to be rendered. + * The lp_scene::curr_x and ::curr_y fields will be advanced. + * Multiple rendering threads will call this function to get a chunk + * of work (a bin) to work on. + */ +struct cmd_bin * +lp_scene_bin_iter_next( struct lp_scene *scene, int *bin_x, int *bin_y ) +{ + struct cmd_bin *bin = NULL; + + pipe_mutex_lock(scene->mutex); + + if (scene->curr_x < 0) { + /* first bin */ + scene->curr_x = 0; + scene->curr_y = 0; + } + else if (!next_bin(scene)) { + /* no more bins left */ + goto end; + } + + bin = lp_scene_get_bin(scene, scene->curr_x, scene->curr_y); + *bin_x = scene->curr_x; + *bin_y = scene->curr_y; + +end: + /*printf("return bin %p at %d, %d\n", (void *) bin, *bin_x, *bin_y);*/ + pipe_mutex_unlock(scene->mutex); + return bin; +} diff --git a/src/gallium/drivers/llvmpipe/lp_scene.h b/src/gallium/drivers/llvmpipe/lp_scene.h new file mode 100644 index 0000000000..fb478cc2eb --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_scene.h @@ -0,0 +1,301 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + + +/** + * Binner data structures and bin-related functions. + * Note: the "setup" code is concerned with building scenes while + * The "rast" code is concerned with consuming/executing scenes. + */ + +#ifndef LP_SCENE_H +#define LP_SCENE_H + +#include "os/os_thread.h" +#include "lp_tile_soa.h" +#include "lp_rast.h" + + +/* We're limited to 2K by 2K for 32bit fixed point rasterization. + * Will need a 64-bit version for larger framebuffers. + */ +#define MAXHEIGHT 2048 +#define MAXWIDTH 2048 +#define TILES_X (MAXWIDTH / TILE_SIZE) +#define TILES_Y (MAXHEIGHT / TILE_SIZE) + + +#define CMD_BLOCK_MAX 128 +#define DATA_BLOCK_SIZE (16 * 1024 - sizeof(unsigned) - sizeof(void *)) + + + +/* switch to a non-pointer value for this: + */ +typedef void (*lp_rast_cmd)( struct lp_rasterizer *, + unsigned thread_index, + const union lp_rast_cmd_arg ); + +struct cmd_block { + lp_rast_cmd cmd[CMD_BLOCK_MAX]; + union lp_rast_cmd_arg arg[CMD_BLOCK_MAX]; + unsigned count; + struct cmd_block *next; +}; + +struct data_block { + ubyte data[DATA_BLOCK_SIZE]; + unsigned used; + struct data_block *next; +}; + +struct cmd_block_list { + struct cmd_block *head; + struct cmd_block *tail; +}; + +/** + * For each screen tile we have one of these bins. + */ +struct cmd_bin { + struct cmd_block_list commands; +}; + + +/** + * This stores bulk data which is shared by all bins within a scene. + * Examples include triangle data and state data. The commands in + * the per-tile bins will point to chunks of data in this structure. + */ +struct data_block_list { + struct data_block *head; + struct data_block *tail; +}; + + +/** List of texture references */ +struct texture_ref { + struct pipe_texture *texture; + struct texture_ref *prev, *next; /**< linked list w/ u_simple_list.h */ +}; + + +/** + * All bins and bin data are contained here. + * Per-bin data goes into the 'tile' bins. + * Shared data goes into the 'data' buffer. + * + * When there are multiple threads, will want to double-buffer between + * scenes: + */ +struct lp_scene { + struct cmd_bin tile[TILES_X][TILES_Y]; + struct data_block_list data; + + /** the framebuffer to render the scene into */ + struct pipe_framebuffer_state fb; + + /** list of textures referenced by the scene commands */ + struct texture_ref textures; + + boolean write_depth; + + /** + * Number of active tiles in each dimension. + * This basically the framebuffer size divided by tile size + */ + unsigned tiles_x, tiles_y; + + int curr_x, curr_y; /**< for iterating over bins */ + pipe_mutex mutex; +}; + + + +struct lp_scene *lp_scene_create(void); + +void lp_scene_destroy(struct lp_scene *scene); + + +void lp_scene_init(struct lp_scene *scene); + +boolean lp_scene_is_empty(struct lp_scene *scene ); + +void lp_scene_reset(struct lp_scene *scene ); + +void lp_scene_free_bin_data(struct lp_scene *scene); + +void lp_scene_set_framebuffer_size( struct lp_scene *scene, + unsigned width, unsigned height ); + +void lp_bin_new_data_block( struct data_block_list *list ); + +void lp_bin_new_cmd_block( struct cmd_block_list *list ); + +unsigned lp_scene_data_size( const struct lp_scene *scene ); + +unsigned lp_scene_bin_size( const struct lp_scene *scene, unsigned x, unsigned y ); + +void lp_scene_texture_reference( struct lp_scene *scene, + struct pipe_texture *texture ); + +boolean lp_scene_is_texture_referenced( const struct lp_scene *scene, + const struct pipe_texture *texture ); + + +/** + * Allocate space for a command/data in the bin's data buffer. + * Grow the block list if needed. + */ +static INLINE void * +lp_scene_alloc( struct lp_scene *scene, unsigned size) +{ + struct data_block_list *list = &scene->data; + + if (list->tail->used + size > DATA_BLOCK_SIZE) { + lp_bin_new_data_block( list ); + } + + { + struct data_block *tail = list->tail; + ubyte *data = tail->data + tail->used; + tail->used += size; + return data; + } +} + + +/** + * As above, but with specific alignment. + */ +static INLINE void * +lp_scene_alloc_aligned( struct lp_scene *scene, unsigned size, + unsigned alignment ) +{ + struct data_block_list *list = &scene->data; + + if (list->tail->used + size + alignment - 1 > DATA_BLOCK_SIZE) { + lp_bin_new_data_block( list ); + } + + { + struct data_block *tail = list->tail; + ubyte *data = tail->data + tail->used; + unsigned offset = (((uintptr_t)data + alignment - 1) & ~(alignment - 1)) - (uintptr_t)data; + tail->used += offset + size; + return data + offset; + } +} + + +/* Put back data if we decide not to use it, eg. culled triangles. + */ +static INLINE void +lp_scene_putback_data( struct lp_scene *scene, unsigned size) +{ + struct data_block_list *list = &scene->data; + assert(list->tail->used >= size); + list->tail->used -= size; +} + + +/** Return pointer to a particular tile's bin. */ +static INLINE struct cmd_bin * +lp_scene_get_bin(struct lp_scene *scene, unsigned x, unsigned y) +{ + return &scene->tile[x][y]; +} + + +/** Remove all commands from a bin */ +void +lp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y); + + +/* Add a command to bin[x][y]. + */ +static INLINE void +lp_scene_bin_command( struct lp_scene *scene, + unsigned x, unsigned y, + lp_rast_cmd cmd, + union lp_rast_cmd_arg arg ) +{ + struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); + struct cmd_block_list *list = &bin->commands; + + assert(x < scene->tiles_x); + assert(y < scene->tiles_y); + + if (list->tail->count == CMD_BLOCK_MAX) { + lp_bin_new_cmd_block( list ); + } + + { + struct cmd_block *tail = list->tail; + unsigned i = tail->count; + tail->cmd[i] = cmd; + tail->arg[i] = arg; + tail->count++; + } +} + + +/* Add a command to all active bins. + */ +static INLINE void +lp_scene_bin_everywhere( struct lp_scene *scene, + lp_rast_cmd cmd, + const union lp_rast_cmd_arg arg ) +{ + unsigned i, j; + for (i = 0; i < scene->tiles_x; i++) + for (j = 0; j < scene->tiles_y; j++) + lp_scene_bin_command( scene, i, j, cmd, arg ); +} + + +void +lp_scene_bin_state_command( struct lp_scene *scene, + lp_rast_cmd cmd, + const union lp_rast_cmd_arg arg ); + + +static INLINE unsigned +lp_scene_get_num_bins( const struct lp_scene *scene ) +{ + return scene->tiles_x * scene->tiles_y; +} + + +void +lp_scene_bin_iter_begin( struct lp_scene *scene ); + +struct cmd_bin * +lp_scene_bin_iter_next( struct lp_scene *scene, int *bin_x, int *bin_y ); + + +#endif /* LP_BIN_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_scene_queue.c b/src/gallium/drivers/llvmpipe/lp_scene_queue.c new file mode 100644 index 0000000000..43d74e4d89 --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_scene_queue.c @@ -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. + * + **************************************************************************/ + + +/** + * Scene queue. We'll use two queues. One contains "full" scenes which + * are produced by the "setup" code. The other contains "empty" scenes + * which are produced by the "rast" code when it finishes rendering a scene. + */ + +#include "util/u_ringbuffer.h" +#include "util/u_memory.h" +#include "lp_scene_queue.h" + + + +#define MAX_SCENE_QUEUE 4 + +struct scene_packet { + struct util_packet header; + struct lp_scene *scene; +}; + +/** + * A queue of scenes + */ +struct lp_scene_queue +{ + struct util_ringbuffer *ring; +}; + + + +/** Allocate a new scene queue */ +struct lp_scene_queue * +lp_scene_queue_create(void) +{ + struct lp_scene_queue *queue = CALLOC_STRUCT(lp_scene_queue); + if (queue == NULL) + return NULL; + + queue->ring = util_ringbuffer_create( MAX_SCENE_QUEUE * + sizeof( struct scene_packet ) / 4); + if (queue->ring == NULL) + goto fail; + + return queue; + +fail: + FREE(queue); + return NULL; +} + + +/** Delete a scene queue */ +void +lp_scene_queue_destroy(struct lp_scene_queue *queue) +{ + util_ringbuffer_destroy(queue->ring); + FREE(queue); +} + + +/** Remove first lp_scene from head of queue */ +struct lp_scene * +lp_scene_dequeue(struct lp_scene_queue *queue, boolean wait) +{ + struct scene_packet packet; + enum pipe_error ret; + + ret = util_ringbuffer_dequeue(queue->ring, + &packet.header, + sizeof packet / 4, + wait ); + if (ret != PIPE_OK) + return NULL; + + return packet.scene; +} + + +/** Add an lp_scene to tail of queue */ +void +lp_scene_enqueue(struct lp_scene_queue *queue, struct lp_scene *scene) +{ + struct scene_packet packet; + + packet.header.dwords = sizeof packet / 4; + packet.header.data24 = 0; + packet.scene = scene; + + util_ringbuffer_enqueue(queue->ring, &packet.header); +} + + + + + diff --git a/src/gallium/drivers/llvmpipe/lp_bld_misc.h b/src/gallium/drivers/llvmpipe/lp_scene_queue.h index 0e787e0b9c..fd7c65a2c8 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_misc.h +++ b/src/gallium/drivers/llvmpipe/lp_scene_queue.h @@ -26,31 +26,26 @@ **************************************************************************/ -#ifndef LP_BLD_MISC_H -#define LP_BLD_MISC_H +#ifndef LP_SCENE_QUEUE +#define LP_SCENE_QUEUE +struct lp_scene_queue; +struct lp_scene; -#include "llvm/Config/config.h" -#ifdef __cplusplus -extern "C" { -#endif - - -#ifndef LLVM_NATIVE_ARCH +struct lp_scene_queue * +lp_scene_queue_create(void); void -LLVMLinkInJIT(void); +lp_scene_queue_destroy(struct lp_scene_queue *queue); -int -LLVMInitializeNativeTarget(void); +struct lp_scene * +lp_scene_dequeue(struct lp_scene_queue *queue, boolean wait); -#endif /* !LLVM_NATIVE_ARCH */ +void +lp_scene_enqueue(struct lp_scene_queue *queue, struct lp_scene *scene); -#ifdef __cplusplus -} -#endif -#endif /* !LP_BLD_MISC_H */ +#endif /* LP_BIN_QUEUE */ diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index 9b47415f00..1cd3ea9a84 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -33,9 +33,11 @@ #include "lp_texture.h" #include "lp_buffer.h" +#include "lp_fence.h" #include "lp_winsys.h" #include "lp_jit.h" #include "lp_screen.h" +#include "lp_context.h" #include "lp_debug.h" #ifdef DEBUG @@ -51,6 +53,10 @@ static const struct debug_named_value lp_debug_flags[] = { { "query", DEBUG_QUERY }, { "screen", DEBUG_SCREEN }, { "jit", DEBUG_JIT }, + { "show_tiles", DEBUG_SHOW_TILES }, + { "show_subtiles", DEBUG_SHOW_SUBTILES }, + { "counters", DEBUG_COUNTERS }, + { "nopt", DEBUG_NO_LLVM_OPT }, {NULL, 0} }; #endif @@ -110,6 +116,16 @@ llvmpipe_get_param(struct pipe_screen *screen, int param) return 1; case PIPE_CAP_BLEND_EQUATION_SEPARATE: return 1; + case PIPE_CAP_INDEP_BLEND_ENABLE: + return 0; + case PIPE_CAP_INDEP_BLEND_FUNC: + return 0; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + return 0; default: return 0; } @@ -295,10 +311,12 @@ llvmpipe_create_screen(struct llvmpipe_winsys *winsys) screen->base.is_format_supported = llvmpipe_is_format_supported; screen->base.surface_buffer_create = llvmpipe_surface_buffer_create; + screen->base.context_create = llvmpipe_create_context; screen->base.flush_frontbuffer = llvmpipe_flush_frontbuffer; llvmpipe_init_screen_texture_funcs(&screen->base); llvmpipe_init_screen_buffer_funcs(&screen->base); + llvmpipe_init_screen_fence_funcs(&screen->base); lp_jit_screen_init(screen); diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index b18f17c0cd..3186069899 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -26,1479 +26,704 @@ **************************************************************************/ /** - * \brief Primitive rasterization/rendering (points, lines, triangles) + * Tiling engine. * - * \author Keith Whitwell <keith@tungstengraphics.com> - * \author Brian Paul + * Builds per-tile display lists and executes them on calls to + * lp_setup_flush(). */ -#include "lp_context.h" -#include "lp_quad.h" -#include "lp_setup.h" -#include "lp_state.h" -#include "draw/draw_context.h" -#include "draw/draw_private.h" -#include "draw/draw_vertex.h" -#include "pipe/p_shader_tokens.h" -#include "pipe/p_thread.h" -#include "util/u_format.h" -#include "util/u_math.h" +#include "pipe/p_defines.h" +#include "util/u_inlines.h" #include "util/u_memory.h" -#include "lp_bld_debug.h" -#include "lp_tile_cache.h" -#include "lp_tile_soa.h" - - -#define DEBUG_VERTS 0 -#define DEBUG_FRAGS 0 - -/** - * Triangle edge info - */ -struct edge { - float dx; /**< X(v1) - X(v0), used only during setup */ - float dy; /**< Y(v1) - Y(v0), used only during setup */ - float dxdy; /**< dx/dy */ - float sx, sy; /**< first sample point coord */ - int lines; /**< number of lines on this edge */ -}; - - -#define MAX_QUADS 16 - +#include "util/u_pack_color.h" +#include "util/u_surface.h" +#include "lp_scene.h" +#include "lp_scene_queue.h" +#include "lp_buffer.h" +#include "lp_texture.h" +#include "lp_debug.h" +#include "lp_fence.h" +#include "lp_rast.h" +#include "lp_setup_context.h" -/** - * Triangle setup info (derived from draw_stage). - * Also used for line drawing (taking some liberties). - */ -struct setup_context { - struct llvmpipe_context *llvmpipe; - - /* Vertices are just an array of floats making up each attribute in - * turn. Currently fixed at 4 floats, but should change in time. - * Codegen will help cope with this. - */ - const float (*vmax)[4]; - const float (*vmid)[4]; - const float (*vmin)[4]; - const float (*vprovoke)[4]; - - struct edge ebot; - struct edge etop; - struct edge emaj; - - float oneoverarea; - int facing; +#include "draw/draw_context.h" +#include "draw/draw_vbuf.h" - float pixel_offset; - struct quad_header quad[MAX_QUADS]; - struct quad_header *quad_ptrs[MAX_QUADS]; - unsigned count; +static void set_scene_state( struct setup_context *, unsigned ); - struct quad_interp_coef coef; - struct { - int left[2]; /**< [0] = row0, [1] = row1 */ - int right[2]; - int y; - } span; +struct lp_scene * +lp_setup_get_current_scene(struct setup_context *setup) +{ + if (!setup->scene) { -#if DEBUG_FRAGS - uint numFragsEmitted; /**< per primitive */ - uint numFragsWritten; /**< per primitive */ -#endif + /* wait for a free/empty scene + */ + setup->scene = lp_scene_dequeue(setup->empty_scenes, TRUE); - unsigned winding; /* which winding to cull */ -}; + if(0)lp_scene_reset( setup->scene ); /* XXX temporary? */ + lp_scene_set_framebuffer_size(setup->scene, + setup->fb.width, + setup->fb.height); + } + return setup->scene; +} -/** - * Execute fragment shader for the four fragments in the quad. - */ -ALIGN_STACK static void -shade_quads(struct llvmpipe_context *llvmpipe, - struct quad_header *quads[], - unsigned nr) +first_triangle( struct setup_context *setup, + const float (*v0)[4], + const float (*v1)[4], + const float (*v2)[4]) { - struct lp_fragment_shader *fs = llvmpipe->fs; - struct quad_header *quad = quads[0]; - const unsigned x = quad->input.x0; - const unsigned y = quad->input.y0; - uint8_t *tile; - uint8_t *color; - void *depth; - uint32_t ALIGN16_ATTRIB mask[4][NUM_CHANNELS]; - unsigned chan_index; - unsigned q; - - assert(fs->current); - if(!fs->current) - return; - - /* Sanity checks */ - assert(nr * QUAD_SIZE == TILE_VECTOR_HEIGHT * TILE_VECTOR_WIDTH); - assert(x % TILE_VECTOR_WIDTH == 0); - assert(y % TILE_VECTOR_HEIGHT == 0); - for (q = 0; q < nr; ++q) { - assert(quads[q]->input.x0 == x + q*2); - assert(quads[q]->input.y0 == y); - } - - /* mask */ - for (q = 0; q < 4; ++q) - for (chan_index = 0; chan_index < NUM_CHANNELS; ++chan_index) - mask[q][chan_index] = quads[q]->inout.mask & (1 << chan_index) ? ~0 : 0; + set_scene_state( setup, SETUP_ACTIVE ); + lp_setup_choose_triangle( setup ); + setup->triangle( setup, v0, v1, v2 ); +} - /* color buffer */ - if(llvmpipe->framebuffer.nr_cbufs >= 1 && - llvmpipe->framebuffer.cbufs[0]) { - tile = lp_get_cached_tile(llvmpipe->cbuf_cache[0], x, y); - color = &TILE_PIXEL(tile, x & (TILE_SIZE-1), y & (TILE_SIZE-1), 0); - } - else - color = NULL; - - /* depth buffer */ - if(llvmpipe->zsbuf_map) { - assert((x % 2) == 0); - assert((y % 2) == 0); - depth = llvmpipe->zsbuf_map + - y*llvmpipe->zsbuf_transfer->stride + - 2*x*util_format_get_blocksize(llvmpipe->zsbuf_transfer->texture->format); - } - else - depth = NULL; - - /* XXX: This will most likely fail on 32bit x86 without -mstackrealign */ - assert(lp_check_alignment(mask, 16)); - - assert(lp_check_alignment(depth, 16)); - assert(lp_check_alignment(color, 16)); - assert(lp_check_alignment(llvmpipe->jit_context.blend_color, 16)); - - /* run shader */ - fs->current->jit_function( &llvmpipe->jit_context, - x, y, - quad->coef->a0, - quad->coef->dadx, - quad->coef->dady, - &mask[0][0], - color, - depth); +static void +first_line( struct setup_context *setup, + const float (*v0)[4], + const float (*v1)[4]) +{ + set_scene_state( setup, SETUP_ACTIVE ); + lp_setup_choose_line( setup ); + setup->line( setup, v0, v1 ); } +static void +first_point( struct setup_context *setup, + const float (*v0)[4]) +{ + set_scene_state( setup, SETUP_ACTIVE ); + lp_setup_choose_point( setup ); + setup->point( setup, v0 ); +} +static void reset_context( struct setup_context *setup ) +{ + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); + /* Reset derived state */ + setup->constants.stored_size = 0; + setup->constants.stored_data = NULL; + setup->fs.stored = NULL; + setup->dirty = ~0; -/** - * Do triangle cull test using tri determinant (sign indicates orientation) - * \return true if triangle is to be culled. - */ -static INLINE boolean -cull_tri(const struct setup_context *setup, float det) -{ - if (det != 0) { - /* if (det < 0 then Z points toward camera and triangle is - * counter-clockwise winding. - */ - unsigned winding = (det < 0) ? PIPE_WINDING_CCW : PIPE_WINDING_CW; + /* no current bin */ + setup->scene = NULL; - if ((winding & setup->winding) == 0) - return FALSE; - } + /* Reset some state: + */ + setup->clear.flags = 0; - /* Culled: + /* Have an explicit "start-binning" call and get rid of this + * pointer twiddling? */ - return TRUE; + setup->line = first_line; + setup->point = first_point; + setup->triangle = first_triangle; } - -/** - * Clip setup->quad against the scissor/surface bounds. - */ -static INLINE void -quad_clip( struct setup_context *setup, struct quad_header *quad ) +/** Rasterize all scene's bins */ +static void +lp_setup_rasterize_scene( struct setup_context *setup, + boolean write_depth ) { - const struct pipe_scissor_state *cliprect = &setup->llvmpipe->cliprect; - const int minx = (int) cliprect->minx; - const int maxx = (int) cliprect->maxx; - const int miny = (int) cliprect->miny; - const int maxy = (int) cliprect->maxy; - - if (quad->input.x0 >= maxx || - quad->input.y0 >= maxy || - quad->input.x0 + 1 < minx || - quad->input.y0 + 1 < miny) { - /* totally clipped */ - quad->inout.mask = 0x0; - return; - } - if (quad->input.x0 < minx) - quad->inout.mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT); - if (quad->input.y0 < miny) - quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT); - if (quad->input.x0 == maxx - 1) - quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT); - if (quad->input.y0 == maxy - 1) - quad->inout.mask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT); -} + struct lp_scene *scene = lp_setup_get_current_scene(setup); + lp_rasterize_scene(setup->rast, + scene, + &setup->fb, + write_depth); + reset_context( setup ); -/** - * Given an X or Y coordinate, return the block/quad coordinate that it - * belongs to. - */ -static INLINE int block( int x ) -{ - return x & ~(2-1); + LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__); } -static INLINE int block_x( int x ) + + +static void +begin_binning( struct setup_context *setup ) { - return x & ~(TILE_VECTOR_WIDTH - 1); + struct lp_scene *scene = lp_setup_get_current_scene(setup); + + LP_DBG(DEBUG_SETUP, "%s color: %s depth: %s\n", __FUNCTION__, + (setup->clear.flags & PIPE_CLEAR_COLOR) ? "clear": "load", + (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) ? "clear": "load"); + + if (setup->fb.nr_cbufs) { + if (setup->clear.flags & PIPE_CLEAR_COLOR) + lp_scene_bin_everywhere( scene, + lp_rast_clear_color, + setup->clear.color ); + else + lp_scene_bin_everywhere( scene, + lp_rast_load_color, + lp_rast_arg_null() ); + } + + if (setup->fb.zsbuf) { + if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) + lp_scene_bin_everywhere( scene, + lp_rast_clear_zstencil, + setup->clear.zstencil ); + else + lp_scene_bin_everywhere( scene, + lp_rast_load_zstencil, + lp_rast_arg_null() ); + } + + LP_DBG(DEBUG_SETUP, "%s done\n", __FUNCTION__); } -/** - * Emit a quad (pass to next stage) with clipping. +/* This basically bins and then flushes any outstanding full-screen + * clears. + * + * TODO: fast path for fullscreen clears and no triangles. */ -static INLINE void -clip_emit_quad( struct setup_context *setup, struct quad_header *quad ) +static void +execute_clears( struct setup_context *setup ) { - quad_clip( setup, quad ); - - if (quad->inout.mask) { - struct llvmpipe_context *lp = setup->llvmpipe; - -#if 1 - /* XXX: The blender expects 4 quads. This is far from efficient, but - * until we codegenerate single-quad variants of the fragment pipeline - * we need this hack. */ - const unsigned nr_quads = TILE_VECTOR_HEIGHT*TILE_VECTOR_WIDTH/QUAD_SIZE; - struct quad_header quads[4]; - struct quad_header *quad_ptrs[4]; - int x0 = block_x(quad->input.x0); - unsigned i; - - assert(nr_quads == 4); - - for(i = 0; i < nr_quads; ++i) { - int x = x0 + 2*i; - if(x == quad->input.x0) - memcpy(&quads[i], quad, sizeof quads[i]); - else { - memset(&quads[i], 0, sizeof quads[i]); - quads[i].input.x0 = x; - quads[i].input.y0 = quad->input.y0; - quads[i].coef = quad->coef; - } - quad_ptrs[i] = &quads[i]; - } + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); - shade_quads( lp, quad_ptrs, nr_quads ); -#else - shade_quads( lp, &quad, 1 ); -#endif - } + begin_binning( setup ); + lp_setup_rasterize_scene( setup, TRUE ); } -/** - * Render a horizontal span of quads - */ -static void flush_spans( struct setup_context *setup ) +static void +set_scene_state( struct setup_context *setup, + unsigned new_state ) { - const int step = TILE_VECTOR_WIDTH; - const int xleft0 = setup->span.left[0]; - const int xleft1 = setup->span.left[1]; - const int xright0 = setup->span.right[0]; - const int xright1 = setup->span.right[1]; - - - int minleft = block_x(MIN2(xleft0, xleft1)); - int maxright = MAX2(xright0, xright1); - int x; - - for (x = minleft; x < maxright; x += step) { - unsigned skip_left0 = CLAMP(xleft0 - x, 0, step); - unsigned skip_left1 = CLAMP(xleft1 - x, 0, step); - unsigned skip_right0 = CLAMP(x + step - xright0, 0, step); - unsigned skip_right1 = CLAMP(x + step - xright1, 0, step); - unsigned lx = x; - const unsigned nr_quads = TILE_VECTOR_HEIGHT*TILE_VECTOR_WIDTH/QUAD_SIZE; - unsigned q = 0; - - unsigned skipmask_left0 = (1U << skip_left0) - 1U; - unsigned skipmask_left1 = (1U << skip_left1) - 1U; - - /* These calculations fail when step == 32 and skip_right == 0. - */ - unsigned skipmask_right0 = ~0U << (unsigned)(step - skip_right0); - unsigned skipmask_right1 = ~0U << (unsigned)(step - skip_right1); - - unsigned mask0 = ~skipmask_left0 & ~skipmask_right0; - unsigned mask1 = ~skipmask_left1 & ~skipmask_right1; - - if (mask0 | mask1) { - for(q = 0; q < nr_quads; ++q) { - unsigned quadmask = (mask0 & 3) | ((mask1 & 3) << 2); - setup->quad[q].input.x0 = lx; - setup->quad[q].input.y0 = setup->span.y; - setup->quad[q].inout.mask = quadmask; - setup->quad_ptrs[q] = &setup->quad[q]; - mask0 >>= 2; - mask1 >>= 2; - lx += 2; - } - assert(!(mask0 | mask1)); + unsigned old_state = setup->state; - shade_quads(setup->llvmpipe, setup->quad_ptrs, nr_quads ); + if (old_state == new_state) + return; + + LP_DBG(DEBUG_SETUP, "%s old %d new %d\n", __FUNCTION__, old_state, new_state); + + switch (new_state) { + case SETUP_ACTIVE: + begin_binning( setup ); + break; + + case SETUP_CLEARED: + if (old_state == SETUP_ACTIVE) { + assert(0); + return; } + break; + + case SETUP_FLUSHED: + if (old_state == SETUP_CLEARED) + execute_clears( setup ); + else + lp_setup_rasterize_scene( setup, TRUE ); + break; } - - setup->span.y = 0; - setup->span.right[0] = 0; - setup->span.right[1] = 0; - setup->span.left[0] = 1000000; /* greater than right[0] */ - setup->span.left[1] = 1000000; /* greater than right[1] */ + setup->state = new_state; } -#if DEBUG_VERTS -static void print_vertex(const struct setup_context *setup, - const float (*v)[4]) +void +lp_setup_flush( struct setup_context *setup, + unsigned flags ) { - int i; - debug_printf(" Vertex: (%p)\n", v); - for (i = 0; i < setup->quad[0].nr_attrs; i++) { - debug_printf(" %d: %f %f %f %f\n", i, - v[i][0], v[i][1], v[i][2], v[i][3]); - if (util_is_inf_or_nan(v[i][0])) { - debug_printf(" NaN!\n"); - } - } + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); + + set_scene_state( setup, SETUP_FLUSHED ); } -#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, - float det, - const float (*v0)[4], - const float (*v1)[4], - const float (*v2)[4] ) -{ - setup->vprovoke = v2; - - /* determine bottom to top order of vertices */ - { - float y0 = v0[0][1]; - float y1 = v1[0][1]; - float y2 = v2[0][1]; - if (y0 <= y1) { - if (y1 <= y2) { - /* y0<=y1<=y2 */ - setup->vmin = v0; - setup->vmid = v1; - setup->vmax = v2; - } - else if (y2 <= y0) { - /* y2<=y0<=y1 */ - setup->vmin = v2; - setup->vmid = v0; - setup->vmax = v1; - } - else { - /* y0<=y2<=y1 */ - setup->vmin = v0; - setup->vmid = v2; - setup->vmax = v1; - } - } - else { - if (y0 <= y2) { - /* y1<=y0<=y2 */ - setup->vmin = v1; - setup->vmid = v0; - setup->vmax = v2; - } - else if (y2 <= y1) { - /* y2<=y1<=y0 */ - setup->vmin = v2; - setup->vmid = v1; - setup->vmax = v0; - } - else { - /* y1<=y2<=y0 */ - setup->vmin = v1; - setup->vmid = v2; - setup->vmax = v0; - } - } - } - setup->ebot.dx = setup->vmid[0][0] - setup->vmin[0][0]; - setup->ebot.dy = setup->vmid[0][1] - setup->vmin[0][1]; - setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0]; - setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1]; - setup->etop.dx = setup->vmax[0][0] - setup->vmid[0][0]; - setup->etop.dy = setup->vmax[0][1] - setup->vmid[0][1]; - - /* - * Compute triangle's area. Use 1/area to compute partial - * derivatives of attributes later. - * - * The area will be the same as prim->det, but the sign may be - * different depending on how the vertices get sorted above. - * - * To determine whether the primitive is front or back facing we - * use the prim->det value because its sign is correct. - */ - { - const float area = (setup->emaj.dx * setup->ebot.dy - - setup->ebot.dx * setup->emaj.dy); - - setup->oneoverarea = 1.0f / area; - - /* - debug_printf("%s one-over-area %f area %f det %f\n", - __FUNCTION__, setup->oneoverarea, area, det ); - */ - if (util_is_inf_or_nan(setup->oneoverarea)) - return FALSE; - } +void +lp_setup_bind_framebuffer( struct setup_context *setup, + const struct pipe_framebuffer_state *fb ) +{ + struct lp_scene *scene = lp_setup_get_current_scene(setup); - /* We need to know if this is a front or back-facing triangle for: - * - the GLSL gl_FrontFacing fragment attribute (bool) - * - two-sided stencil test - */ - setup->facing = - ((det > 0.0) ^ - (setup->llvmpipe->rasterizer->front_winding == PIPE_WINDING_CW)); + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); - /* Prepare pixel offset for rasterisation: - * - pixel center (0.5, 0.5) for GL, or - * - assume (0.0, 0.0) for other APIs. - */ - if (setup->llvmpipe->rasterizer->gl_rasterization_rules) { - setup->pixel_offset = 0.5f; - } else { - setup->pixel_offset = 0.0f; - } + set_scene_state( setup, SETUP_FLUSHED ); - return TRUE; -} + /* re-get scene pointer, may have a new scene after flushing */ + scene = lp_setup_get_current_scene(setup); + util_copy_framebuffer_state(&setup->fb, fb); -/** - * Compute a0, dadx and dady for a linearly interpolated coefficient, - * for a triangle. - */ -static void tri_pos_coeff( struct setup_context *setup, - uint vertSlot, unsigned i) -{ - float botda = setup->vmid[vertSlot][i] - setup->vmin[vertSlot][i]; - float majda = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i]; - float a = setup->ebot.dy * majda - botda * setup->emaj.dy; - float b = setup->emaj.dx * botda - majda * setup->ebot.dx; - float dadx = a * setup->oneoverarea; - float dady = b * setup->oneoverarea; - - assert(i <= 3); - - setup->coef.dadx[0][i] = dadx; - setup->coef.dady[0][i] = dady; - - /* calculate a0 as the value which would be sampled for the - * fragment at (0,0), taking into account that we want to sample at - * pixel centers, in other words (pixel_offset, pixel_offset). - * - * this is neat but unfortunately not a good way to do things for - * triangles with very large values of dadx or dady as it will - * result in the subtraction and re-addition from a0 of a very - * large number, which means we'll end up loosing a lot of the - * fractional bits and precision from a0. the way to fix this is - * to define a0 as the sample at a pixel center somewhere near vmin - * instead - i'll switch to this later. - */ - setup->coef.a0[0][i] = (setup->vmin[vertSlot][i] - - (dadx * (setup->vmin[0][0] - setup->pixel_offset) + - dady * (setup->vmin[0][1] - setup->pixel_offset))); - - /* - debug_printf("attr[%d].%c: %f dx:%f dy:%f\n", - slot, "xyzw"[i], - setup->coef[slot].a0[i], - setup->coef[slot].dadx[i], - setup->coef[slot].dady[i]); - */ + lp_scene_set_framebuffer_size(scene, setup->fb.width, setup->fb.height); } -/** - * Compute a0 for a constant-valued coefficient (GL_FLAT shading). - * The value value comes from vertex[slot][i]. - * The result will be put into setup->coef[slot].a0[i]. - * \param slot which attribute slot - * \param i which component of the slot (0..3) - */ -static void const_pos_coeff( struct setup_context *setup, - uint vertSlot, unsigned i) +void +lp_setup_clear( struct setup_context *setup, + const float *color, + double depth, + unsigned stencil, + unsigned flags ) { - setup->coef.dadx[0][i] = 0; - setup->coef.dady[0][i] = 0; - - /* need provoking vertex info! - */ - setup->coef.a0[0][i] = setup->vprovoke[vertSlot][i]; -} + struct lp_scene *scene = lp_setup_get_current_scene(setup); + unsigned i; + LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); -/** - * Compute a0 for a constant-valued coefficient (GL_FLAT shading). - * The value value comes from vertex[slot][i]. - * The result will be put into setup->coef[slot].a0[i]. - * \param slot which attribute slot - * \param i which component of the slot (0..3) - */ -static void const_coeff( struct setup_context *setup, - unsigned attrib, - uint vertSlot) -{ - unsigned i; - for (i = 0; i < NUM_CHANNELS; ++i) { - setup->coef.dadx[1 + attrib][i] = 0; - setup->coef.dady[1 + attrib][i] = 0; - /* need provoking vertex info! - */ - setup->coef.a0[1 + attrib][i] = setup->vprovoke[vertSlot][i]; + if (flags & PIPE_CLEAR_COLOR) { + for (i = 0; i < 4; ++i) + setup->clear.color.clear_color[i] = float_to_ubyte(color[i]); } -} - -/** - * Compute a0, dadx and dady for a linearly interpolated coefficient, - * for a triangle. - */ -static void tri_linear_coeff( struct setup_context *setup, - unsigned attrib, - uint vertSlot) -{ - unsigned i; - for (i = 0; i < NUM_CHANNELS; ++i) { - float botda = setup->vmid[vertSlot][i] - setup->vmin[vertSlot][i]; - float majda = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i]; - float a = setup->ebot.dy * majda - botda * setup->emaj.dy; - float b = setup->emaj.dx * botda - majda * setup->ebot.dx; - float dadx = a * setup->oneoverarea; - float dady = b * setup->oneoverarea; - - assert(i <= 3); - - setup->coef.dadx[1 + attrib][i] = dadx; - setup->coef.dady[1 + attrib][i] = dady; - - /* calculate a0 as the value which would be sampled for the - * fragment at (0,0), taking into account that we want to sample at - * pixel centers, in other words (0.5, 0.5). - * - * this is neat but unfortunately not a good way to do things for - * triangles with very large values of dadx or dady as it will - * result in the subtraction and re-addition from a0 of a very - * large number, which means we'll end up loosing a lot of the - * fractional bits and precision from a0. the way to fix this is - * to define a0 as the sample at a pixel center somewhere near vmin - * instead - i'll switch to this later. - */ - setup->coef.a0[1 + attrib][i] = (setup->vmin[vertSlot][i] - - (dadx * (setup->vmin[0][0] - setup->pixel_offset) + - dady * (setup->vmin[0][1] - setup->pixel_offset))); - - /* - debug_printf("attr[%d].%c: %f dx:%f dy:%f\n", - slot, "xyzw"[i], - setup->coef[slot].a0[i], - setup->coef[slot].dadx[i], - setup->coef[slot].dady[i]); - */ + if (flags & PIPE_CLEAR_DEPTHSTENCIL) { + setup->clear.zstencil.clear_zstencil = + util_pack_z_stencil(setup->fb.zsbuf->format, + depth, + stencil); } -} + if (setup->state == SETUP_ACTIVE) { + /* Add the clear to existing scene. In the unusual case where + * both color and depth-stencil are being cleared when there's + * already been some rendering, we could discard the currently + * binned scene and start again, but I don't see that as being + * a common usage. + */ + if (flags & PIPE_CLEAR_COLOR) + lp_scene_bin_everywhere( scene, + lp_rast_clear_color, + setup->clear.color ); -/** - * Compute a0, dadx and dady for a perspective-corrected interpolant, - * for a triangle. - * We basically multiply the vertex value by 1/w before computing - * the plane coefficients (a0, dadx, dady). - * Later, when we compute the value at a particular fragment position we'll - * divide the interpolated value by the interpolated W at that fragment. - */ -static void tri_persp_coeff( struct setup_context *setup, - unsigned attrib, - uint vertSlot) -{ - unsigned i; - for (i = 0; i < NUM_CHANNELS; ++i) { - /* premultiply by 1/w (v[0][3] is always W): + if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) + lp_scene_bin_everywhere( scene, + lp_rast_clear_zstencil, + setup->clear.zstencil ); + } + else { + /* Put ourselves into the 'pre-clear' state, specifically to try + * and accumulate multiple clears to color and depth_stencil + * buffers which the app or state-tracker might issue + * separately. */ - float mina = setup->vmin[vertSlot][i] * setup->vmin[0][3]; - float mida = setup->vmid[vertSlot][i] * setup->vmid[0][3]; - float maxa = setup->vmax[vertSlot][i] * setup->vmax[0][3]; - float botda = mida - mina; - float majda = maxa - mina; - float a = setup->ebot.dy * majda - botda * setup->emaj.dy; - float b = setup->emaj.dx * botda - majda * setup->ebot.dx; - float dadx = a * setup->oneoverarea; - float dady = b * setup->oneoverarea; - - /* - debug_printf("tri persp %d,%d: %f %f %f\n", vertSlot, i, - setup->vmin[vertSlot][i], - setup->vmid[vertSlot][i], - setup->vmax[vertSlot][i] - ); - */ - assert(i <= 3); - - setup->coef.dadx[1 + attrib][i] = dadx; - setup->coef.dady[1 + attrib][i] = dady; - setup->coef.a0[1 + attrib][i] = (mina - - (dadx * (setup->vmin[0][0] - setup->pixel_offset) + - dady * (setup->vmin[0][1] - setup->pixel_offset))); + set_scene_state( setup, SETUP_CLEARED ); + + setup->clear.flags |= flags; } } /** - * Special coefficient setup for gl_FragCoord. - * X and Y are trivial, though Y has to be inverted for OpenGL. - * Z and W are copied from posCoef which should have already been computed. - * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask. + * Emit a fence. */ -static void -setup_fragcoord_coeff(struct setup_context *setup, uint slot) +struct pipe_fence_handle * +lp_setup_fence( struct setup_context *setup ) { - /*X*/ - setup->coef.a0[1 + slot][0] = 0; - setup->coef.dadx[1 + slot][0] = 1.0; - setup->coef.dady[1 + slot][0] = 0.0; - /*Y*/ - setup->coef.a0[1 + slot][1] = 0.0; - setup->coef.dadx[1 + slot][1] = 0.0; - setup->coef.dady[1 + slot][1] = 1.0; - /*Z*/ - setup->coef.a0[1 + slot][2] = setup->coef.a0[0][2]; - setup->coef.dadx[1 + slot][2] = setup->coef.dadx[0][2]; - setup->coef.dady[1 + slot][2] = setup->coef.dady[0][2]; - /*W*/ - setup->coef.a0[1 + slot][3] = setup->coef.a0[0][3]; - setup->coef.dadx[1 + slot][3] = setup->coef.dadx[0][3]; - setup->coef.dady[1 + slot][3] = setup->coef.dady[0][3]; -} + struct lp_scene *scene = lp_setup_get_current_scene(setup); + const unsigned rank = lp_scene_get_num_bins( scene ); /* xxx */ + struct lp_fence *fence = lp_fence_create(rank); + LP_DBG(DEBUG_SETUP, "%s rank %u\n", __FUNCTION__, rank); + set_scene_state( setup, SETUP_ACTIVE ); -/** - * Compute the setup->coef[] array dadx, dady, a0 values. - * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized. - */ -static void setup_tri_coefficients( struct setup_context *setup ) -{ - struct llvmpipe_context *llvmpipe = setup->llvmpipe; - const struct lp_fragment_shader *lpfs = llvmpipe->fs; - const struct vertex_info *vinfo = llvmpipe_get_vertex_info(llvmpipe); - uint fragSlot; + /* insert the fence into all command bins */ + lp_scene_bin_everywhere( scene, + lp_rast_fence, + lp_rast_arg_fence(fence) ); - /* z and w are done by linear interpolation: - */ - tri_pos_coeff(setup, 0, 2); - tri_pos_coeff(setup, 0, 3); + return (struct pipe_fence_handle *) fence; +} - /* setup interpolation for all the remaining attributes: - */ - for (fragSlot = 0; fragSlot < lpfs->info.num_inputs; fragSlot++) { - const uint vertSlot = vinfo->attrib[fragSlot].src_index; - switch (vinfo->attrib[fragSlot].interp_mode) { - case INTERP_CONSTANT: - const_coeff(setup, fragSlot, vertSlot); - break; - case INTERP_LINEAR: - tri_linear_coeff(setup, fragSlot, vertSlot); - break; - case INTERP_PERSPECTIVE: - tri_persp_coeff(setup, fragSlot, vertSlot); - break; - case INTERP_POS: - setup_fragcoord_coeff(setup, fragSlot); - break; - default: - assert(0); - } +void +lp_setup_set_triangle_state( struct setup_context *setup, + unsigned cull_mode, + boolean ccw_is_frontface, + boolean scissor ) +{ + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); - if (lpfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) { - setup->coef.a0[1 + fragSlot][0] = 1.0f - setup->facing; - setup->coef.dadx[1 + fragSlot][0] = 0.0; - setup->coef.dady[1 + fragSlot][0] = 0.0; - } - } + setup->ccw_is_frontface = ccw_is_frontface; + setup->cullmode = cull_mode; + setup->triangle = first_triangle; + setup->scissor_test = scissor; } -static void setup_tri_edges( struct setup_context *setup ) +void +lp_setup_set_fs_inputs( struct setup_context *setup, + const struct lp_shader_input *input, + unsigned nr ) { - float vmin_x = setup->vmin[0][0] + setup->pixel_offset; - float vmid_x = setup->vmid[0][0] + setup->pixel_offset; - - float vmin_y = setup->vmin[0][1] - setup->pixel_offset; - float vmid_y = setup->vmid[0][1] - setup->pixel_offset; - float vmax_y = setup->vmax[0][1] - setup->pixel_offset; - - setup->emaj.sy = ceilf(vmin_y); - setup->emaj.lines = (int) ceilf(vmax_y - setup->emaj.sy); - setup->emaj.dxdy = setup->emaj.dx / setup->emaj.dy; - setup->emaj.sx = vmin_x + (setup->emaj.sy - vmin_y) * setup->emaj.dxdy; - - setup->etop.sy = ceilf(vmid_y); - setup->etop.lines = (int) ceilf(vmax_y - setup->etop.sy); - setup->etop.dxdy = setup->etop.dx / setup->etop.dy; - setup->etop.sx = vmid_x + (setup->etop.sy - vmid_y) * setup->etop.dxdy; - - setup->ebot.sy = ceilf(vmin_y); - setup->ebot.lines = (int) ceilf(vmid_y - setup->ebot.sy); - setup->ebot.dxdy = setup->ebot.dx / setup->ebot.dy; - setup->ebot.sx = vmin_x + (setup->ebot.sy - vmin_y) * setup->ebot.dxdy; -} + LP_DBG(DEBUG_SETUP, "%s %p %u\n", __FUNCTION__, (void *) input, nr); + memcpy( setup->fs.input, input, nr * sizeof input[0] ); + setup->fs.nr_inputs = nr; +} -/** - * Render the upper or lower half of a triangle. - * Scissoring/cliprect is applied here too. - */ -static void subtriangle( struct setup_context *setup, - struct edge *eleft, - struct edge *eright, - unsigned lines ) +void +lp_setup_set_fs_functions( struct setup_context *setup, + lp_jit_frag_func jit_function0, + lp_jit_frag_func jit_function1, + boolean opaque ) { - const struct pipe_scissor_state *cliprect = &setup->llvmpipe->cliprect; - const int minx = (int) cliprect->minx; - const int maxx = (int) cliprect->maxx; - const int miny = (int) cliprect->miny; - const int maxy = (int) cliprect->maxy; - int y, start_y, finish_y; - int sy = (int)eleft->sy; - - assert((int)eleft->sy == (int) eright->sy); - - /* clip top/bottom */ - start_y = sy; - if (start_y < miny) - start_y = miny; - - finish_y = sy + lines; - if (finish_y > maxy) - finish_y = maxy; - - start_y -= sy; - finish_y -= sy; - - /* - debug_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y); - */ - - for (y = start_y; y < finish_y; y++) { - - /* avoid accumulating adds as floats don't have the precision to - * accurately iterate large triangle edges that way. luckily we - * can just multiply these days. - * - * this is all drowned out by the attribute interpolation anyway. - */ - int left = (int)(eleft->sx + y * eleft->dxdy); - int right = (int)(eright->sx + y * eright->dxdy); - - /* clip left/right */ - if (left < minx) - left = minx; - if (right > maxx) - right = maxx; - - if (left < right) { - int _y = sy + y; - if (block(_y) != setup->span.y) { - flush_spans(setup); - setup->span.y = block(_y); - } + LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) jit_function0); + /* FIXME: reference count */ - setup->span.left[_y&1] = left; - setup->span.right[_y&1] = right; - } - } - - - /* save the values so that emaj can be restarted: - */ - eleft->sx += lines * eleft->dxdy; - eright->sx += lines * eright->dxdy; - eleft->sy += lines; - eright->sy += lines; + setup->fs.current.jit_function[0] = jit_function0; + setup->fs.current.jit_function[1] = jit_function1; + setup->fs.current.opaque = opaque; + setup->dirty |= LP_SETUP_NEW_FS; } - -/** - * Recalculate prim's determinant. This is needed as we don't have - * get this information through the vbuf_render interface & we must - * calculate it here. - */ -static float -calc_det( const float (*v0)[4], - const float (*v1)[4], - const float (*v2)[4] ) +void +lp_setup_set_fs_constants(struct setup_context *setup, + struct pipe_buffer *buffer) { - /* edge vectors e = v0 - v2, f = v1 - v2 */ - const float ex = v0[0][0] - v2[0][0]; - const float ey = v0[0][1] - v2[0][1]; - const float fx = v1[0][0] - v2[0][0]; - const float fy = v1[0][1] - v2[0][1]; - - /* det = cross(e,f).z */ - return ex * fy - ey * fx; + LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffer); + + pipe_buffer_reference(&setup->constants.current, buffer); + + setup->dirty |= LP_SETUP_NEW_CONSTANTS; } -/** - * Do setup for triangle rasterization, then render the triangle. - */ -void llvmpipe_setup_tri( struct setup_context *setup, - const float (*v0)[4], - const float (*v1)[4], - const float (*v2)[4] ) +void +lp_setup_set_alpha_ref_value( struct setup_context *setup, + float alpha_ref_value ) { - float det; - -#if DEBUG_VERTS - debug_printf("Setup triangle:\n"); - print_vertex(setup, v0); - print_vertex(setup, v1); - print_vertex(setup, v2); -#endif + LP_DBG(DEBUG_SETUP, "%s %f\n", __FUNCTION__, alpha_ref_value); - if (setup->llvmpipe->no_rast) - return; - - det = calc_det(v0, v1, v2); - /* - debug_printf("%s\n", __FUNCTION__ ); - */ + if(setup->fs.current.jit_context.alpha_ref_value != alpha_ref_value) { + setup->fs.current.jit_context.alpha_ref_value = alpha_ref_value; + setup->dirty |= LP_SETUP_NEW_FS; + } +} -#if DEBUG_FRAGS - setup->numFragsEmitted = 0; - setup->numFragsWritten = 0; -#endif +void +lp_setup_set_blend_color( struct setup_context *setup, + const struct pipe_blend_color *blend_color ) +{ + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); - if (cull_tri( setup, det )) - return; + assert(blend_color); - if (!setup_sort_vertices( setup, det, v0, v1, v2 )) - return; - setup_tri_coefficients( setup ); - setup_tri_edges( setup ); + if(memcmp(&setup->blend_color.current, blend_color, sizeof *blend_color) != 0) { + memcpy(&setup->blend_color.current, blend_color, sizeof *blend_color); + setup->dirty |= LP_SETUP_NEW_BLEND_COLOR; + } +} - assert(setup->llvmpipe->reduced_prim == PIPE_PRIM_TRIANGLES); - setup->span.y = 0; - setup->span.right[0] = 0; - setup->span.right[1] = 0; - /* setup->span.z_mode = tri_z_mode( setup->ctx ); */ +void +lp_setup_set_scissor( struct setup_context *setup, + const struct pipe_scissor_state *scissor ) +{ + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); - /* init_constant_attribs( setup ); */ + assert(scissor); - if (setup->oneoverarea < 0.0) { - /* emaj on left: - */ - subtriangle( setup, &setup->emaj, &setup->ebot, setup->ebot.lines ); - subtriangle( setup, &setup->emaj, &setup->etop, setup->etop.lines ); - } - else { - /* emaj on right: - */ - subtriangle( setup, &setup->ebot, &setup->emaj, setup->ebot.lines ); - subtriangle( setup, &setup->etop, &setup->emaj, setup->etop.lines ); + if (memcmp(&setup->scissor.current, scissor, sizeof(*scissor)) != 0) { + setup->scissor.current = *scissor; /* struct copy */ + setup->dirty |= LP_SETUP_NEW_SCISSOR; } - - flush_spans( setup ); - -#if DEBUG_FRAGS - printf("Tri: %u frags emitted, %u written\n", - setup->numFragsEmitted, - setup->numFragsWritten); -#endif } - -/** - * Compute a0, dadx and dady for a linearly interpolated coefficient, - * for a line. - */ -static void -linear_pos_coeff(struct setup_context *setup, - uint vertSlot, uint i) +void +lp_setup_set_flatshade_first( struct setup_context *setup, + boolean flatshade_first ) { - const float da = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i]; - const float dadx = da * setup->emaj.dx * setup->oneoverarea; - const float dady = da * setup->emaj.dy * setup->oneoverarea; - setup->coef.dadx[0][i] = dadx; - setup->coef.dady[0][i] = dady; - setup->coef.a0[0][i] = (setup->vmin[vertSlot][i] - - (dadx * (setup->vmin[0][0] - setup->pixel_offset) + - dady * (setup->vmin[0][1] - setup->pixel_offset))); + setup->flatshade_first = flatshade_first; } -/** - * Compute a0, dadx and dady for a linearly interpolated coefficient, - * for a line. - */ -static void -line_linear_coeff(struct setup_context *setup, - unsigned attrib, - uint vertSlot) +void +lp_setup_set_vertex_info( struct setup_context *setup, + struct vertex_info *vertex_info ) { - unsigned i; - for (i = 0; i < NUM_CHANNELS; ++i) { - const float da = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i]; - const float dadx = da * setup->emaj.dx * setup->oneoverarea; - const float dady = da * setup->emaj.dy * setup->oneoverarea; - setup->coef.dadx[1 + attrib][i] = dadx; - setup->coef.dady[1 + attrib][i] = dady; - setup->coef.a0[1 + attrib][i] = (setup->vmin[vertSlot][i] - - (dadx * (setup->vmin[0][0] - setup->pixel_offset) + - dady * (setup->vmin[0][1] - setup->pixel_offset))); - } + /* XXX: just silently holding onto the pointer: + */ + setup->vertex_info = vertex_info; } /** - * Compute a0, dadx and dady for a perspective-corrected interpolant, - * for a line. + * Called during state validation when LP_NEW_TEXTURE is set. */ -static void -line_persp_coeff(struct setup_context *setup, - unsigned attrib, - uint vertSlot) +void +lp_setup_set_sampler_textures( struct setup_context *setup, + unsigned num, struct pipe_texture **texture) { unsigned i; - for (i = 0; i < NUM_CHANNELS; ++i) { - /* XXX double-check/verify this arithmetic */ - const float a0 = setup->vmin[vertSlot][i] * setup->vmin[0][3]; - const float a1 = setup->vmax[vertSlot][i] * setup->vmax[0][3]; - const float da = a1 - a0; - const float dadx = da * setup->emaj.dx * setup->oneoverarea; - const float dady = da * setup->emaj.dy * setup->oneoverarea; - setup->coef.dadx[1 + attrib][i] = dadx; - setup->coef.dady[1 + attrib][i] = dady; - setup->coef.a0[1 + attrib][i] = (setup->vmin[vertSlot][i] - - (dadx * (setup->vmin[0][0] - setup->pixel_offset) + - dady * (setup->vmin[0][1] - setup->pixel_offset))); + + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); + + assert(num <= PIPE_MAX_SAMPLERS); + + for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { + struct pipe_texture *tex = i < num ? texture[i] : NULL; + + if(tex) { + struct llvmpipe_texture *lp_tex = llvmpipe_texture(tex); + struct lp_jit_texture *jit_tex; + jit_tex = &setup->fs.current.jit_context.textures[i]; + jit_tex->width = tex->width0; + jit_tex->height = tex->height0; + jit_tex->stride = lp_tex->stride[0]; + if(!lp_tex->dt) + jit_tex->data = lp_tex->data; + else + /* FIXME: map the rendertarget */ + assert(0); + + /* the scene references this texture */ + { + struct lp_scene *scene = lp_setup_get_current_scene(setup); + lp_scene_texture_reference(scene, tex); + } + } } + + setup->dirty |= LP_SETUP_NEW_FS; } /** - * Compute the setup->coef[] array dadx, dady, a0 values. - * Must be called after setup->vmin,vmax are initialized. + * Is the given texture referenced by any scene? + * Note: we have to check all scenes including any scenes currently + * being rendered and the current scene being built. */ -static INLINE boolean -setup_line_coefficients(struct setup_context *setup, - const float (*v0)[4], - const float (*v1)[4]) +unsigned +lp_setup_is_texture_referenced( const struct setup_context *setup, + const struct pipe_texture *texture ) { - struct llvmpipe_context *llvmpipe = setup->llvmpipe; - const struct lp_fragment_shader *lpfs = llvmpipe->fs; - const struct vertex_info *vinfo = llvmpipe_get_vertex_info(llvmpipe); - uint fragSlot; - float area; - - /* use setup->vmin, vmax to point to vertices */ - if (llvmpipe->rasterizer->flatshade_first) - setup->vprovoke = v0; - else - setup->vprovoke = v1; - setup->vmin = v0; - setup->vmax = v1; - - setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0]; - setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1]; - - /* NOTE: this is not really area but something proportional to it */ - area = setup->emaj.dx * setup->emaj.dx + setup->emaj.dy * setup->emaj.dy; - if (area == 0.0f || util_is_inf_or_nan(area)) - return FALSE; - setup->oneoverarea = 1.0f / area; - - /* z and w are done by linear interpolation: - */ - linear_pos_coeff(setup, 0, 2); - linear_pos_coeff(setup, 0, 3); - - /* setup interpolation for all the remaining attributes: - */ - for (fragSlot = 0; fragSlot < lpfs->info.num_inputs; fragSlot++) { - const uint vertSlot = vinfo->attrib[fragSlot].src_index; - - switch (vinfo->attrib[fragSlot].interp_mode) { - case INTERP_CONSTANT: - const_coeff(setup, fragSlot, vertSlot); - break; - case INTERP_LINEAR: - line_linear_coeff(setup, fragSlot, vertSlot); - break; - case INTERP_PERSPECTIVE: - line_persp_coeff(setup, fragSlot, vertSlot); - break; - case INTERP_POS: - setup_fragcoord_coeff(setup, fragSlot); - break; - default: - assert(0); - } + unsigned i; - if (lpfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) { - setup->coef.a0[1 + fragSlot][0] = 1.0f - setup->facing; - setup->coef.dadx[1 + fragSlot][0] = 0.0; - setup->coef.dady[1 + fragSlot][0] = 0.0; - } + /* check the render targets */ + for (i = 0; i < setup->fb.nr_cbufs; i++) { + if (setup->fb.cbufs[i]->texture == texture) + return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; + } + if (setup->fb.zsbuf && setup->fb.zsbuf->texture == texture) { + return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; } - return TRUE; -} - -/** - * Plot a pixel in a line segment. - */ -static INLINE void -plot(struct setup_context *setup, int x, int y) -{ - const int iy = y & 1; - const int ix = x & 1; - const int quadX = x - ix; - const int quadY = y - iy; - const int mask = (1 << ix) << (2 * iy); - - if (quadX != setup->quad[0].input.x0 || - quadY != setup->quad[0].input.y0) - { - /* flush prev quad, start new quad */ - - if (setup->quad[0].input.x0 != -1) - clip_emit_quad( setup, &setup->quad[0] ); - - setup->quad[0].input.x0 = quadX; - setup->quad[0].input.y0 = quadY; - setup->quad[0].inout.mask = 0x0; + /* check textures referenced by the scene */ + for (i = 0; i < Elements(setup->scenes); i++) { + if (lp_scene_is_texture_referenced(setup->scenes[i], texture)) { + return PIPE_REFERENCED_FOR_READ; + } } - setup->quad[0].inout.mask |= mask; + return PIPE_UNREFERENCED; } /** - * Do setup for line rasterization, then render the line. - * Single-pixel width, no stipple, etc. We rely on the 'draw' module - * to handle stippling and wide lines. + * Called by vbuf code when we're about to draw something. */ void -llvmpipe_setup_line(struct setup_context *setup, - const float (*v0)[4], - const float (*v1)[4]) +lp_setup_update_state( struct setup_context *setup ) { - int x0 = (int) v0[0][0]; - int x1 = (int) v1[0][0]; - int y0 = (int) v0[0][1]; - int y1 = (int) v1[0][1]; - int dx = x1 - x0; - int dy = y1 - y0; - int xstep, ystep; - -#if DEBUG_VERTS - debug_printf("Setup line:\n"); - print_vertex(setup, v0); - print_vertex(setup, v1); -#endif - - if (setup->llvmpipe->no_rast) - return; - - if (dx == 0 && dy == 0) - return; + struct lp_scene *scene = lp_setup_get_current_scene(setup); - if (!setup_line_coefficients(setup, v0, v1)) - return; - - assert(v0[0][0] < 1.0e9); - assert(v0[0][1] < 1.0e9); - assert(v1[0][0] < 1.0e9); - assert(v1[0][1] < 1.0e9); - - if (dx < 0) { - dx = -dx; /* make positive */ - xstep = -1; - } - else { - xstep = 1; - } + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); - if (dy < 0) { - dy = -dy; /* make positive */ - ystep = -1; - } - else { - ystep = 1; - } + assert(setup->fs.current.jit_function); - assert(dx >= 0); - assert(dy >= 0); - assert(setup->llvmpipe->reduced_prim == PIPE_PRIM_LINES); + if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) { + uint8_t *stored; + unsigned i, j; - setup->quad[0].input.x0 = setup->quad[0].input.y0 = -1; - setup->quad[0].inout.mask = 0x0; + stored = lp_scene_alloc_aligned(scene, 4 * 16, 16); - /* XXX temporary: set coverage to 1.0 so the line appears - * if AA mode happens to be enabled. - */ - setup->quad[0].input.coverage[0] = - setup->quad[0].input.coverage[1] = - setup->quad[0].input.coverage[2] = - setup->quad[0].input.coverage[3] = 1.0; - - if (dx > dy) { - /*** X-major line ***/ - int i; - const int errorInc = dy + dy; - int error = errorInc - dx; - const int errorDec = error - dx; - - for (i = 0; i < dx; i++) { - plot(setup, x0, y0); - - x0 += xstep; - if (error < 0) { - error += errorInc; - } - else { - error += errorDec; - y0 += ystep; - } - } - } - else { - /*** Y-major line ***/ - int i; - const int errorInc = dx + dx; - int error = errorInc - dy; - const int errorDec = error - dy; - - for (i = 0; i < dy; i++) { - plot(setup, x0, y0); - - y0 += ystep; - if (error < 0) { - error += errorInc; - } - else { - error += errorDec; - x0 += xstep; - } + /* smear each blend color component across 16 ubyte elements */ + for (i = 0; i < 4; ++i) { + uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]); + for (j = 0; j < 16; ++j) + stored[i*16 + j] = c; } - } - /* draw final quad */ - if (setup->quad[0].inout.mask) { - clip_emit_quad( setup, &setup->quad[0] ); + setup->blend_color.stored = stored; + + setup->fs.current.jit_context.blend_color = setup->blend_color.stored; + setup->dirty |= LP_SETUP_NEW_FS; } -} + if (setup->dirty & LP_SETUP_NEW_SCISSOR) { + float *stored; -static void -point_persp_coeff(struct setup_context *setup, - const float (*vert)[4], - unsigned attrib, - uint vertSlot) -{ - unsigned i; - for(i = 0; i < NUM_CHANNELS; ++i) { - setup->coef.dadx[1 + attrib][i] = 0.0F; - setup->coef.dady[1 + attrib][i] = 0.0F; - setup->coef.a0[1 + attrib][i] = vert[vertSlot][i] * vert[0][3]; - } -} + stored = lp_scene_alloc_aligned(scene, 4 * sizeof(int32_t), 16); + stored[0] = (float) setup->scissor.current.minx; + stored[1] = (float) setup->scissor.current.miny; + stored[2] = (float) setup->scissor.current.maxx; + stored[3] = (float) setup->scissor.current.maxy; -/** - * Do setup for point rasterization, then render the point. - * Round or square points... - * XXX could optimize a lot for 1-pixel points. - */ -void -llvmpipe_setup_point( struct setup_context *setup, - const float (*v0)[4] ) -{ - struct llvmpipe_context *llvmpipe = setup->llvmpipe; - const struct lp_fragment_shader *lpfs = llvmpipe->fs; - const int sizeAttr = setup->llvmpipe->psize_slot; - const float size - = sizeAttr > 0 ? v0[sizeAttr][0] - : setup->llvmpipe->rasterizer->point_size; - const float halfSize = 0.5F * size; - const boolean round = (boolean) setup->llvmpipe->rasterizer->point_smooth; - const float x = v0[0][0]; /* Note: data[0] is always position */ - const float y = v0[0][1]; - const struct vertex_info *vinfo = llvmpipe_get_vertex_info(llvmpipe); - uint fragSlot; - -#if DEBUG_VERTS - debug_printf("Setup point:\n"); - print_vertex(setup, v0); -#endif - - if (llvmpipe->no_rast) - return; + setup->scissor.stored = stored; - assert(setup->llvmpipe->reduced_prim == PIPE_PRIM_POINTS); - - /* For points, all interpolants are constant-valued. - * However, for point sprites, we'll need to setup texcoords appropriately. - * XXX: which coefficients are the texcoords??? - * We may do point sprites as textured quads... - * - * KW: We don't know which coefficients are texcoords - ultimately - * the choice of what interpolation mode to use for each attribute - * should be determined by the fragment program, using - * per-attribute declaration statements that include interpolation - * mode as a parameter. So either the fragment program will have - * to be adjusted for pointsprite vs normal point behaviour, or - * otherwise a special interpolation mode will have to be defined - * which matches the required behaviour for point sprites. But - - * the latter is not a feature of normal hardware, and as such - * probably should be ruled out on that basis. - */ - setup->vprovoke = v0; + setup->fs.current.jit_context.scissor_xmin = stored[0]; + setup->fs.current.jit_context.scissor_ymin = stored[1]; + setup->fs.current.jit_context.scissor_xmax = stored[2]; + setup->fs.current.jit_context.scissor_ymax = stored[3]; - /* setup Z, W */ - const_pos_coeff(setup, 0, 2); - const_pos_coeff(setup, 0, 3); + setup->dirty |= LP_SETUP_NEW_FS; + } - for (fragSlot = 0; fragSlot < lpfs->info.num_inputs; fragSlot++) { - const uint vertSlot = vinfo->attrib[fragSlot].src_index; + if(setup->dirty & LP_SETUP_NEW_CONSTANTS) { + struct pipe_buffer *buffer = setup->constants.current; - switch (vinfo->attrib[fragSlot].interp_mode) { - case INTERP_CONSTANT: - /* fall-through */ - case INTERP_LINEAR: - const_coeff(setup, fragSlot, vertSlot); - break; - case INTERP_PERSPECTIVE: - point_persp_coeff(setup, setup->vprovoke, fragSlot, vertSlot); - break; - case INTERP_POS: - setup_fragcoord_coeff(setup, fragSlot); - break; - default: - assert(0); - } + if(buffer) { + unsigned current_size = buffer->size; + const void *current_data = llvmpipe_buffer(buffer)->data; - if (lpfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) { - setup->coef.a0[1 + fragSlot][0] = 1.0f - setup->facing; - setup->coef.dadx[1 + fragSlot][0] = 0.0; - setup->coef.dady[1 + fragSlot][0] = 0.0; - } - } + /* TODO: copy only the actually used constants? */ + if(setup->constants.stored_size != current_size || + !setup->constants.stored_data || + memcmp(setup->constants.stored_data, + current_data, + current_size) != 0) { + void *stored; - if (halfSize <= 0.5 && !round) { - /* special case for 1-pixel points */ - const int ix = ((int) x) & 1; - const int iy = ((int) y) & 1; - setup->quad[0].input.x0 = (int) x - ix; - setup->quad[0].input.y0 = (int) y - iy; - setup->quad[0].inout.mask = (1 << ix) << (2 * iy); - clip_emit_quad( setup, &setup->quad[0] ); - } - else { - if (round) { - /* rounded points */ - const int ixmin = block((int) (x - halfSize)); - const int ixmax = block((int) (x + halfSize)); - const int iymin = block((int) (y - halfSize)); - const int iymax = block((int) (y + halfSize)); - const float rmin = halfSize - 0.7071F; /* 0.7071 = sqrt(2)/2 */ - const float rmax = halfSize + 0.7071F; - const float rmin2 = MAX2(0.0F, rmin * rmin); - const float rmax2 = rmax * rmax; - const float cscale = 1.0F / (rmax2 - rmin2); - int ix, iy; - - for (iy = iymin; iy <= iymax; iy += 2) { - for (ix = ixmin; ix <= ixmax; ix += 2) { - float dx, dy, dist2, cover; - - setup->quad[0].inout.mask = 0x0; - - dx = (ix + 0.5f) - x; - dy = (iy + 0.5f) - y; - dist2 = dx * dx + dy * dy; - if (dist2 <= rmax2) { - cover = 1.0F - (dist2 - rmin2) * cscale; - setup->quad[0].input.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0f); - setup->quad[0].inout.mask |= MASK_TOP_LEFT; - } - - dx = (ix + 1.5f) - x; - dy = (iy + 0.5f) - y; - dist2 = dx * dx + dy * dy; - if (dist2 <= rmax2) { - cover = 1.0F - (dist2 - rmin2) * cscale; - setup->quad[0].input.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0f); - setup->quad[0].inout.mask |= MASK_TOP_RIGHT; - } - - dx = (ix + 0.5f) - x; - dy = (iy + 1.5f) - y; - dist2 = dx * dx + dy * dy; - if (dist2 <= rmax2) { - cover = 1.0F - (dist2 - rmin2) * cscale; - setup->quad[0].input.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0f); - setup->quad[0].inout.mask |= MASK_BOTTOM_LEFT; - } - - dx = (ix + 1.5f) - x; - dy = (iy + 1.5f) - y; - dist2 = dx * dx + dy * dy; - if (dist2 <= rmax2) { - cover = 1.0F - (dist2 - rmin2) * cscale; - setup->quad[0].input.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0f); - setup->quad[0].inout.mask |= MASK_BOTTOM_RIGHT; - } - - if (setup->quad[0].inout.mask) { - setup->quad[0].input.x0 = ix; - setup->quad[0].input.y0 = iy; - clip_emit_quad( setup, &setup->quad[0] ); - } + stored = lp_scene_alloc(scene, current_size); + if(stored) { + memcpy(stored, + current_data, + current_size); + setup->constants.stored_size = current_size; + setup->constants.stored_data = stored; } } } else { - /* square points */ - const int xmin = (int) (x + 0.75 - halfSize); - const int ymin = (int) (y + 0.25 - halfSize); - const int xmax = xmin + (int) size; - const int ymax = ymin + (int) size; - /* XXX could apply scissor to xmin,ymin,xmax,ymax now */ - const int ixmin = block(xmin); - const int ixmax = block(xmax - 1); - const int iymin = block(ymin); - const int iymax = block(ymax - 1); - int ix, iy; - - /* - debug_printf("(%f, %f) -> X:%d..%d Y:%d..%d\n", x, y, xmin, xmax,ymin,ymax); - */ - for (iy = iymin; iy <= iymax; iy += 2) { - uint rowMask = 0xf; - if (iy < ymin) { - /* above the top edge */ - rowMask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT); - } - if (iy + 1 >= ymax) { - /* below the bottom edge */ - rowMask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT); - } + setup->constants.stored_size = 0; + setup->constants.stored_data = NULL; + } - for (ix = ixmin; ix <= ixmax; ix += 2) { - uint mask = rowMask; - - if (ix < xmin) { - /* fragment is past left edge of point, turn off left bits */ - mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT); - } - if (ix + 1 >= xmax) { - /* past the right edge */ - mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT); - } - - setup->quad[0].inout.mask = mask; - setup->quad[0].input.x0 = ix; - setup->quad[0].input.y0 = iy; - clip_emit_quad( setup, &setup->quad[0] ); - } + setup->fs.current.jit_context.constants = setup->constants.stored_data; + setup->dirty |= LP_SETUP_NEW_FS; + } + + + if(setup->dirty & LP_SETUP_NEW_FS) { + if(!setup->fs.stored || + memcmp(setup->fs.stored, + &setup->fs.current, + sizeof setup->fs.current) != 0) { + /* The fs state that's been stored in the scene is different from + * the new, current state. So allocate a new lp_rast_state object + * and append it to the bin's setup data buffer. + */ + struct lp_rast_state *stored = + (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored); + if(stored) { + memcpy(stored, + &setup->fs.current, + sizeof setup->fs.current); + setup->fs.stored = stored; + + /* put the state-set command into all bins */ + lp_scene_bin_state_command( scene, + lp_rast_set_state, + lp_rast_arg_state(setup->fs.stored) ); } } } + + setup->dirty = 0; + + assert(setup->fs.stored); } -void llvmpipe_setup_prepare( struct setup_context *setup ) + + +/* Only caller is lp_setup_vbuf_destroy() + */ +void +lp_setup_destroy( struct setup_context *setup ) { - struct llvmpipe_context *lp = setup->llvmpipe; + reset_context( setup ); - if (lp->dirty) { - llvmpipe_update_derived(lp); - } + pipe_buffer_reference(&setup->constants.current, NULL); - if (lp->reduced_api_prim == PIPE_PRIM_TRIANGLES && - lp->rasterizer->fill_cw == PIPE_POLYGON_MODE_FILL && - lp->rasterizer->fill_ccw == PIPE_POLYGON_MODE_FILL) { - /* we'll do culling */ - setup->winding = lp->rasterizer->cull_mode; - } - else { - /* 'draw' will do culling */ - setup->winding = PIPE_WINDING_NONE; + /* free the scenes in the 'empty' queue */ + while (1) { + struct lp_scene *scene = lp_scene_dequeue(setup->empty_scenes, FALSE); + if (!scene) + break; + lp_scene_destroy(scene); } -} - + lp_rast_destroy( setup->rast ); -void llvmpipe_setup_destroy_context( struct setup_context *setup ) -{ - align_free( setup ); + FREE( setup ); } /** - * Create a new primitive setup/render stage. + * Create a new primitive tiling engine. Plug it into the backend of + * the draw module. Currently also creates a rasterizer to use with + * it. */ -struct setup_context *llvmpipe_setup_create_context( struct llvmpipe_context *llvmpipe ) +struct setup_context * +lp_setup_create( struct pipe_screen *screen, + struct draw_context *draw ) { - struct setup_context *setup; unsigned i; + struct setup_context *setup = CALLOC_STRUCT(setup_context); - setup = align_malloc(sizeof(struct setup_context), 16); if (!setup) return NULL; - memset(setup, 0, sizeof *setup); - setup->llvmpipe = llvmpipe; + lp_setup_init_vbuf(setup); + + setup->empty_scenes = lp_scene_queue_create(); + if (!setup->empty_scenes) + goto fail; - for (i = 0; i < MAX_QUADS; i++) { - setup->quad[i].coef = &setup->coef; + setup->rast = lp_rast_create( screen, setup->empty_scenes ); + if (!setup->rast) + goto fail; + + setup->vbuf = draw_vbuf_stage(draw, &setup->base); + if (!setup->vbuf) + goto fail; + + draw_set_rasterize_stage(draw, setup->vbuf); + draw_set_render(draw, &setup->base); + + /* create some empty scenes */ + for (i = 0; i < MAX_SCENES; i++) { + setup->scenes[i] = lp_scene_create(); + lp_scene_enqueue(setup->empty_scenes, setup->scenes[i]); } - setup->span.left[0] = 1000000; /* greater than right[0] */ - setup->span.left[1] = 1000000; /* greater than right[1] */ + setup->triangle = first_triangle; + setup->line = first_line; + setup->point = first_point; + + setup->dirty = ~0; return setup; + +fail: + if (setup->rast) + lp_rast_destroy( setup->rast ); + + if (setup->vbuf) + ; + + if (setup->empty_scenes) + lp_scene_queue_destroy(setup->empty_scenes); + + FREE(setup); + return NULL; } diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h index 89c43da046..0e155a7dc3 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.h +++ b/src/gallium/drivers/llvmpipe/lp_setup.h @@ -27,27 +27,113 @@ #ifndef LP_SETUP_H #define LP_SETUP_H -struct setup_context; -struct llvmpipe_context; +#include "pipe/p_compiler.h" +#include "lp_jit.h" + +struct draw_context; +struct vertex_info; + +enum lp_interp { + LP_INTERP_CONSTANT, + LP_INTERP_LINEAR, + LP_INTERP_PERSPECTIVE, + LP_INTERP_POSITION, + LP_INTERP_FACING +}; + +/* Describes how to generate all the fragment shader inputs from the + * the vertices passed into our triangle/line/point functions. + * + * Vertices are treated as an array of float[4] values, indexed by + * src_index. + */ +struct lp_shader_input { + enum lp_interp interp; /* how to interpolate values */ + unsigned src_index; /* where to find values in incoming vertices */ +}; + +struct pipe_texture; +struct pipe_surface; +struct pipe_buffer; +struct pipe_blend_color; +struct pipe_screen; +struct pipe_framebuffer_state; +struct lp_fragment_shader; +struct lp_jit_context; + +struct setup_context * +lp_setup_create( struct pipe_screen *screen, + struct draw_context *draw ); + +void +lp_setup_clear(struct setup_context *setup, + const float *clear_color, + double clear_depth, + unsigned clear_stencil, + unsigned flags); + +struct pipe_fence_handle * +lp_setup_fence( struct setup_context *setup ); + + +void +lp_setup_flush( struct setup_context *setup, + unsigned flags ); + + +void +lp_setup_bind_framebuffer( struct setup_context *setup, + const struct pipe_framebuffer_state *fb ); void -llvmpipe_setup_tri( struct setup_context *setup, - const float (*v0)[4], - const float (*v1)[4], - const float (*v2)[4] ); +lp_setup_set_triangle_state( struct setup_context *setup, + unsigned cullmode, + boolean front_is_ccw, + boolean scissor ); void -llvmpipe_setup_line(struct setup_context *setup, - const float (*v0)[4], - const float (*v1)[4]); +lp_setup_set_fs_inputs( struct setup_context *setup, + const struct lp_shader_input *interp, + unsigned nr ); void -llvmpipe_setup_point( struct setup_context *setup, - const float (*v0)[4] ); +lp_setup_set_fs_functions( struct setup_context *setup, + lp_jit_frag_func jit_function0, + lp_jit_frag_func jit_function1, + boolean opaque ); +void +lp_setup_set_fs_constants(struct setup_context *setup, + struct pipe_buffer *buffer); + + +void +lp_setup_set_alpha_ref_value( struct setup_context *setup, + float alpha_ref_value ); + +void +lp_setup_set_blend_color( struct setup_context *setup, + const struct pipe_blend_color *blend_color ); + +void +lp_setup_set_scissor( struct setup_context *setup, + const struct pipe_scissor_state *scissor ); + +void +lp_setup_set_sampler_textures( struct setup_context *setup, + unsigned num, struct pipe_texture **texture); + +unsigned +lp_setup_is_texture_referenced( const struct setup_context *setup, + const struct pipe_texture *texture ); + +void +lp_setup_set_flatshade_first( struct setup_context *setup, + boolean flatshade_first ); + +void +lp_setup_set_vertex_info( struct setup_context *setup, + struct vertex_info *info ); -struct setup_context *llvmpipe_setup_create_context( struct llvmpipe_context *llvmpipe ); -void llvmpipe_setup_prepare( struct setup_context *setup ); -void llvmpipe_setup_destroy_context( struct setup_context *setup ); #endif diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h new file mode 100644 index 0000000000..a5fc34e54a --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h @@ -0,0 +1,159 @@ +/************************************************************************** + * + * Copyright 2007-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. + * + **************************************************************************/ + + +/** + * The setup code is concerned with point/line/triangle setup and + * putting commands/data into the bins. + */ + + +#ifndef LP_SETUP_CONTEXT_H +#define LP_SETUP_CONTEXT_H + +#include "lp_setup.h" +#include "lp_rast.h" +#include "lp_tile_soa.h" /* for TILE_SIZE */ +#include "lp_scene.h" + +#include "draw/draw_vbuf.h" + +#define LP_SETUP_NEW_FS 0x01 +#define LP_SETUP_NEW_CONSTANTS 0x02 +#define LP_SETUP_NEW_BLEND_COLOR 0x04 +#define LP_SETUP_NEW_SCISSOR 0x08 + + +struct lp_scene_queue; + + +/** Max number of scenes */ +#define MAX_SCENES 2 + + + +/** + * Point/line/triangle setup context. + * Note: "stored" below indicates data which is stored in the bins, + * not arbitrary malloc'd memory. + * + * + * Subclass of vbuf_render, plugged directly into the draw module as + * the rendering backend. + */ +struct setup_context +{ + struct vbuf_render base; + + struct vertex_info *vertex_info; + uint prim; + uint vertex_size; + uint nr_vertices; + uint vertex_buffer_size; + void *vertex_buffer; + + /* Final pipeline stage for draw module. Draw module should + * create/install this itself now. + */ + struct draw_stage *vbuf; + struct lp_rasterizer *rast; + struct lp_scene *scenes[MAX_SCENES]; /**< all the scenes */ + struct lp_scene *scene; /**< current scene being built */ + struct lp_scene_queue *empty_scenes; /**< queue of empty scenes */ + + boolean flatshade_first; + boolean ccw_is_frontface; + boolean scissor_test; + unsigned cullmode; + + struct pipe_framebuffer_state fb; + + struct { + unsigned flags; + union lp_rast_cmd_arg color; /**< lp_rast_clear_color() cmd */ + union lp_rast_cmd_arg zstencil; /**< lp_rast_clear_zstencil() cmd */ + } clear; + + enum { + SETUP_FLUSHED, + SETUP_CLEARED, + SETUP_ACTIVE + } state; + + struct { + struct lp_shader_input input[PIPE_MAX_ATTRIBS]; + unsigned nr_inputs; + + const struct lp_rast_state *stored; /**< what's in the scene */ + struct lp_rast_state current; /**< currently set state */ + } fs; + + /** fragment shader constants */ + struct { + struct pipe_buffer *current; + unsigned stored_size; + const void *stored_data; + } constants; + + struct { + struct pipe_blend_color current; + uint8_t *stored; + } blend_color; + + struct { + struct pipe_scissor_state current; + const void *stored; + } scissor; + + unsigned dirty; /**< bitmask of LP_SETUP_NEW_x bits */ + + void (*point)( struct setup_context *, + const float (*v0)[4]); + + void (*line)( struct setup_context *, + const float (*v0)[4], + const float (*v1)[4]); + + void (*triangle)( struct setup_context *, + const float (*v0)[4], + const float (*v1)[4], + const float (*v2)[4]); +}; + +void lp_setup_choose_triangle( struct setup_context *setup ); +void lp_setup_choose_line( struct setup_context *setup ); +void lp_setup_choose_point( struct setup_context *setup ); + +struct lp_scene *lp_setup_get_current_scene(struct setup_context *setup); + +void lp_setup_init_vbuf(struct setup_context *setup); + +void lp_setup_update_state( struct setup_context *setup ); + +void lp_setup_destroy( struct setup_context *setup ); + +#endif diff --git a/src/gallium/drivers/llvmpipe/lp_bld_alpha.h b/src/gallium/drivers/llvmpipe/lp_setup_line.c index 634575670d..feea79d394 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_alpha.h +++ b/src/gallium/drivers/llvmpipe/lp_setup_line.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2009 VMware, Inc. + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,37 +18,30 @@ * 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 + * 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. * **************************************************************************/ -/** - * Alpha testing to LLVM IR translation. - * - * @author Jose Fonseca <jfonseca@vmware.com> +/* + * Binning code for lines */ -#ifndef LP_BLD_ALPHA_H -#define LP_BLD_ALPHA_H - - -#include <llvm-c/Core.h> +#include "lp_setup_context.h" -struct pipe_alpha_state; -struct lp_type; -struct lp_build_mask_context; +static void line_nop( struct setup_context *setup, + const float (*v0)[4], + const float (*v1)[4] ) +{ +} -void -lp_build_alpha_test(LLVMBuilderRef builder, - const struct pipe_alpha_state *state, - struct lp_type type, - struct lp_build_mask_context *mask, - LLVMValueRef alpha, - LLVMValueRef ref); +void +lp_setup_choose_line( struct setup_context *setup ) +{ + setup->line = line_nop; +} -#endif /* !LP_BLD_ALPHA_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_prim_vbuf.h b/src/gallium/drivers/llvmpipe/lp_setup_point.c index 0676e2f42a..f03ca729b2 100644 --- a/src/gallium/drivers/llvmpipe/lp_prim_vbuf.h +++ b/src/gallium/drivers/llvmpipe/lp_setup_point.c @@ -1,8 +1,8 @@ /************************************************************************** - * + * * Copyright 2007 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 @@ -10,11 +10,11 @@ * 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. @@ -22,17 +22,25 @@ * 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 LP_VBUF_H -#define LP_VBUF_H +/* + * Binning code for points + */ +#include "lp_setup_context.h" -struct llvmpipe_context; +static void point_nop( struct setup_context *setup, + const float (*v0)[4] ) +{ +} -extern struct vbuf_render * -lp_create_vbuf_backend(struct llvmpipe_context *llvmpipe); + +void +lp_setup_choose_point( struct setup_context *setup ) +{ + setup->point = point_nop; +} -#endif /* LP_VBUF_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c new file mode 100644 index 0000000000..9e59a6602c --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c @@ -0,0 +1,618 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/* + * Binning code for triangles + */ + +#include "util/u_math.h" +#include "util/u_memory.h" +#include "lp_perf.h" +#include "lp_setup_context.h" +#include "lp_rast.h" + +#define NUM_CHANNELS 4 + + +/** + * Compute a0 for a constant-valued coefficient (GL_FLAT shading). + */ +static void constant_coef( struct lp_rast_triangle *tri, + unsigned slot, + const float value, + unsigned i ) +{ + tri->inputs.a0[slot][i] = value; + tri->inputs.dadx[slot][i] = 0.0f; + tri->inputs.dady[slot][i] = 0.0f; +} + + +/** + * Compute a0, dadx and dady for a linearly interpolated coefficient, + * for a triangle. + */ +static void linear_coef( struct lp_rast_triangle *tri, + float oneoverarea, + unsigned slot, + const float (*v1)[4], + const float (*v2)[4], + const float (*v3)[4], + unsigned vert_attr, + unsigned i) +{ + float a1 = v1[vert_attr][i]; + float a2 = v2[vert_attr][i]; + float a3 = v3[vert_attr][i]; + + float da12 = a1 - a2; + float da31 = a3 - a1; + float dadx = (da12 * tri->dy31 - tri->dy12 * da31) * oneoverarea; + float dady = (da31 * tri->dx12 - tri->dx31 * da12) * oneoverarea; + + tri->inputs.dadx[slot][i] = dadx; + tri->inputs.dady[slot][i] = dady; + + /* calculate a0 as the value which would be sampled for the + * fragment at (0,0), taking into account that we want to sample at + * pixel centers, in other words (0.5, 0.5). + * + * this is neat but unfortunately not a good way to do things for + * triangles with very large values of dadx or dady as it will + * result in the subtraction and re-addition from a0 of a very + * large number, which means we'll end up loosing a lot of the + * fractional bits and precision from a0. the way to fix this is + * to define a0 as the sample at a pixel center somewhere near vmin + * instead - i'll switch to this later. + */ + tri->inputs.a0[slot][i] = (a1 - + (dadx * (v1[0][0] - 0.5f) + + dady * (v1[0][1] - 0.5f))); +} + + +/** + * Compute a0, dadx and dady for a perspective-corrected interpolant, + * for a triangle. + * We basically multiply the vertex value by 1/w before computing + * the plane coefficients (a0, dadx, dady). + * Later, when we compute the value at a particular fragment position we'll + * divide the interpolated value by the interpolated W at that fragment. + */ +static void perspective_coef( struct lp_rast_triangle *tri, + float oneoverarea, + unsigned slot, + const float (*v1)[4], + const float (*v2)[4], + const float (*v3)[4], + unsigned vert_attr, + unsigned i) +{ + /* premultiply by 1/w (v[0][3] is always 1/w): + */ + float a1 = v1[vert_attr][i] * v1[0][3]; + float a2 = v2[vert_attr][i] * v2[0][3]; + float a3 = v3[vert_attr][i] * v3[0][3]; + float da12 = a1 - a2; + float da31 = a3 - a1; + float dadx = (da12 * tri->dy31 - tri->dy12 * da31) * oneoverarea; + float dady = (da31 * tri->dx12 - tri->dx31 * da12) * oneoverarea; + + tri->inputs.dadx[slot][i] = dadx; + tri->inputs.dady[slot][i] = dady; + tri->inputs.a0[slot][i] = (a1 - + (dadx * (v1[0][0] - 0.5f) + + dady * (v1[0][1] - 0.5f))); +} + + +/** + * Special coefficient setup for gl_FragCoord. + * X and Y are trivial + * Z and W are copied from position_coef which should have already been computed. + * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask. + */ +static void +setup_fragcoord_coef(struct lp_rast_triangle *tri, + float oneoverarea, + unsigned slot, + const float (*v1)[4], + const float (*v2)[4], + const float (*v3)[4]) +{ + /*X*/ + tri->inputs.a0[slot][0] = 0.0; + tri->inputs.dadx[slot][0] = 1.0; + tri->inputs.dady[slot][0] = 0.0; + /*Y*/ + tri->inputs.a0[slot][1] = 0.0; + tri->inputs.dadx[slot][1] = 0.0; + tri->inputs.dady[slot][1] = 1.0; + /*Z*/ + linear_coef(tri, oneoverarea, slot, v1, v2, v3, 0, 2); + /*W*/ + linear_coef(tri, oneoverarea, slot, v1, v2, v3, 0, 3); +} + + +static void setup_facing_coef( struct lp_rast_triangle *tri, + unsigned slot, + boolean frontface ) +{ + constant_coef( tri, slot, 1.0f - frontface, 0 ); + constant_coef( tri, slot, 0.0f, 1 ); /* wasted */ + constant_coef( tri, slot, 0.0f, 2 ); /* wasted */ + constant_coef( tri, slot, 0.0f, 3 ); /* wasted */ +} + + +/** + * Compute the tri->coef[] array dadx, dady, a0 values. + */ +static void setup_tri_coefficients( struct setup_context *setup, + struct lp_rast_triangle *tri, + float oneoverarea, + const float (*v1)[4], + const float (*v2)[4], + const float (*v3)[4], + boolean frontface) +{ + unsigned slot; + + /* The internal position input is in slot zero: + */ + setup_fragcoord_coef(tri, oneoverarea, 0, v1, v2, v3); + + /* setup interpolation for all the remaining attributes: + */ + for (slot = 0; slot < setup->fs.nr_inputs; slot++) { + unsigned vert_attr = setup->fs.input[slot].src_index; + unsigned i; + + switch (setup->fs.input[slot].interp) { + case LP_INTERP_CONSTANT: + for (i = 0; i < NUM_CHANNELS; i++) + constant_coef(tri, slot+1, v3[vert_attr][i], i); + break; + + case LP_INTERP_LINEAR: + for (i = 0; i < NUM_CHANNELS; i++) + linear_coef(tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i); + break; + + case LP_INTERP_PERSPECTIVE: + for (i = 0; i < NUM_CHANNELS; i++) + perspective_coef(tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i); + break; + + case LP_INTERP_POSITION: + /* XXX: fix me - duplicates the values in slot zero. + */ + setup_fragcoord_coef(tri, oneoverarea, slot+1, v1, v2, v3); + break; + + case LP_INTERP_FACING: + setup_facing_coef(tri, slot+1, frontface); + break; + + default: + assert(0); + } + } +} + + + +static INLINE int subpixel_snap( float a ) +{ + return util_iround(FIXED_ONE * a - (FIXED_ONE / 2)); +} + + + +/** + * Alloc space for a new triangle plus the input.a0/dadx/dady arrays + * immediately after it. + * The memory is allocated from the per-scene pool, not per-tile. + * \param tri_size returns number of bytes allocated + * \param nr_inputs number of fragment shader inputs + * \return pointer to triangle space + */ +static INLINE struct lp_rast_triangle * +alloc_triangle(struct lp_scene *scene, unsigned nr_inputs, unsigned *tri_size) +{ + unsigned input_array_sz = NUM_CHANNELS * (nr_inputs + 1) * sizeof(float); + struct lp_rast_triangle *tri; + unsigned bytes; + char *inputs; + + assert(sizeof(*tri) % 16 == 0); + + bytes = sizeof(*tri) + (3 * input_array_sz); + + tri = lp_scene_alloc_aligned( scene, bytes, 16 ); + + inputs = (char *) (tri + 1); + tri->inputs.a0 = (float (*)[4]) inputs; + tri->inputs.dadx = (float (*)[4]) (inputs + input_array_sz); + tri->inputs.dady = (float (*)[4]) (inputs + 2 * input_array_sz); + + *tri_size = bytes; + + return tri; +} + + + +/** + * Do basic setup for triangle rasterization and determine which + * framebuffer tiles are touched. Put the triangle in the scene's + * bins for the tiles which we overlap. + */ +static void +do_triangle_ccw(struct setup_context *setup, + const float (*v1)[4], + const float (*v2)[4], + const float (*v3)[4], + boolean frontfacing ) +{ + /* x/y positions in fixed point */ + const int x1 = subpixel_snap(v1[0][0]); + const int x2 = subpixel_snap(v2[0][0]); + const int x3 = subpixel_snap(v3[0][0]); + const int y1 = subpixel_snap(v1[0][1]); + const int y2 = subpixel_snap(v2[0][1]); + const int y3 = subpixel_snap(v3[0][1]); + + struct lp_scene *scene = lp_setup_get_current_scene(setup); + struct lp_rast_triangle *tri; + int area; + float oneoverarea; + int minx, maxx, miny, maxy; + unsigned tri_bytes; + + tri = alloc_triangle(scene, setup->fs.nr_inputs, &tri_bytes); + + tri->dx12 = x1 - x2; + tri->dx23 = x2 - x3; + tri->dx31 = x3 - x1; + + tri->dy12 = y1 - y2; + tri->dy23 = y2 - y3; + tri->dy31 = y3 - y1; + + area = (tri->dx12 * tri->dy31 - tri->dx31 * tri->dy12); + + LP_COUNT(nr_tris); + + /* Cull non-ccw and zero-sized triangles. + * + * XXX: subject to overflow?? + */ + if (area <= 0) { + lp_scene_putback_data( scene, tri_bytes ); + LP_COUNT(nr_culled_tris); + return; + } + + /* Bounding rectangle (in pixels) */ + minx = (MIN3(x1, x2, x3) + (FIXED_ONE-1)) >> FIXED_ORDER; + maxx = (MAX3(x1, x2, x3) + (FIXED_ONE-1)) >> FIXED_ORDER; + miny = (MIN3(y1, y2, y3) + (FIXED_ONE-1)) >> FIXED_ORDER; + maxy = (MAX3(y1, y2, y3) + (FIXED_ONE-1)) >> FIXED_ORDER; + + if (setup->scissor_test) { + minx = MAX2(minx, setup->scissor.current.minx); + maxx = MIN2(maxx, setup->scissor.current.maxx); + miny = MAX2(miny, setup->scissor.current.miny); + maxy = MIN2(maxy, setup->scissor.current.maxy); + } + + if (miny == maxy || + minx == maxx) { + lp_scene_putback_data( scene, tri_bytes ); + LP_COUNT(nr_culled_tris); + return; + } + + /* + */ + oneoverarea = ((float)FIXED_ONE) / (float)area; + + /* Setup parameter interpolants: + */ + setup_tri_coefficients( setup, tri, oneoverarea, v1, v2, v3, frontfacing ); + + /* half-edge constants, will be interated over the whole render target. + */ + tri->c1 = tri->dy12 * x1 - tri->dx12 * y1; + tri->c2 = tri->dy23 * x2 - tri->dx23 * y2; + tri->c3 = tri->dy31 * x3 - tri->dx31 * y3; + + /* correct for top-left fill convention: + */ + if (tri->dy12 < 0 || (tri->dy12 == 0 && tri->dx12 > 0)) tri->c1++; + if (tri->dy23 < 0 || (tri->dy23 == 0 && tri->dx23 > 0)) tri->c2++; + if (tri->dy31 < 0 || (tri->dy31 == 0 && tri->dx31 > 0)) tri->c3++; + + tri->dy12 *= FIXED_ONE; + tri->dy23 *= FIXED_ONE; + tri->dy31 *= FIXED_ONE; + + tri->dx12 *= FIXED_ONE; + tri->dx23 *= FIXED_ONE; + tri->dx31 *= FIXED_ONE; + + /* find trivial reject offsets for each edge for a single-pixel + * sized block. These will be scaled up at each recursive level to + * match the active blocksize. Scaling in this way works best if + * the blocks are square. + */ + tri->eo1 = 0; + if (tri->dy12 < 0) tri->eo1 -= tri->dy12; + if (tri->dx12 > 0) tri->eo1 += tri->dx12; + + tri->eo2 = 0; + if (tri->dy23 < 0) tri->eo2 -= tri->dy23; + if (tri->dx23 > 0) tri->eo2 += tri->dx23; + + tri->eo3 = 0; + if (tri->dy31 < 0) tri->eo3 -= tri->dy31; + if (tri->dx31 > 0) tri->eo3 += tri->dx31; + + /* Calculate trivial accept offsets from the above. + */ + tri->ei1 = tri->dx12 - tri->dy12 - tri->eo1; + tri->ei2 = tri->dx23 - tri->dy23 - tri->eo2; + tri->ei3 = tri->dx31 - tri->dy31 - tri->eo3; + + /* Fill in the inputs.step[][] arrays. + * We've manually unrolled some loops here. + */ + { + const int xstep1 = -tri->dy12; + const int xstep2 = -tri->dy23; + const int xstep3 = -tri->dy31; + const int ystep1 = tri->dx12; + const int ystep2 = tri->dx23; + const int ystep3 = tri->dx31; + +#define SETUP_STEP(i, x, y) \ + do { \ + tri->inputs.step[0][i] = x * xstep1 + y * ystep1; \ + tri->inputs.step[1][i] = x * xstep2 + y * ystep2; \ + tri->inputs.step[2][i] = x * xstep3 + y * ystep3; \ + } while (0) + + SETUP_STEP(0, 0, 0); + SETUP_STEP(1, 1, 0); + SETUP_STEP(2, 0, 1); + SETUP_STEP(3, 1, 1); + + SETUP_STEP(4, 2, 0); + SETUP_STEP(5, 3, 0); + SETUP_STEP(6, 2, 1); + SETUP_STEP(7, 3, 1); + + SETUP_STEP(8, 0, 2); + SETUP_STEP(9, 1, 2); + SETUP_STEP(10, 0, 3); + SETUP_STEP(11, 1, 3); + + SETUP_STEP(12, 2, 2); + SETUP_STEP(13, 3, 2); + SETUP_STEP(14, 2, 3); + SETUP_STEP(15, 3, 3); +#undef STEP + } + + /* + * All fields of 'tri' are now set. The remaining code here is + * concerned with binning. + */ + + /* Convert to tile coordinates: + */ + minx = minx / TILE_SIZE; + miny = miny / TILE_SIZE; + maxx = maxx / TILE_SIZE; + maxy = maxy / TILE_SIZE; + + /* Clamp maxx, maxy to framebuffer size + */ + maxx = MIN2(maxx, scene->tiles_x - 1); + maxy = MIN2(maxy, scene->tiles_y - 1); + + /* Determine which tile(s) intersect the triangle's bounding box + */ + if (miny == maxy && minx == maxx) + { + /* Triangle is contained in a single tile: + */ + lp_scene_bin_command( scene, minx, miny, lp_rast_triangle, + lp_rast_arg_triangle(tri) ); + } + else + { + int c1 = (tri->c1 + + tri->dx12 * miny * TILE_SIZE - + tri->dy12 * minx * TILE_SIZE); + int c2 = (tri->c2 + + tri->dx23 * miny * TILE_SIZE - + tri->dy23 * minx * TILE_SIZE); + int c3 = (tri->c3 + + tri->dx31 * miny * TILE_SIZE - + tri->dy31 * minx * TILE_SIZE); + + int ei1 = tri->ei1 << TILE_ORDER; + int ei2 = tri->ei2 << TILE_ORDER; + int ei3 = tri->ei3 << TILE_ORDER; + + int eo1 = tri->eo1 << TILE_ORDER; + int eo2 = tri->eo2 << TILE_ORDER; + int eo3 = tri->eo3 << TILE_ORDER; + + int xstep1 = -(tri->dy12 << TILE_ORDER); + int xstep2 = -(tri->dy23 << TILE_ORDER); + int xstep3 = -(tri->dy31 << TILE_ORDER); + + int ystep1 = tri->dx12 << TILE_ORDER; + int ystep2 = tri->dx23 << TILE_ORDER; + int ystep3 = tri->dx31 << TILE_ORDER; + int x, y; + + + /* Test tile-sized blocks against the triangle. + * Discard blocks fully outside the tri. If the block is fully + * contained inside the tri, bin an lp_rast_shade_tile command. + * Else, bin a lp_rast_triangle command. + */ + for (y = miny; y <= maxy; y++) + { + int cx1 = c1; + int cx2 = c2; + int cx3 = c3; + boolean in = FALSE; /* are we inside the triangle? */ + + for (x = minx; x <= maxx; x++) + { + if (cx1 + eo1 < 0 || + cx2 + eo2 < 0 || + cx3 + eo3 < 0) + { + /* do nothing */ + LP_COUNT(nr_empty_64); + if (in) + break; /* exiting triangle, all done with this row */ + } + else if (cx1 + ei1 > 0 && + cx2 + ei2 > 0 && + cx3 + ei3 > 0) + { + /* triangle covers the whole tile- shade whole tile */ + LP_COUNT(nr_fully_covered_64); + in = TRUE; + if(setup->fs.current.opaque) { + lp_scene_bin_reset( scene, x, y ); + lp_scene_bin_command( scene, x, y, + lp_rast_set_state, + lp_rast_arg_state(setup->fs.stored) ); + } + lp_scene_bin_command( scene, x, y, + lp_rast_shade_tile, + lp_rast_arg_inputs(&tri->inputs) ); + } + else + { + /* rasterizer/shade partial tile */ + LP_COUNT(nr_partially_covered_64); + in = TRUE; + lp_scene_bin_command( scene, x, y, + lp_rast_triangle, + lp_rast_arg_triangle(tri) ); + } + + /* Iterate cx values across the region: + */ + cx1 += xstep1; + cx2 += xstep2; + cx3 += xstep3; + } + + /* Iterate c values down the region: + */ + c1 += ystep1; + c2 += ystep2; + c3 += ystep3; + } + } +} + + +static void triangle_cw( struct setup_context *setup, + const float (*v0)[4], + const float (*v1)[4], + const float (*v2)[4] ) +{ + do_triangle_ccw( setup, v1, v0, v2, !setup->ccw_is_frontface ); +} + + +static void triangle_ccw( struct setup_context *setup, + const float (*v0)[4], + const float (*v1)[4], + const float (*v2)[4] ) +{ + do_triangle_ccw( setup, v0, v1, v2, setup->ccw_is_frontface ); +} + + +static void triangle_both( struct setup_context *setup, + const float (*v0)[4], + const float (*v1)[4], + const float (*v2)[4] ) +{ + /* edge vectors e = v0 - v2, f = v1 - v2 */ + const float ex = v0[0][0] - v2[0][0]; + const float ey = v0[0][1] - v2[0][1]; + const float fx = v1[0][0] - v2[0][0]; + const float fy = v1[0][1] - v2[0][1]; + + /* det = cross(e,f).z */ + if (ex * fy - ey * fx < 0.0f) + triangle_ccw( setup, v0, v1, v2 ); + else + triangle_cw( setup, v0, v1, v2 ); +} + + +static void triangle_nop( struct setup_context *setup, + const float (*v0)[4], + const float (*v1)[4], + const float (*v2)[4] ) +{ +} + + +void +lp_setup_choose_triangle( struct setup_context *setup ) +{ + switch (setup->cullmode) { + case PIPE_WINDING_NONE: + setup->triangle = triangle_both; + break; + case PIPE_WINDING_CCW: + setup->triangle = triangle_cw; + break; + case PIPE_WINDING_CW: + setup->triangle = triangle_ccw; + break; + default: + setup->triangle = triangle_nop; + break; + } +} diff --git a/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c new file mode 100644 index 0000000000..24291da91e --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_setup_vbuf.c @@ -0,0 +1,518 @@ +/************************************************************************** + * + * Copyright 2007 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. + * + **************************************************************************/ + +/** + * Interface between 'draw' module's output and the llvmpipe rasterizer/setup + * code. When the 'draw' module has finished filling a vertex buffer, the + * draw_arrays() functions below will be called. Loop over the vertices and + * call the point/line/tri setup functions. + * + * Authors + * Brian Paul + */ + + +#include "lp_setup_context.h" +#include "draw/draw_vbuf.h" +#include "draw/draw_vertex.h" +#include "util/u_memory.h" + + +#define LP_MAX_VBUF_INDEXES 1024 +#define LP_MAX_VBUF_SIZE 4096 + + + +/** cast wrapper */ +static struct setup_context * +setup_context(struct vbuf_render *vbr) +{ + return (struct setup_context *) vbr; +} + + + +static const struct vertex_info * +lp_setup_get_vertex_info(struct vbuf_render *vbr) +{ + struct setup_context *setup = setup_context(vbr); + return setup->vertex_info; +} + + +static boolean +lp_setup_allocate_vertices(struct vbuf_render *vbr, + ushort vertex_size, ushort nr_vertices) +{ + struct setup_context *setup = setup_context(vbr); + unsigned size = vertex_size * nr_vertices; + + if (setup->vertex_buffer_size < size) { + align_free(setup->vertex_buffer); + setup->vertex_buffer = align_malloc(size, 16); + setup->vertex_buffer_size = size; + } + + setup->vertex_size = vertex_size; + setup->nr_vertices = nr_vertices; + + return setup->vertex_buffer != NULL; +} + +static void +lp_setup_release_vertices(struct vbuf_render *vbr) +{ + /* keep the old allocation for next time */ +} + +static void * +lp_setup_map_vertices(struct vbuf_render *vbr) +{ + struct setup_context *setup = setup_context(vbr); + return setup->vertex_buffer; +} + +static void +lp_setup_unmap_vertices(struct vbuf_render *vbr, + ushort min_index, + ushort max_index ) +{ + struct setup_context *setup = setup_context(vbr); + assert( setup->vertex_buffer_size >= (max_index+1) * setup->vertex_size ); + /* do nothing */ +} + + +static boolean +lp_setup_set_primitive(struct vbuf_render *vbr, unsigned prim) +{ + setup_context(vbr)->prim = prim; + return TRUE; +} + +typedef const float (*const_float4_ptr)[4]; + +static INLINE const_float4_ptr get_vert( const void *vertex_buffer, + int index, + int stride ) +{ + return (const_float4_ptr)((char *)vertex_buffer + index * stride); +} + +/** + * draw elements / indexed primitives + */ +static void +lp_setup_draw(struct vbuf_render *vbr, const ushort *indices, uint nr) +{ + struct setup_context *setup = setup_context(vbr); + const unsigned stride = setup->vertex_info->size * sizeof(float); + const void *vertex_buffer = setup->vertex_buffer; + unsigned i; + + lp_setup_update_state(setup); + + switch (setup->prim) { + case PIPE_PRIM_POINTS: + for (i = 0; i < nr; i++) { + setup->point( setup, + get_vert(vertex_buffer, indices[i-0], stride) ); + } + break; + + case PIPE_PRIM_LINES: + for (i = 1; i < nr; i += 2) { + setup->line( setup, + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } + break; + + case PIPE_PRIM_LINE_STRIP: + for (i = 1; i < nr; i ++) { + setup->line( setup, + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } + break; + + case PIPE_PRIM_LINE_LOOP: + for (i = 1; i < nr; i ++) { + setup->line( setup, + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[i-0], stride) ); + } + if (nr) { + setup->line( setup, + get_vert(vertex_buffer, indices[nr-1], stride), + get_vert(vertex_buffer, indices[0], stride) ); + } + break; + + case PIPE_PRIM_TRIANGLES: + if (setup->flatshade_first) { + for (i = 2; i < nr; i += 3) { + setup->triangle( setup, + 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 { + for (i = 2; i < nr; i += 3) { + setup->triangle( setup, + 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: + if (setup->flatshade_first) { + for (i = 2; i < nr; i += 1) { + setup->triangle( setup, + 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 { + for (i = 2; i < nr; i += 1) { + setup->triangle( setup, + 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: + if (setup->flatshade_first) { + for (i = 2; i < nr; i += 1) { + setup->triangle( setup, + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[0], stride), + get_vert(vertex_buffer, indices[i-1], stride) ); + } + } + else { + for (i = 2; i < nr; i += 1) { + setup->triangle( setup, + 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: + if (setup->flatshade_first) { + for (i = 3; i < nr; i += 4) { + setup->triangle( setup, + 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->triangle( setup, + 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 { + for (i = 3; i < nr; i += 4) { + setup->triangle( setup, + 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->triangle( setup, + 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: + if (setup->flatshade_first) { + for (i = 3; i < nr; i += 2) { + setup->triangle( setup, + 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->triangle( setup, + 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 { + for (i = 3; i < nr; i += 2) { + setup->triangle( setup, + 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->triangle( setup, + 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->triangle( setup, + get_vert(vertex_buffer, indices[i-0], stride), + get_vert(vertex_buffer, indices[i-1], stride), + get_vert(vertex_buffer, indices[0], stride) ); + } + break; + + default: + assert(0); + } +} + + +/** + * This function is hit when the draw module is working in pass-through mode. + * It's up to us to convert the vertex array into point/line/tri prims. + */ +static void +lp_setup_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) +{ + struct setup_context *setup = setup_context(vbr); + const unsigned stride = setup->vertex_info->size * sizeof(float); + const void *vertex_buffer = + (void *) get_vert(setup->vertex_buffer, start, stride); + unsigned i; + + lp_setup_update_state(setup); + + switch (setup->prim) { + case PIPE_PRIM_POINTS: + for (i = 0; i < nr; i++) { + setup->point( setup, + get_vert(vertex_buffer, i-0, stride) ); + } + break; + + case PIPE_PRIM_LINES: + for (i = 1; i < nr; i += 2) { + setup->line( setup, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); + } + break; + + case PIPE_PRIM_LINE_STRIP: + for (i = 1; i < nr; i ++) { + setup->line( setup, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); + } + break; + + case PIPE_PRIM_LINE_LOOP: + for (i = 1; i < nr; i ++) { + setup->line( setup, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride) ); + } + if (nr) { + setup->line( setup, + get_vert(vertex_buffer, nr-1, stride), + get_vert(vertex_buffer, 0, stride) ); + } + break; + + case PIPE_PRIM_TRIANGLES: + if (setup->flatshade_first) { + for (i = 2; i < nr; i += 3) { + setup->triangle( setup, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-2, stride) ); + } + } + else { + for (i = 2; i < nr; i += 3) { + setup->triangle( setup, + 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: + if (setup->flatshade_first) { + for (i = 2; i < nr; i++) { + setup->triangle( setup, + 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 { + for (i = 2; i < nr; i++) { + setup->triangle( setup, + 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: + if (setup->flatshade_first) { + for (i = 2; i < nr; i += 1) { + setup->triangle( setup, + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, 0, stride), + get_vert(vertex_buffer, i-1, stride) ); + } + } + else { + for (i = 2; i < nr; i += 1) { + setup->triangle( setup, + 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: + if (setup->flatshade_first) { + for (i = 3; i < nr; i += 4) { + setup->triangle( setup, + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-3, stride) ); + setup->triangle( setup, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-3, stride) ); + } + } + else { + for (i = 3; i < nr; i += 4) { + setup->triangle( setup, + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride) ); + setup->triangle( setup, + 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: + if (setup->flatshade_first) { + for (i = 3; i < nr; i += 2) { + setup->triangle( setup, + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-3, stride) ); + setup->triangle( setup, + + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, i-3, stride) ); + } + } + else { + for (i = 3; i < nr; i += 2) { + setup->triangle( setup, + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, i-2, stride), + get_vert(vertex_buffer, i-0, stride) ); + setup->triangle( setup, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-3, stride), + get_vert(vertex_buffer, 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->triangle( setup, + get_vert(vertex_buffer, i-1, stride), + get_vert(vertex_buffer, i-0, stride), + get_vert(vertex_buffer, 0, stride) ); + } + break; + + default: + assert(0); + } +} + + + +static void +lp_setup_vbuf_destroy(struct vbuf_render *vbr) +{ + lp_setup_destroy(setup_context(vbr)); +} + + +/** + * Create the post-transform vertex handler for the given context. + */ +void +lp_setup_init_vbuf(struct setup_context *setup) +{ + setup->base.max_indices = LP_MAX_VBUF_INDEXES; + setup->base.max_vertex_buffer_bytes = LP_MAX_VBUF_SIZE; + + setup->base.get_vertex_info = lp_setup_get_vertex_info; + setup->base.allocate_vertices = lp_setup_allocate_vertices; + setup->base.map_vertices = lp_setup_map_vertices; + setup->base.unmap_vertices = lp_setup_unmap_vertices; + setup->base.set_primitive = lp_setup_set_primitive; + setup->base.draw = lp_setup_draw; + setup->base.draw_arrays = lp_setup_draw_arrays; + setup->base.release_vertices = lp_setup_release_vertices; + setup->base.destroy = lp_setup_vbuf_destroy; +} diff --git a/src/gallium/drivers/llvmpipe/lp_state.h b/src/gallium/drivers/llvmpipe/lp_state.h index 7020da145f..8f68f12bed 100644 --- a/src/gallium/drivers/llvmpipe/lp_state.h +++ b/src/gallium/drivers/llvmpipe/lp_state.h @@ -36,7 +36,7 @@ #include "pipe/p_state.h" #include "tgsi/tgsi_scan.h" #include "lp_jit.h" -#include "lp_bld_sample.h" /* for struct lp_sampler_static_state */ +#include "gallivm/lp_bld_sample.h" /* for struct lp_sampler_static_state */ #define LP_NEW_VIEWPORT 0x1 @@ -54,6 +54,7 @@ #define LP_NEW_VERTEX 0x1000 #define LP_NEW_VS 0x2000 #define LP_NEW_QUERY 0x4000 +#define LP_NEW_BLEND_COLOR 0x8000 struct vertex_info; @@ -65,11 +66,18 @@ struct lp_fragment_shader; struct lp_fragment_shader_variant_key { - enum pipe_format zsbuf_format; struct pipe_depth_state depth; struct pipe_alpha_state alpha; struct pipe_blend_state blend; - + enum pipe_format zsbuf_format; + unsigned nr_cbufs:8; + unsigned flatshade:1; + unsigned scissor:1; + + struct { + ubyte colormask; + } cbuf_blend[PIPE_MAX_COLOR_BUFS]; + struct lp_sampler_static_state sampler[PIPE_MAX_SAMPLERS]; }; @@ -80,9 +88,9 @@ struct lp_fragment_shader_variant struct lp_fragment_shader_variant_key key; - LLVMValueRef function; + LLVMValueRef function[2]; - lp_jit_frag_func jit_function; + lp_jit_frag_func jit_function[2]; struct lp_fragment_shader_variant *next; }; @@ -154,7 +162,7 @@ void llvmpipe_set_clip_state( struct pipe_context *, void llvmpipe_set_constant_buffer(struct pipe_context *, uint shader, uint index, - const struct pipe_constant_buffer *buf); + struct pipe_buffer *buf); void *llvmpipe_create_fs_state(struct pipe_context *, const struct pipe_shader_state *); @@ -212,23 +220,10 @@ llvmpipe_draw_range_elements(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count); void -llvmpipe_map_transfers(struct llvmpipe_context *lp); - -void -llvmpipe_unmap_transfers(struct llvmpipe_context *lp); - -void llvmpipe_map_texture_surfaces(struct llvmpipe_context *lp); void llvmpipe_unmap_texture_surfaces(struct llvmpipe_context *lp); -struct vertex_info * -llvmpipe_get_vertex_info(struct llvmpipe_context *llvmpipe); - -struct vertex_info * -llvmpipe_get_vbuf_vertex_info(struct llvmpipe_context *llvmpipe); - - #endif diff --git a/src/gallium/drivers/llvmpipe/lp_state_blend.c b/src/gallium/drivers/llvmpipe/lp_state_blend.c index a94cd05ef2..9b950e82d8 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_blend.c +++ b/src/gallium/drivers/llvmpipe/lp_state_blend.c @@ -73,7 +73,9 @@ void llvmpipe_set_blend_color( struct pipe_context *pipe, const struct pipe_blend_color *blend_color ) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); - unsigned i, j; + + if(!blend_color) + return; if(memcmp(&llvmpipe->blend_color, blend_color, sizeof *blend_color) == 0) return; @@ -82,13 +84,7 @@ void llvmpipe_set_blend_color( struct pipe_context *pipe, memcpy(&llvmpipe->blend_color, blend_color, sizeof *blend_color); - if(!llvmpipe->jit_context.blend_color) - llvmpipe->jit_context.blend_color = align_malloc(4 * 16, 16); - for (i = 0; i < 4; ++i) { - uint8_t c = float_to_ubyte(blend_color->color[i]); - for (j = 0; j < 16; ++j) - llvmpipe->jit_context.blend_color[i*16 + j] = c; - } + llvmpipe->dirty |= LP_NEW_BLEND_COLOR; } @@ -117,9 +113,6 @@ llvmpipe_bind_depth_stencil_state(struct pipe_context *pipe, llvmpipe->depth_stencil = depth_stencil; - if(llvmpipe->depth_stencil) - llvmpipe->jit_context.alpha_ref_value = llvmpipe->depth_stencil->alpha.ref_value; - llvmpipe->dirty |= LP_NEW_DEPTH_STENCIL_ALPHA; } diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c index 6c1ef6bc42..bdd906e1a7 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_derived.c +++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c @@ -33,166 +33,113 @@ #include "draw/draw_private.h" #include "lp_context.h" #include "lp_screen.h" -#include "lp_tex_cache.h" +#include "lp_setup.h" #include "lp_state.h" -/** - * Mark the current vertex layout as "invalid". - * We'll validate the vertex layout later, when we start to actually - * render a point or line or tri. - */ -static void -invalidate_vertex_layout(struct llvmpipe_context *llvmpipe) -{ - llvmpipe->vertex_info.num_attribs = 0; -} - /** * The vertex info describes how to convert the post-transformed vertices * (simple float[][4]) used by the 'draw' module into vertices for * rasterization. * - * This function validates the vertex layout and returns a pointer to a - * vertex_info object. + * This function validates the vertex layout. */ -struct vertex_info * -llvmpipe_get_vertex_info(struct llvmpipe_context *llvmpipe) +static void +compute_vertex_info(struct llvmpipe_context *llvmpipe) { + const struct lp_fragment_shader *lpfs = llvmpipe->fs; struct vertex_info *vinfo = &llvmpipe->vertex_info; + const uint num = draw_num_shader_outputs(llvmpipe->draw); + uint i; - if (vinfo->num_attribs == 0) { - /* compute vertex layout now */ - const struct lp_fragment_shader *lpfs = llvmpipe->fs; - struct vertex_info *vinfo_vbuf = &llvmpipe->vertex_info_vbuf; - const uint num = draw_current_shader_outputs(llvmpipe->draw); - uint i; - - /* Tell draw_vbuf to simply emit the whole post-xform vertex - * as-is. No longer any need to try and emit draw vertex_header - * info. - */ - vinfo_vbuf->num_attribs = 0; - for (i = 0; i < num; i++) { - draw_emit_vertex_attr(vinfo_vbuf, EMIT_4F, INTERP_PERSPECTIVE, i); - } - draw_compute_vertex_size(vinfo_vbuf); + /* Tell setup to tell the draw module to simply emit the whole + * post-xform vertex as-is. + * + * Not really sure if this is the best approach. + */ + vinfo->num_attribs = 0; + for (i = 0; i < num; i++) { + draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, i); + } + draw_compute_vertex_size(vinfo); - /* - * Loop over fragment shader inputs, searching for the matching output - * from the vertex shader. - */ - vinfo->num_attribs = 0; - for (i = 0; i < lpfs->info.num_inputs; i++) { - int src; - enum interp_mode interp; - switch (lpfs->info.input_interpolate[i]) { - case TGSI_INTERPOLATE_CONSTANT: - interp = INTERP_CONSTANT; - break; - case TGSI_INTERPOLATE_LINEAR: - interp = INTERP_LINEAR; - break; - case TGSI_INTERPOLATE_PERSPECTIVE: - interp = INTERP_PERSPECTIVE; - break; - default: - assert(0); - interp = INTERP_LINEAR; - } + lp_setup_set_vertex_info(llvmpipe->setup, vinfo); + +/* + llvmpipe->psize_slot = draw_find_vs_output(llvmpipe->draw, + TGSI_SEMANTIC_PSIZE, 0); +*/ + + /* Now match FS inputs against emitted vertex data. It's also + * entirely possible to just have a fixed layout for FS input, + * determined by the fragment shader itself, and adjust the draw + * outputs to match that. + */ + { + struct lp_shader_input inputs[PIPE_MAX_SHADER_INPUTS]; + for (i = 0; i < lpfs->info.num_inputs; i++) { + + /* This can be precomputed, except for flatshade: + */ switch (lpfs->info.input_semantic_name[i]) { + case TGSI_SEMANTIC_FACE: + inputs[i].interp = LP_INTERP_FACING; + break; case TGSI_SEMANTIC_POSITION: - interp = INTERP_POS; + inputs[i].interp = LP_INTERP_POSITION; break; - case TGSI_SEMANTIC_COLOR: - if (llvmpipe->rasterizer->flatshade) { - interp = INTERP_CONSTANT; - } + /* Colors are linearly interpolated in the fragment shader + * even when flatshading is active. This just tells the + * setup module to use coefficients with ddx==0 and + * ddy==0. + */ + if (llvmpipe->rasterizer->flatshade) + inputs[i].interp = LP_INTERP_CONSTANT; + else + inputs[i].interp = LP_INTERP_LINEAR; break; - } - /* this includes texcoords and varying vars */ - src = draw_find_shader_output(llvmpipe->draw, - lpfs->info.input_semantic_name[i], - lpfs->info.input_semantic_index[i]); - draw_emit_vertex_attr(vinfo, EMIT_4F, interp, src); - } + default: + switch (lpfs->info.input_interpolate[i]) { + case TGSI_INTERPOLATE_CONSTANT: + inputs[i].interp = LP_INTERP_CONSTANT; + break; + case TGSI_INTERPOLATE_LINEAR: + inputs[i].interp = LP_INTERP_LINEAR; + break; + case TGSI_INTERPOLATE_PERSPECTIVE: + inputs[i].interp = LP_INTERP_PERSPECTIVE; + break; + default: + assert(0); + break; + } + } - llvmpipe->psize_slot = draw_find_shader_output(llvmpipe->draw, - TGSI_SEMANTIC_PSIZE, 0); - if (llvmpipe->psize_slot > 0) { - draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, - llvmpipe->psize_slot); + /* Search for each input in current vs output: + */ + inputs[i].src_index = + draw_find_shader_output(llvmpipe->draw, + lpfs->info.input_semantic_name[i], + lpfs->info.input_semantic_index[i]); } - draw_compute_vertex_size(vinfo); + lp_setup_set_fs_inputs(llvmpipe->setup, + inputs, + lpfs->info.num_inputs); } - - return vinfo; } /** - * Called from vbuf module. + * Handle state changes. + * Called just prior to drawing anything (pipe::draw_arrays(), etc). * - * Note that there's actually two different vertex layouts in llvmpipe. - * - * The normal one is computed in llvmpipe_get_vertex_info() above and is - * used by the point/line/tri "setup" code. - * - * The other one (this one) is only used by the vbuf module (which is - * not normally used by default but used in testing). For the vbuf module, - * we basically want to pass-through the draw module's vertex layout as-is. - * When the llvmpipe vbuf code begins drawing, the normal vertex layout - * will come into play again. - */ -struct vertex_info * -llvmpipe_get_vbuf_vertex_info(struct llvmpipe_context *llvmpipe) -{ - (void) llvmpipe_get_vertex_info(llvmpipe); - return &llvmpipe->vertex_info_vbuf; -} - - -/** - * Recompute cliprect from scissor bounds, scissor enable and surface size. - */ -static void -compute_cliprect(struct llvmpipe_context *lp) -{ - /* LP_NEW_FRAMEBUFFER - */ - uint surfWidth = lp->framebuffer.width; - uint surfHeight = lp->framebuffer.height; - - /* LP_NEW_RASTERIZER - */ - if (lp->rasterizer->scissor) { - - /* LP_NEW_SCISSOR - * - * clip to scissor rect: - */ - lp->cliprect.minx = MAX2(lp->scissor.minx, 0); - lp->cliprect.miny = MAX2(lp->scissor.miny, 0); - lp->cliprect.maxx = MIN2(lp->scissor.maxx, surfWidth); - lp->cliprect.maxy = MIN2(lp->scissor.maxy, surfHeight); - } - else { - /* clip to surface bounds */ - lp->cliprect.minx = 0; - lp->cliprect.miny = 0; - lp->cliprect.maxx = surfWidth; - lp->cliprect.maxy = surfHeight; - } -} - - -/* Hopefully this will remain quite simple, otherwise need to pull in + * Hopefully this will remain quite simple, otherwise need to pull in * something like the state tracker mechanism. */ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe ) @@ -206,28 +153,40 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe ) llvmpipe->dirty |= LP_NEW_TEXTURE; } - if (llvmpipe->dirty & (LP_NEW_SAMPLER | - LP_NEW_TEXTURE)) { - /* TODO */ - } - if (llvmpipe->dirty & (LP_NEW_RASTERIZER | LP_NEW_FS | LP_NEW_VS)) - invalidate_vertex_layout( llvmpipe ); - - if (llvmpipe->dirty & (LP_NEW_SCISSOR | - LP_NEW_RASTERIZER | - LP_NEW_FRAMEBUFFER)) - compute_cliprect(llvmpipe); + compute_vertex_info( llvmpipe ); if (llvmpipe->dirty & (LP_NEW_FS | LP_NEW_BLEND | + LP_NEW_SCISSOR | LP_NEW_DEPTH_STENCIL_ALPHA | + LP_NEW_RASTERIZER | LP_NEW_SAMPLER | LP_NEW_TEXTURE)) llvmpipe_update_fs( llvmpipe ); + if (llvmpipe->dirty & LP_NEW_BLEND_COLOR) + lp_setup_set_blend_color(llvmpipe->setup, + &llvmpipe->blend_color); + + if (llvmpipe->dirty & LP_NEW_SCISSOR) + lp_setup_set_scissor(llvmpipe->setup, &llvmpipe->scissor); + + if (llvmpipe->dirty & LP_NEW_DEPTH_STENCIL_ALPHA) + lp_setup_set_alpha_ref_value(llvmpipe->setup, + llvmpipe->depth_stencil->alpha.ref_value); + + if (llvmpipe->dirty & LP_NEW_CONSTANTS) + lp_setup_set_fs_constants(llvmpipe->setup, + llvmpipe->constants[PIPE_SHADER_FRAGMENT]); + + if (llvmpipe->dirty & LP_NEW_TEXTURE) + lp_setup_set_sampler_textures(llvmpipe->setup, + llvmpipe->num_textures, + llvmpipe->texture); llvmpipe->dirty = 0; } + diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index b73ca2d41e..15c10d8e2e 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -31,6 +31,8 @@ * Code generate the whole fragment pipeline. * * The fragment pipeline consists of the following stages: + * - triangle edge in/out testing + * - scissor test * - stipple (TBI) * - early depth test * - fragment shader @@ -58,36 +60,39 @@ * @author Jose Fonseca <jfonseca@vmware.com> */ +#include <limits.h> #include "pipe/p_defines.h" +#include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_format.h" #include "util/u_debug_dump.h" -#include "pipe/internal/p_winsys_screen.h" +#include "os/os_time.h" #include "pipe/p_shader_tokens.h" #include "draw/draw_context.h" #include "tgsi/tgsi_dump.h" #include "tgsi/tgsi_scan.h" #include "tgsi/tgsi_parse.h" -#include "lp_bld_type.h" -#include "lp_bld_const.h" -#include "lp_bld_conv.h" -#include "lp_bld_intr.h" -#include "lp_bld_logic.h" -#include "lp_bld_depth.h" -#include "lp_bld_interp.h" -#include "lp_bld_tgsi.h" -#include "lp_bld_alpha.h" -#include "lp_bld_blend.h" -#include "lp_bld_swizzle.h" -#include "lp_bld_flow.h" -#include "lp_bld_debug.h" -#include "lp_screen.h" -#include "lp_context.h" +#include "gallivm/lp_bld_type.h" +#include "gallivm/lp_bld_const.h" +#include "gallivm/lp_bld_conv.h" +#include "gallivm/lp_bld_intr.h" +#include "gallivm/lp_bld_logic.h" +#include "gallivm/lp_bld_depth.h" +#include "gallivm/lp_bld_interp.h" +#include "gallivm/lp_bld_tgsi.h" +#include "gallivm/lp_bld_alpha.h" +#include "gallivm/lp_bld_blend.h" +#include "gallivm/lp_bld_swizzle.h" +#include "gallivm/lp_bld_flow.h" +#include "gallivm/lp_bld_debug.h" #include "lp_buffer.h" +#include "lp_context.h" +#include "lp_debug.h" +#include "lp_perf.h" +#include "lp_screen.h" +#include "lp_setup.h" #include "lp_state.h" -#include "lp_quad.h" #include "lp_tex_sample.h" -#include "lp_debug.h" static const unsigned char quad_offset_x[4] = {0, 1, 0, 1}; @@ -187,7 +192,187 @@ generate_depth(LLVMBuilderRef builder, /** + * Generate the code to do inside/outside triangle testing for the + * four pixels in a 2x2 quad. This will set the four elements of the + * quad mask vector to 0 or ~0. + * \param i which quad of the quad group to test, in [0,3] + */ +static void +generate_tri_edge_mask(LLVMBuilderRef builder, + unsigned i, + LLVMValueRef *mask, /* ivec4, out */ + LLVMValueRef c0, /* int32 */ + LLVMValueRef c1, /* int32 */ + LLVMValueRef c2, /* int32 */ + LLVMValueRef step0_ptr, /* ivec4 */ + LLVMValueRef step1_ptr, /* ivec4 */ + LLVMValueRef step2_ptr) /* ivec4 */ +{ +#define OPTIMIZE_IN_OUT_TEST 0 +#if OPTIMIZE_IN_OUT_TEST + struct lp_build_if_state ifctx; + LLVMValueRef not_draw_all; +#endif + struct lp_build_flow_context *flow; + struct lp_type i32_type; + LLVMTypeRef i32vec4_type, mask_type; + LLVMValueRef c0_vec, c1_vec, c2_vec; + LLVMValueRef in_out_mask; + + assert(i < 4); + + /* int32 vector type */ + memset(&i32_type, 0, sizeof i32_type); + i32_type.floating = FALSE; /* values are integers */ + i32_type.sign = TRUE; /* values are signed */ + i32_type.norm = FALSE; /* values are not normalized */ + i32_type.width = 32; /* 32-bit int values */ + i32_type.length = 4; /* 4 elements per vector */ + + i32vec4_type = lp_build_int32_vec4_type(); + + mask_type = LLVMIntType(32 * 4); + + /* + * Use a conditional here to do detailed pixel in/out testing. + * We only have to do this if c0 != INT_MIN. + */ + flow = lp_build_flow_create(builder); + lp_build_flow_scope_begin(flow); + + { +#if OPTIMIZE_IN_OUT_TEST + /* not_draw_all = (c0 != INT_MIN) */ + not_draw_all = LLVMBuildICmp(builder, + LLVMIntNE, + c0, + LLVMConstInt(LLVMInt32Type(), INT_MIN, 0), + ""); + + in_out_mask = lp_build_int_const_scalar(i32_type, ~0); + + + lp_build_flow_scope_declare(flow, &in_out_mask); + + /* if (not_draw_all) {... */ + lp_build_if(&ifctx, flow, builder, not_draw_all); +#endif + { + LLVMValueRef step0_vec, step1_vec, step2_vec; + LLVMValueRef m0_vec, m1_vec, m2_vec; + LLVMValueRef index, m; + + /* c0_vec = {c0, c0, c0, c0} + * Note that we emit this code four times but LLVM optimizes away + * three instances of it. + */ + c0_vec = lp_build_broadcast(builder, i32vec4_type, c0); + c1_vec = lp_build_broadcast(builder, i32vec4_type, c1); + c2_vec = lp_build_broadcast(builder, i32vec4_type, c2); + lp_build_name(c0_vec, "edgeconst0vec"); + lp_build_name(c1_vec, "edgeconst1vec"); + lp_build_name(c2_vec, "edgeconst2vec"); + + /* load step0vec, step1, step2 vec from memory */ + index = LLVMConstInt(LLVMInt32Type(), i, 0); + step0_vec = LLVMBuildLoad(builder, LLVMBuildGEP(builder, step0_ptr, &index, 1, ""), ""); + step1_vec = LLVMBuildLoad(builder, LLVMBuildGEP(builder, step1_ptr, &index, 1, ""), ""); + step2_vec = LLVMBuildLoad(builder, LLVMBuildGEP(builder, step2_ptr, &index, 1, ""), ""); + lp_build_name(step0_vec, "step0vec"); + lp_build_name(step1_vec, "step1vec"); + lp_build_name(step2_vec, "step2vec"); + + /* m0_vec = step0_ptr[i] > c0_vec */ + m0_vec = lp_build_compare(builder, i32_type, PIPE_FUNC_GREATER, step0_vec, c0_vec); + m1_vec = lp_build_compare(builder, i32_type, PIPE_FUNC_GREATER, step1_vec, c1_vec); + m2_vec = lp_build_compare(builder, i32_type, PIPE_FUNC_GREATER, step2_vec, c2_vec); + + /* in_out_mask = m0_vec & m1_vec & m2_vec */ + m = LLVMBuildAnd(builder, m0_vec, m1_vec, ""); + in_out_mask = LLVMBuildAnd(builder, m, m2_vec, ""); + lp_build_name(in_out_mask, "inoutmaskvec"); + } +#if OPTIMIZE_IN_OUT_TEST + lp_build_endif(&ifctx); +#endif + + } + lp_build_flow_scope_end(flow); + lp_build_flow_destroy(flow); + + /* This is the initial alive/dead pixel mask for a quad of four pixels. + * It's an int[4] vector with each word set to 0 or ~0. + * Words will get cleared when pixels faile the Z test, etc. + */ + *mask = in_out_mask; +} + + +static LLVMValueRef +generate_scissor_test(LLVMBuilderRef builder, + LLVMValueRef context_ptr, + const struct lp_build_interp_soa_context *interp, + struct lp_type type) +{ + LLVMTypeRef vec_type = lp_build_vec_type(type); + LLVMValueRef xpos = interp->pos[0], ypos = interp->pos[1]; + LLVMValueRef xmin, ymin, xmax, ymax; + LLVMValueRef m0, m1, m2, m3, m; + + /* xpos, ypos contain the window coords for the four pixels in the quad */ + assert(xpos); + assert(ypos); + + /* get the current scissor bounds, convert to vectors */ + xmin = lp_jit_context_scissor_xmin_value(builder, context_ptr); + xmin = lp_build_broadcast(builder, vec_type, xmin); + + ymin = lp_jit_context_scissor_ymin_value(builder, context_ptr); + ymin = lp_build_broadcast(builder, vec_type, ymin); + + xmax = lp_jit_context_scissor_xmax_value(builder, context_ptr); + xmax = lp_build_broadcast(builder, vec_type, xmax); + + ymax = lp_jit_context_scissor_ymax_value(builder, context_ptr); + ymax = lp_build_broadcast(builder, vec_type, ymax); + + /* compare the fragment's position coordinates against the scissor bounds */ + m0 = lp_build_compare(builder, type, PIPE_FUNC_GEQUAL, xpos, xmin); + m1 = lp_build_compare(builder, type, PIPE_FUNC_GEQUAL, ypos, ymin); + m2 = lp_build_compare(builder, type, PIPE_FUNC_LESS, xpos, xmax); + m3 = lp_build_compare(builder, type, PIPE_FUNC_LESS, ypos, ymax); + + /* AND all the masks together */ + m = LLVMBuildAnd(builder, m0, m1, ""); + m = LLVMBuildAnd(builder, m, m2, ""); + m = LLVMBuildAnd(builder, m, m3, ""); + + lp_build_name(m, "scissormask"); + + return m; +} + + +static LLVMValueRef +build_int32_vec_const(int value) +{ + struct lp_type i32_type; + + memset(&i32_type, 0, sizeof i32_type); + i32_type.floating = FALSE; /* values are integers */ + i32_type.sign = TRUE; /* values are signed */ + i32_type.norm = FALSE; /* values are not normalized */ + i32_type.width = 32; /* 32-bit int values */ + i32_type.length = 4; /* 4 elements per vector */ + return lp_build_int_const_scalar(i32_type, value); +} + + + +/** * Generate the fragment shader, depth/stencil test, and alpha tests. + * \param i which quad in the tile, in range [0,3] + * \param do_tri_test if 1, do triangle edge in/out testing */ static void generate_fs(struct llvmpipe_context *lp, @@ -200,8 +385,15 @@ generate_fs(struct llvmpipe_context *lp, const struct lp_build_interp_soa_context *interp, struct lp_build_sampler_soa *sampler, LLVMValueRef *pmask, - LLVMValueRef *color, - LLVMValueRef depth_ptr) + LLVMValueRef (*color)[4], + LLVMValueRef depth_ptr, + unsigned do_tri_test, + LLVMValueRef c0, + LLVMValueRef c1, + LLVMValueRef c2, + LLVMValueRef step0_ptr, + LLVMValueRef step1_ptr, + LLVMValueRef step2_ptr) { const struct tgsi_token *tokens = shader->base.tokens; LLVMTypeRef elem_type; @@ -215,6 +407,9 @@ generate_fs(struct llvmpipe_context *lp, boolean early_depth_test; unsigned attrib; unsigned chan; + unsigned cbuf; + + assert(i < 4); elem_type = lp_build_elem_type(type); vec_type = lp_build_vec_type(type); @@ -229,14 +424,32 @@ generate_fs(struct llvmpipe_context *lp, lp_build_flow_scope_begin(flow); /* Declare the color and z variables */ - for(chan = 0; chan < NUM_CHANNELS; ++chan) { - color[chan] = LLVMGetUndef(vec_type); - lp_build_flow_scope_declare(flow, &color[chan]); + for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) { + for(chan = 0; chan < NUM_CHANNELS; ++chan) { + color[cbuf][chan] = LLVMGetUndef(vec_type); + lp_build_flow_scope_declare(flow, &color[cbuf][chan]); + } } lp_build_flow_scope_declare(flow, &z); + /* do triangle edge testing */ + if (do_tri_test) { + generate_tri_edge_mask(builder, i, pmask, + c0, c1, c2, step0_ptr, step1_ptr, step2_ptr); + } + else { + *pmask = build_int32_vec_const(~0); + } + + /* 'mask' will control execution based on quad's pixel alive/killed state */ lp_build_mask_begin(&mask, flow, type, *pmask); + if (key->scissor) { + LLVMValueRef smask = + generate_scissor_test(builder, context_ptr, interp, type); + lp_build_mask_update(&mask, smask); + } + early_depth_test = key->depth.enabled && !key->alpha.enabled && @@ -255,19 +468,21 @@ generate_fs(struct llvmpipe_context *lp, for (attrib = 0; attrib < shader->info.num_outputs; ++attrib) { for(chan = 0; chan < NUM_CHANNELS; ++chan) { if(outputs[attrib][chan]) { - lp_build_name(outputs[attrib][chan], "output%u.%u.%c", i, attrib, "xyzw"[chan]); + LLVMValueRef out = LLVMBuildLoad(builder, outputs[attrib][chan], ""); + lp_build_name(out, "output%u.%u.%c", i, attrib, "xyzw"[chan]); switch (shader->info.output_semantic_name[attrib]) { case TGSI_SEMANTIC_COLOR: { unsigned cbuf = shader->info.output_semantic_index[attrib]; - lp_build_name(outputs[attrib][chan], "color%u.%u.%c", i, attrib, "rgba"[chan]); + lp_build_name(out, "color%u.%u.%c", i, attrib, "rgba"[chan]); /* Alpha test */ /* XXX: should the alpha reference value be passed separately? */ + /* XXX: should only test the final assignment to alpha */ if(cbuf == 0 && chan == 3) { - LLVMValueRef alpha = outputs[attrib][chan]; + LLVMValueRef alpha = out; LLVMValueRef alpha_ref_value; alpha_ref_value = lp_jit_context_alpha_ref_value(builder, context_ptr); alpha_ref_value = lp_build_broadcast(builder, vec_type, alpha_ref_value); @@ -275,15 +490,13 @@ generate_fs(struct llvmpipe_context *lp, &mask, alpha, alpha_ref_value); } - if(cbuf == 0) - color[chan] = outputs[attrib][chan]; - + color[cbuf][chan] = out; break; } case TGSI_SEMANTIC_POSITION: if(chan == 2) - z = outputs[attrib][chan]; + z = out; break; } } @@ -332,6 +545,8 @@ generate_blend(const struct pipe_blend_state *blend, lp_build_context_init(&bld, builder, type); flow = lp_build_flow_create(builder); + + /* we'll use this mask context to skip blending if all pixels are dead */ lp_build_mask_begin(&mask_ctx, flow, type, mask); vec_type = lp_build_vec_type(type); @@ -354,7 +569,7 @@ generate_blend(const struct pipe_blend_state *blend, lp_build_blend_soa(builder, blend, type, src, dst, con, res); for(chan = 0; chan < 4; ++chan) { - if(blend->colormask & (1 << chan)) { + if(blend->rt[0].colormask & (1 << chan)) { LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), chan, 0); lp_build_name(res[chan], "res.%c", "rgba"[chan]); res[chan] = lp_build_select(&bld, mask, res[chan], dst[chan]); @@ -369,14 +584,18 @@ generate_blend(const struct pipe_blend_state *blend, /** * Generate the runtime callable function for the whole fragment pipeline. + * Note that the function which we generate operates on a block of 16 + * pixels at at time. The block contains 2x2 quads. Each quad contains + * 2x2 pixels. */ -static struct lp_fragment_shader_variant * +static void generate_fragment(struct llvmpipe_context *lp, struct lp_fragment_shader *shader, - const struct lp_fragment_shader_variant_key *key) + struct lp_fragment_shader_variant *variant, + unsigned do_tri_test) { struct llvmpipe_screen *screen = llvmpipe_screen(lp->pipe.screen); - struct lp_fragment_shader_variant *variant; + const struct lp_fragment_shader_variant_key *key = &variant->key; struct lp_type fs_type; struct lp_type blend_type; LLVMTypeRef fs_elem_type; @@ -384,17 +603,18 @@ generate_fragment(struct llvmpipe_context *lp, LLVMTypeRef fs_int_vec_type; LLVMTypeRef blend_vec_type; LLVMTypeRef blend_int_vec_type; - LLVMTypeRef arg_types[9]; + LLVMTypeRef arg_types[14]; LLVMTypeRef func_type; + LLVMTypeRef int32_vec4_type = lp_build_int32_vec4_type(); LLVMValueRef context_ptr; LLVMValueRef x; LLVMValueRef y; LLVMValueRef a0_ptr; LLVMValueRef dadx_ptr; LLVMValueRef dady_ptr; - LLVMValueRef mask_ptr; - LLVMValueRef color_ptr; + LLVMValueRef color_ptr_ptr; LLVMValueRef depth_ptr; + LLVMValueRef c0, c1, c2, step0_ptr, step1_ptr, step2_ptr; LLVMBasicBlockRef block; LLVMBuilderRef builder; LLVMValueRef x0; @@ -402,71 +622,15 @@ generate_fragment(struct llvmpipe_context *lp, struct lp_build_sampler_soa *sampler; struct lp_build_interp_soa_context interp; LLVMValueRef fs_mask[LP_MAX_VECTOR_LENGTH]; - LLVMValueRef fs_out_color[NUM_CHANNELS][LP_MAX_VECTOR_LENGTH]; + LLVMValueRef fs_out_color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS][LP_MAX_VECTOR_LENGTH]; LLVMValueRef blend_mask; LLVMValueRef blend_in_color[NUM_CHANNELS]; + LLVMValueRef function; unsigned num_fs; unsigned i; unsigned chan; + unsigned cbuf; - if (LP_DEBUG & DEBUG_JIT) { - tgsi_dump(shader->base.tokens, 0); - if(key->depth.enabled) { - debug_printf("depth.format = %s\n", pf_name(key->zsbuf_format)); - debug_printf("depth.func = %s\n", debug_dump_func(key->depth.func, TRUE)); - debug_printf("depth.writemask = %u\n", key->depth.writemask); - } - if(key->alpha.enabled) { - debug_printf("alpha.func = %s\n", debug_dump_func(key->alpha.func, TRUE)); - debug_printf("alpha.ref_value = %f\n", key->alpha.ref_value); - } - if(key->blend.logicop_enable) { - debug_printf("blend.logicop_func = %u\n", key->blend.logicop_func); - } - else if(key->blend.blend_enable) { - debug_printf("blend.rgb_func = %s\n", debug_dump_blend_func (key->blend.rgb_func, TRUE)); - debug_printf("rgb_src_factor = %s\n", debug_dump_blend_factor(key->blend.rgb_src_factor, TRUE)); - debug_printf("rgb_dst_factor = %s\n", debug_dump_blend_factor(key->blend.rgb_dst_factor, TRUE)); - debug_printf("alpha_func = %s\n", debug_dump_blend_func (key->blend.alpha_func, TRUE)); - debug_printf("alpha_src_factor = %s\n", debug_dump_blend_factor(key->blend.alpha_src_factor, TRUE)); - debug_printf("alpha_dst_factor = %s\n", debug_dump_blend_factor(key->blend.alpha_dst_factor, TRUE)); - } - debug_printf("blend.colormask = 0x%x\n", key->blend.colormask); - for(i = 0; i < PIPE_MAX_SAMPLERS; ++i) { - if(key->sampler[i].format) { - debug_printf("sampler[%u] = \n", i); - debug_printf(" .format = %s\n", - pf_name(key->sampler[i].format)); - debug_printf(" .target = %s\n", - debug_dump_tex_target(key->sampler[i].target, TRUE)); - debug_printf(" .pot = %u %u %u\n", - key->sampler[i].pot_width, - key->sampler[i].pot_height, - key->sampler[i].pot_depth); - debug_printf(" .wrap = %s %s %s\n", - debug_dump_tex_wrap(key->sampler[i].wrap_s, TRUE), - debug_dump_tex_wrap(key->sampler[i].wrap_t, TRUE), - debug_dump_tex_wrap(key->sampler[i].wrap_r, TRUE)); - debug_printf(" .min_img_filter = %s\n", - debug_dump_tex_filter(key->sampler[i].min_img_filter, TRUE)); - debug_printf(" .min_mip_filter = %s\n", - debug_dump_tex_mipfilter(key->sampler[i].min_mip_filter, TRUE)); - debug_printf(" .mag_img_filter = %s\n", - debug_dump_tex_filter(key->sampler[i].mag_img_filter, TRUE)); - if(key->sampler[i].compare_mode != PIPE_TEX_COMPARE_NONE) - debug_printf(" .compare_func = %s\n", debug_dump_func(key->sampler[i].compare_func, TRUE)); - debug_printf(" .normalized_coords = %u\n", key->sampler[i].normalized_coords); - debug_printf(" .prefilter = %u\n", key->sampler[i].prefilter); - } - } - } - - variant = CALLOC_STRUCT(lp_fragment_shader_variant); - if(!variant) - return NULL; - - variant->shader = shader; - memcpy(&variant->key, key, sizeof *key); /* TODO: actually pick these based on the fs and color buffer * characteristics. */ @@ -476,8 +640,8 @@ generate_fragment(struct llvmpipe_context *lp, fs_type.sign = TRUE; /* values are signed */ fs_type.norm = FALSE; /* values are not limited to [0,1] or [-1,1] */ fs_type.width = 32; /* 32-bit float */ - fs_type.length = 4; /* 4 element per vector */ - num_fs = 4; + fs_type.length = 4; /* 4 elements per vector */ + num_fs = 4; /* number of quads per block */ memset(&blend_type, 0, sizeof blend_type); blend_type.floating = FALSE; /* values are integers */ @@ -504,27 +668,47 @@ generate_fragment(struct llvmpipe_context *lp, arg_types[3] = LLVMPointerType(fs_elem_type, 0); /* a0 */ arg_types[4] = LLVMPointerType(fs_elem_type, 0); /* dadx */ arg_types[5] = LLVMPointerType(fs_elem_type, 0); /* dady */ - arg_types[6] = LLVMPointerType(fs_int_vec_type, 0); /* mask */ - arg_types[7] = LLVMPointerType(blend_vec_type, 0); /* color */ - arg_types[8] = LLVMPointerType(fs_int_vec_type, 0); /* depth */ + arg_types[6] = LLVMPointerType(LLVMPointerType(blend_vec_type, 0), 0); /* color */ + arg_types[7] = LLVMPointerType(fs_int_vec_type, 0); /* depth */ + arg_types[8] = LLVMInt32Type(); /* c0 */ + arg_types[9] = LLVMInt32Type(); /* c1 */ + arg_types[10] = LLVMInt32Type(); /* c2 */ + /* Note: the step arrays are built as int32[16] but we interpret + * them here as int32_vec4[4]. + */ + arg_types[11] = LLVMPointerType(int32_vec4_type, 0);/* step0 */ + arg_types[12] = LLVMPointerType(int32_vec4_type, 0);/* step1 */ + arg_types[13] = LLVMPointerType(int32_vec4_type, 0);/* step2 */ func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0); - variant->function = LLVMAddFunction(screen->module, "shader", func_type); - LLVMSetFunctionCallConv(variant->function, LLVMCCallConv); + function = LLVMAddFunction(screen->module, "shader", func_type); + LLVMSetFunctionCallConv(function, LLVMCCallConv); + + variant->function[do_tri_test] = function; + + + /* XXX: need to propagate noalias down into color param now we are + * passing a pointer-to-pointer? + */ for(i = 0; i < Elements(arg_types); ++i) if(LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind) - LLVMAddAttribute(LLVMGetParam(variant->function, i), LLVMNoAliasAttribute); - - context_ptr = LLVMGetParam(variant->function, 0); - x = LLVMGetParam(variant->function, 1); - y = LLVMGetParam(variant->function, 2); - a0_ptr = LLVMGetParam(variant->function, 3); - dadx_ptr = LLVMGetParam(variant->function, 4); - dady_ptr = LLVMGetParam(variant->function, 5); - mask_ptr = LLVMGetParam(variant->function, 6); - color_ptr = LLVMGetParam(variant->function, 7); - depth_ptr = LLVMGetParam(variant->function, 8); + LLVMAddAttribute(LLVMGetParam(function, i), LLVMNoAliasAttribute); + + context_ptr = LLVMGetParam(function, 0); + x = LLVMGetParam(function, 1); + y = LLVMGetParam(function, 2); + a0_ptr = LLVMGetParam(function, 3); + dadx_ptr = LLVMGetParam(function, 4); + dady_ptr = LLVMGetParam(function, 5); + color_ptr_ptr = LLVMGetParam(function, 6); + depth_ptr = LLVMGetParam(function, 7); + c0 = LLVMGetParam(function, 8); + c1 = LLVMGetParam(function, 9); + c2 = LLVMGetParam(function, 10); + step0_ptr = LLVMGetParam(function, 11); + step1_ptr = LLVMGetParam(function, 12); + step2_ptr = LLVMGetParam(function, 13); lp_build_name(context_ptr, "context"); lp_build_name(x, "x"); @@ -532,36 +716,45 @@ generate_fragment(struct llvmpipe_context *lp, lp_build_name(a0_ptr, "a0"); lp_build_name(dadx_ptr, "dadx"); lp_build_name(dady_ptr, "dady"); - lp_build_name(mask_ptr, "mask"); - lp_build_name(color_ptr, "color"); + lp_build_name(color_ptr_ptr, "color_ptr"); lp_build_name(depth_ptr, "depth"); + lp_build_name(c0, "c0"); + lp_build_name(c1, "c1"); + lp_build_name(c2, "c2"); + lp_build_name(step0_ptr, "step0"); + lp_build_name(step1_ptr, "step1"); + lp_build_name(step2_ptr, "step2"); /* * Function body */ - block = LLVMAppendBasicBlock(variant->function, "entry"); + block = LLVMAppendBasicBlock(function, "entry"); builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, block); generate_pos0(builder, x, y, &x0, &y0); - lp_build_interp_soa_init(&interp, shader->base.tokens, builder, fs_type, + lp_build_interp_soa_init(&interp, + shader->base.tokens, + key->flatshade, + builder, fs_type, a0_ptr, dadx_ptr, dady_ptr, - x0, y0, 2, 0); + x0, y0); /* code generated texture sampling */ sampler = lp_llvm_sampler_soa_create(key->sampler, context_ptr); + /* loop over quads in the block */ for(i = 0; i < num_fs; ++i) { LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0); - LLVMValueRef out_color[NUM_CHANNELS]; + LLVMValueRef out_color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS]; LLVMValueRef depth_ptr_i; + int cbuf; if(i != 0) - lp_build_interp_soa_update(&interp); + lp_build_interp_soa_update(&interp, i); - fs_mask[i] = LLVMBuildLoad(builder, LLVMBuildGEP(builder, mask_ptr, &index, 1, ""), ""); depth_ptr_i = LLVMBuildGEP(builder, depth_ptr, &index, 1, ""); generate_fs(lp, shader, key, @@ -571,71 +764,162 @@ generate_fragment(struct llvmpipe_context *lp, i, &interp, sampler, - &fs_mask[i], + &fs_mask[i], /* output */ out_color, - depth_ptr_i); - - for(chan = 0; chan < NUM_CHANNELS; ++chan) - fs_out_color[chan][i] = out_color[chan]; + depth_ptr_i, + do_tri_test, + c0, c1, c2, + step0_ptr, step1_ptr, step2_ptr); + + for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) + for(chan = 0; chan < NUM_CHANNELS; ++chan) + fs_out_color[cbuf][chan][i] = out_color[cbuf][chan]; } sampler->destroy(sampler); - /* - * Convert the fs's output color and mask to fit to the blending type. + /* Loop over color outputs / color buffers to do blending. */ + for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) { + LLVMValueRef color_ptr; + LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), cbuf, 0); - for(chan = 0; chan < NUM_CHANNELS; ++chan) { - lp_build_conv(builder, fs_type, blend_type, - fs_out_color[chan], num_fs, - &blend_in_color[chan], 1); - lp_build_name(blend_in_color[chan], "color.%c", "rgba"[chan]); + /* + * Convert the fs's output color and mask to fit to the blending type. + */ + for(chan = 0; chan < NUM_CHANNELS; ++chan) { + lp_build_conv(builder, fs_type, blend_type, + fs_out_color[cbuf][chan], num_fs, + &blend_in_color[chan], 1); + lp_build_name(blend_in_color[chan], "color%d.%c", cbuf, "rgba"[chan]); + } + lp_build_conv_mask(builder, fs_type, blend_type, + fs_mask, num_fs, + &blend_mask, 1); + + color_ptr = LLVMBuildLoad(builder, + LLVMBuildGEP(builder, color_ptr_ptr, &index, 1, ""), + ""); + lp_build_name(color_ptr, "color_ptr%d", cbuf); + + /* + * Blending. + */ + generate_blend(&key->blend, + builder, + blend_type, + context_ptr, + blend_mask, + blend_in_color, + color_ptr); } - lp_build_conv_mask(builder, fs_type, blend_type, - fs_mask, num_fs, - &blend_mask, 1); - - /* - * Blending. - */ - - generate_blend(&key->blend, - builder, - blend_type, - context_ptr, - blend_mask, - blend_in_color, - color_ptr); - LLVMBuildRetVoid(builder); LLVMDisposeBuilder(builder); - /* - * Translate the LLVM IR into machine code. - */ + /* Verify the LLVM IR. If invalid, dump and abort */ #ifdef DEBUG - if(LLVMVerifyFunction(variant->function, LLVMPrintMessageAction)) { - LLVMDumpValue(variant->function); - assert(0); + if(LLVMVerifyFunction(function, LLVMPrintMessageAction)) { + if (1) + LLVMDumpValue(function); + abort(); } #endif - LLVMRunFunctionPassManager(screen->pass, variant->function); + /* Apply optimizations to LLVM IR */ + if (1) + LLVMRunFunctionPassManager(screen->pass, function); if (LP_DEBUG & DEBUG_JIT) { - LLVMDumpValue(variant->function); + /* Print the LLVM IR to stderr */ + LLVMDumpValue(function); debug_printf("\n"); } - variant->jit_function = (lp_jit_frag_func)LLVMGetPointerToGlobal(screen->engine, variant->function); + /* + * Translate the LLVM IR into machine code. + */ + variant->jit_function[do_tri_test] = (lp_jit_frag_func)LLVMGetPointerToGlobal(screen->engine, function); if (LP_DEBUG & DEBUG_ASM) - lp_disassemble(variant->jit_function); + lp_disassemble(variant->jit_function[do_tri_test]); +} + + +static struct lp_fragment_shader_variant * +generate_variant(struct llvmpipe_context *lp, + struct lp_fragment_shader *shader, + const struct lp_fragment_shader_variant_key *key) +{ + struct lp_fragment_shader_variant *variant; + + if (LP_DEBUG & DEBUG_JIT) { + unsigned i; + tgsi_dump(shader->base.tokens, 0); + if(key->depth.enabled) { + debug_printf("depth.format = %s\n", pf_name(key->zsbuf_format)); + debug_printf("depth.func = %s\n", debug_dump_func(key->depth.func, TRUE)); + debug_printf("depth.writemask = %u\n", key->depth.writemask); + } + if(key->alpha.enabled) { + debug_printf("alpha.func = %s\n", debug_dump_func(key->alpha.func, TRUE)); + debug_printf("alpha.ref_value = %f\n", key->alpha.ref_value); + } + if(key->blend.logicop_enable) { + debug_printf("blend.logicop_func = %u\n", key->blend.logicop_func); + } + else if(key->blend.rt[0].blend_enable) { + debug_printf("blend.rgb_func = %s\n", debug_dump_blend_func (key->blend.rt[0].rgb_func, TRUE)); + debug_printf("rgb_src_factor = %s\n", debug_dump_blend_factor(key->blend.rt[0].rgb_src_factor, TRUE)); + debug_printf("rgb_dst_factor = %s\n", debug_dump_blend_factor(key->blend.rt[0].rgb_dst_factor, TRUE)); + debug_printf("alpha_func = %s\n", debug_dump_blend_func (key->blend.rt[0].alpha_func, TRUE)); + debug_printf("alpha_src_factor = %s\n", debug_dump_blend_factor(key->blend.rt[0].alpha_src_factor, TRUE)); + debug_printf("alpha_dst_factor = %s\n", debug_dump_blend_factor(key->blend.rt[0].alpha_dst_factor, TRUE)); + } + debug_printf("blend.colormask = 0x%x\n", key->blend.rt[0].colormask); + for(i = 0; i < PIPE_MAX_SAMPLERS; ++i) { + if(key->sampler[i].format) { + debug_printf("sampler[%u] = \n", i); + debug_printf(" .format = %s\n", + pf_name(key->sampler[i].format)); + debug_printf(" .target = %s\n", + debug_dump_tex_target(key->sampler[i].target, TRUE)); + debug_printf(" .pot = %u %u %u\n", + key->sampler[i].pot_width, + key->sampler[i].pot_height, + key->sampler[i].pot_depth); + debug_printf(" .wrap = %s %s %s\n", + debug_dump_tex_wrap(key->sampler[i].wrap_s, TRUE), + debug_dump_tex_wrap(key->sampler[i].wrap_t, TRUE), + debug_dump_tex_wrap(key->sampler[i].wrap_r, TRUE)); + debug_printf(" .min_img_filter = %s\n", + debug_dump_tex_filter(key->sampler[i].min_img_filter, TRUE)); + debug_printf(" .min_mip_filter = %s\n", + debug_dump_tex_mipfilter(key->sampler[i].min_mip_filter, TRUE)); + debug_printf(" .mag_img_filter = %s\n", + debug_dump_tex_filter(key->sampler[i].mag_img_filter, TRUE)); + if(key->sampler[i].compare_mode != PIPE_TEX_COMPARE_NONE) + debug_printf(" .compare_func = %s\n", debug_dump_func(key->sampler[i].compare_func, TRUE)); + debug_printf(" .normalized_coords = %u\n", key->sampler[i].normalized_coords); + } + } + } + + variant = CALLOC_STRUCT(lp_fragment_shader_variant); + if(!variant) + return NULL; + + variant->shader = shader; + memcpy(&variant->key, key, sizeof *key); + + generate_fragment(lp, shader, variant, 0); + generate_fragment(lp, shader, variant, 1); + + /* insert new variant into linked list */ variant->next = shader->variants; shader->variants = variant; @@ -693,11 +977,15 @@ llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs) variant = shader->variants; while(variant) { struct lp_fragment_shader_variant *next = variant->next; - - if(variant->function) { - if(variant->jit_function) - LLVMFreeMachineCodeForFunction(screen->engine, variant->function); - LLVMDeleteFunction(variant->function); + unsigned i; + + for (i = 0; i < Elements(variant->function); i++) { + if (variant->function[i]) { + if (variant->jit_function[i]) + LLVMFreeMachineCodeForFunction(screen->engine, + variant->function[i]); + LLVMDeleteFunction(variant->function[i]); + } } FREE(variant); @@ -714,27 +1002,25 @@ llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs) void llvmpipe_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - const struct pipe_constant_buffer *constants) + struct pipe_buffer *constants) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); - struct pipe_buffer *buffer = constants ? constants->buffer : NULL; - unsigned size = buffer ? buffer->size : 0; - const void *data = buffer ? llvmpipe_buffer(buffer)->data : NULL; + unsigned size = constants ? constants->size : 0; + const void *data = constants ? llvmpipe_buffer(constants)->data : NULL; assert(shader < PIPE_SHADER_TYPES); assert(index == 0); + if(llvmpipe->constants[shader] == constants) + return; + draw_flush(llvmpipe->draw); /* note: reference counting */ - pipe_buffer_reference(&llvmpipe->constants[shader].buffer, buffer); - - if(shader == PIPE_SHADER_FRAGMENT) { - llvmpipe->jit_context.constants = data; - } + pipe_buffer_reference(&llvmpipe->constants[shader], constants); if(shader == PIPE_SHADER_VERTEX) { - draw_set_mapped_constant_buffer(llvmpipe->draw, PIPE_SHADER_VERTEX, + draw_set_mapped_constant_buffer(llvmpipe->draw, PIPE_SHADER_VERTEX, 0, data, size); } @@ -769,21 +1055,30 @@ make_variant_key(struct llvmpipe_context *lp, key->alpha.func = lp->depth_stencil->alpha.func; /* alpha.ref_value is passed in jit_context */ - if(lp->framebuffer.cbufs[0]) { - const struct util_format_description *format_desc; - unsigned chan; + key->flatshade = lp->rasterizer->flatshade; + key->scissor = lp->rasterizer->scissor; + if (lp->framebuffer.nr_cbufs) { memcpy(&key->blend, lp->blend, sizeof key->blend); + } - format_desc = util_format_description(lp->framebuffer.cbufs[0]->format); + key->nr_cbufs = lp->framebuffer.nr_cbufs; + for (i = 0; i < lp->framebuffer.nr_cbufs; i++) { + const struct util_format_description *format_desc; + unsigned chan; + + format_desc = util_format_description(lp->framebuffer.cbufs[i]->format); assert(format_desc->layout == UTIL_FORMAT_COLORSPACE_RGB || format_desc->layout == UTIL_FORMAT_COLORSPACE_SRGB); - /* mask out color channels not present in the color buffer */ + /* mask out color channels not present in the color buffer. + * Should be simple to incorporate per-cbuf writemasks: + */ for(chan = 0; chan < 4; ++chan) { enum util_format_swizzle swizzle = format_desc->swizzle[chan]; - if(swizzle > 4) - key->blend.colormask &= ~(1 << chan); + + if(swizzle <= UTIL_FORMAT_SWIZZLE_W) + key->blend.rt[0].colormask |= (1 << chan); } } @@ -793,12 +1088,17 @@ make_variant_key(struct llvmpipe_context *lp, } +/** + * Update fragment state. This is called just prior to drawing + * something when some fragment-related state has changed. + */ void llvmpipe_update_fs(struct llvmpipe_context *lp) { struct lp_fragment_shader *shader = lp->fs; struct lp_fragment_shader_variant_key key; struct lp_fragment_shader_variant *variant; + boolean opaque; make_variant_key(lp, shader, &key); @@ -810,8 +1110,34 @@ llvmpipe_update_fs(struct llvmpipe_context *lp) variant = variant->next; } - if(!variant) - variant = generate_fragment(lp, shader, &key); + if (!variant) { + int64_t t0, t1; + int64_t dt; + t0 = os_time_get(); + + variant = generate_variant(lp, shader, &key); + + t1 = os_time_get(); + dt = t1 - t0; + LP_COUNT_ADD(llvm_compile_time, dt); + LP_COUNT_ADD(nr_llvm_compiles, 2); /* emit vs. omit in/out test */ + } shader->current = variant; + + /* TODO: put this in the variant */ + /* TODO: most of these can be relaxed, in particular the colormask */ + opaque = !key.blend.logicop_enable && + !key.blend.rt[0].blend_enable && + key.blend.rt[0].colormask == 0xf && + !key.alpha.enabled && + !key.depth.enabled && + !key.scissor && + !shader->info.uses_kill + ? TRUE : FALSE; + + lp_setup_set_fs_functions(lp->setup, + shader->current->jit_function[0], + shader->current->jit_function[1], + opaque); } diff --git a/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c index aa3b5a3f91..feb012816c 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c +++ b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c @@ -29,6 +29,7 @@ #include "util/u_memory.h" #include "lp_context.h" #include "lp_state.h" +#include "lp_setup.h" #include "draw/draw_context.h" @@ -53,6 +54,17 @@ void llvmpipe_bind_rasterizer_state(struct pipe_context *pipe, llvmpipe->rasterizer = rasterizer; + /* Note: we can immediately set the triangle state here and + * not worry about binning because we handle culling during + * triangle setup, not when rasterizing the bins. + */ + if (llvmpipe->rasterizer) { + lp_setup_set_triangle_state( llvmpipe->setup, + llvmpipe->rasterizer->cull_mode, + llvmpipe->rasterizer->front_winding == PIPE_WINDING_CCW, + llvmpipe->rasterizer->scissor); + } + llvmpipe->dirty |= LP_NEW_RASTERIZER; } diff --git a/src/gallium/drivers/llvmpipe/lp_state_sampler.c b/src/gallium/drivers/llvmpipe/lp_state_sampler.c index d382f9ca87..b30a075776 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_sampler.c +++ b/src/gallium/drivers/llvmpipe/lp_state_sampler.c @@ -29,6 +29,7 @@ * Brian Paul */ +#include "util/u_inlines.h" #include "util/u_memory.h" #include "draw/draw_context.h" @@ -36,8 +37,6 @@ #include "lp_context.h" #include "lp_context.h" #include "lp_state.h" -#include "lp_texture.h" -#include "lp_tex_cache.h" #include "draw/draw_context.h" @@ -125,17 +124,6 @@ llvmpipe_set_sampler_textures(struct pipe_context *pipe, struct pipe_texture *tex = i < num ? texture[i] : NULL; pipe_texture_reference(&llvmpipe->texture[i], tex); - lp_tex_tile_cache_set_texture(llvmpipe->tex_cache[i], tex); - - if(tex) { - struct llvmpipe_texture *lp_tex = llvmpipe_texture(tex); - struct lp_jit_texture *jit_tex = &llvmpipe->jit_context.textures[i]; - jit_tex->width = tex->width0; - jit_tex->height = tex->height0; - jit_tex->stride = lp_tex->stride[0]; - if(!lp_tex->dt) - jit_tex->data = lp_tex->data; - } } llvmpipe->num_textures = num; @@ -166,7 +154,6 @@ llvmpipe_set_vertex_sampler_textures(struct pipe_context *pipe, struct pipe_texture *tex = i < num_textures ? textures[i] : NULL; pipe_texture_reference(&llvmpipe->vertex_textures[i], tex); - lp_tex_tile_cache_set_texture(llvmpipe->vertex_tex_cache[i], tex); } llvmpipe->num_vertex_textures = num_textures; diff --git a/src/gallium/drivers/llvmpipe/lp_state_surface.c b/src/gallium/drivers/llvmpipe/lp_state_surface.c index e37ff04f3d..048ac5b968 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_surface.c +++ b/src/gallium/drivers/llvmpipe/lp_state_surface.c @@ -28,10 +28,12 @@ /* Authors: Keith Whitwell <keith@tungstengraphics.com> */ +#include "pipe/p_state.h" +#include "util/u_inlines.h" +#include "util/u_surface.h" #include "lp_context.h" #include "lp_state.h" -#include "lp_surface.h" -#include "lp_tile_cache.h" +#include "lp_setup.h" #include "draw/draw_context.h" @@ -39,54 +41,19 @@ /** - * XXX this might get moved someday * Set the framebuffer surface info: color buffers, zbuffer, stencil buffer. - * Here, we flush the old surfaces and update the tile cache to point to the new - * surfaces. */ void llvmpipe_set_framebuffer_state(struct pipe_context *pipe, const struct pipe_framebuffer_state *fb) { struct llvmpipe_context *lp = llvmpipe_context(pipe); - uint i; - draw_flush(lp->draw); + boolean changed = !util_framebuffer_state_equal(&lp->framebuffer, fb); - for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { - /* check if changing cbuf */ - if (lp->framebuffer.cbufs[i] != fb->cbufs[i]) { - /* flush old */ - lp_tile_cache_map_transfers(lp->cbuf_cache[i]); - lp_flush_tile_cache(lp->cbuf_cache[i]); + if (changed) { - /* assign new */ - pipe_surface_reference(&lp->framebuffer.cbufs[i], fb->cbufs[i]); - - /* update cache */ - lp_tile_cache_set_surface(lp->cbuf_cache[i], fb->cbufs[i]); - } - } - - lp->framebuffer.nr_cbufs = fb->nr_cbufs; - - /* zbuf changing? */ - if (lp->framebuffer.zsbuf != fb->zsbuf) { - - if(lp->zsbuf_transfer) { - struct pipe_screen *screen = pipe->screen; - - if(lp->zsbuf_map) { - screen->transfer_unmap(screen, lp->zsbuf_transfer); - lp->zsbuf_map = NULL; - } - - screen->tex_transfer_destroy(lp->zsbuf_transfer); - lp->zsbuf_transfer = NULL; - } - - /* assign new */ - pipe_surface_reference(&lp->framebuffer.zsbuf, fb->zsbuf); + util_copy_framebuffer_state(&lp->framebuffer, fb); /* Tell draw module how deep the Z/depth buffer is */ if (lp->framebuffer.zsbuf) { @@ -103,10 +70,9 @@ llvmpipe_set_framebuffer_state(struct pipe_context *pipe, } draw_set_mrd(lp->draw, mrd); } - } - lp->framebuffer.width = fb->width; - lp->framebuffer.height = fb->height; + lp_setup_bind_framebuffer( lp->setup, &lp->framebuffer ); - lp->dirty |= LP_NEW_FRAMEBUFFER; + lp->dirty |= LP_NEW_FRAMEBUFFER; + } } diff --git a/src/gallium/drivers/llvmpipe/lp_state_vertex.c b/src/gallium/drivers/llvmpipe/lp_state_vertex.c index 1a17631a4c..57ac25ea0c 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_vertex.c +++ b/src/gallium/drivers/llvmpipe/lp_state_vertex.c @@ -31,7 +31,6 @@ #include "lp_context.h" #include "lp_state.h" -#include "lp_surface.h" #include "draw/draw_context.h" diff --git a/src/gallium/drivers/llvmpipe/lp_test.h b/src/gallium/drivers/llvmpipe/lp_test.h index 39d80726e6..ca0f737b29 100644 --- a/src/gallium/drivers/llvmpipe/lp_test.h +++ b/src/gallium/drivers/llvmpipe/lp_test.h @@ -53,7 +53,7 @@ #include "util/u_math.h" #include "util/u_debug_dump.h" -#include "lp_bld_type.h" +#include "gallivm/lp_bld_type.h" #define LP_TEST_NUM_SAMPLES 32 diff --git a/src/gallium/drivers/llvmpipe/lp_test_blend.c b/src/gallium/drivers/llvmpipe/lp_test_blend.c index 29fff91981..e49b705598 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_blend.c +++ b/src/gallium/drivers/llvmpipe/lp_test_blend.c @@ -37,10 +37,9 @@ */ -#include "lp_bld_type.h" -#include "lp_bld_arit.h" -#include "lp_bld_blend.h" -#include "lp_bld_debug.h" +#include "gallivm/lp_bld_type.h" +#include "gallivm/lp_bld_blend.h" +#include "gallivm/lp_bld_debug.h" #include "lp_test.h" @@ -104,18 +103,18 @@ write_tsv_row(FILE *fp, fprintf(fp, "%s\t%s\t%s\t", - blend->rgb_func != blend->alpha_func ? "true" : "false", - blend->rgb_src_factor != blend->alpha_src_factor ? "true" : "false", - blend->rgb_dst_factor != blend->alpha_dst_factor ? "true" : "false"); + blend->rt[0].rgb_func != blend->rt[0].alpha_func ? "true" : "false", + blend->rt[0].rgb_src_factor != blend->rt[0].alpha_src_factor ? "true" : "false", + blend->rt[0].rgb_dst_factor != blend->rt[0].alpha_dst_factor ? "true" : "false"); fprintf(fp, "%s\t%s\t%s\t%s\t%s\t%s\n", - debug_dump_blend_func(blend->rgb_func, TRUE), - debug_dump_blend_factor(blend->rgb_src_factor, TRUE), - debug_dump_blend_factor(blend->rgb_dst_factor, TRUE), - debug_dump_blend_func(blend->alpha_func, TRUE), - debug_dump_blend_factor(blend->alpha_src_factor, TRUE), - debug_dump_blend_factor(blend->alpha_dst_factor, TRUE)); + debug_dump_blend_func(blend->rt[0].rgb_func, TRUE), + debug_dump_blend_factor(blend->rt[0].rgb_src_factor, TRUE), + debug_dump_blend_factor(blend->rt[0].rgb_dst_factor, TRUE), + debug_dump_blend_func(blend->rt[0].alpha_func, TRUE), + debug_dump_blend_factor(blend->rt[0].alpha_src_factor, TRUE), + debug_dump_blend_factor(blend->rt[0].alpha_dst_factor, TRUE)); fflush(fp); } @@ -137,12 +136,12 @@ dump_blend_type(FILE *fp, fprintf(fp, " %s=%s %s=%s %s=%s %s=%s %s=%s %s=%s", - "rgb_func", debug_dump_blend_func(blend->rgb_func, TRUE), - "rgb_src_factor", debug_dump_blend_factor(blend->rgb_src_factor, TRUE), - "rgb_dst_factor", debug_dump_blend_factor(blend->rgb_dst_factor, TRUE), - "alpha_func", debug_dump_blend_func(blend->alpha_func, TRUE), - "alpha_src_factor", debug_dump_blend_factor(blend->alpha_src_factor, TRUE), - "alpha_dst_factor", debug_dump_blend_factor(blend->alpha_dst_factor, TRUE)); + "rgb_func", debug_dump_blend_func(blend->rt[0].rgb_func, TRUE), + "rgb_src_factor", debug_dump_blend_factor(blend->rt[0].rgb_src_factor, TRUE), + "rgb_dst_factor", debug_dump_blend_factor(blend->rt[0].rgb_dst_factor, TRUE), + "alpha_func", debug_dump_blend_func(blend->rt[0].alpha_func, TRUE), + "alpha_src_factor", debug_dump_blend_factor(blend->rt[0].alpha_src_factor, TRUE), + "alpha_dst_factor", debug_dump_blend_factor(blend->rt[0].alpha_dst_factor, TRUE)); fprintf(fp, " ...\n"); fflush(fp); @@ -401,13 +400,15 @@ compute_blend_ref(const struct pipe_blend_state *blend, double src_term[4]; double dst_term[4]; - compute_blend_ref_term(blend->rgb_src_factor, blend->alpha_src_factor, src, src, dst, con, src_term); - compute_blend_ref_term(blend->rgb_dst_factor, blend->alpha_dst_factor, dst, src, dst, con, dst_term); + compute_blend_ref_term(blend->rt[0].rgb_src_factor, blend->rt[0].alpha_src_factor, + src, src, dst, con, src_term); + compute_blend_ref_term(blend->rt[0].rgb_dst_factor, blend->rt[0].alpha_dst_factor, + dst, src, dst, con, dst_term); /* * Combine RGB terms */ - switch (blend->rgb_func) { + switch (blend->rt[0].rgb_func) { case PIPE_BLEND_ADD: ADD_SAT(res[0], src_term[0], dst_term[0]); /* R */ ADD_SAT(res[1], src_term[1], dst_term[1]); /* G */ @@ -440,7 +441,7 @@ compute_blend_ref(const struct pipe_blend_state *blend, /* * Combine A terms */ - switch (blend->alpha_func) { + switch (blend->rt[0].alpha_func) { case PIPE_BLEND_ADD: ADD_SAT(res[3], src_term[3], dst_term[3]); /* A */ break; @@ -462,7 +463,7 @@ compute_blend_ref(const struct pipe_blend_state *blend, } -ALIGN_STACK +PIPE_ALIGN_STACK static boolean test_one(unsigned verbose, FILE *fp, @@ -531,11 +532,11 @@ test_one(unsigned verbose, success = TRUE; for(i = 0; i < n && success; ++i) { if(mode == AoS) { - ALIGN16_ATTRIB uint8_t src[LP_NATIVE_VECTOR_WIDTH/8]; - ALIGN16_ATTRIB uint8_t dst[LP_NATIVE_VECTOR_WIDTH/8]; - ALIGN16_ATTRIB uint8_t con[LP_NATIVE_VECTOR_WIDTH/8]; - ALIGN16_ATTRIB uint8_t res[LP_NATIVE_VECTOR_WIDTH/8]; - ALIGN16_ATTRIB uint8_t ref[LP_NATIVE_VECTOR_WIDTH/8]; + PIPE_ALIGN_VAR(16) uint8_t src[LP_NATIVE_VECTOR_WIDTH/8]; + PIPE_ALIGN_VAR(16) uint8_t dst[LP_NATIVE_VECTOR_WIDTH/8]; + PIPE_ALIGN_VAR(16) uint8_t con[LP_NATIVE_VECTOR_WIDTH/8]; + PIPE_ALIGN_VAR(16) uint8_t res[LP_NATIVE_VECTOR_WIDTH/8]; + PIPE_ALIGN_VAR(16) uint8_t ref[LP_NATIVE_VECTOR_WIDTH/8]; int64_t start_counter = 0; int64_t end_counter = 0; @@ -596,11 +597,11 @@ test_one(unsigned verbose, if(mode == SoA) { const unsigned stride = type.length*type.width/8; - ALIGN16_ATTRIB uint8_t src[4*LP_NATIVE_VECTOR_WIDTH/8]; - ALIGN16_ATTRIB uint8_t dst[4*LP_NATIVE_VECTOR_WIDTH/8]; - ALIGN16_ATTRIB uint8_t con[4*LP_NATIVE_VECTOR_WIDTH/8]; - ALIGN16_ATTRIB uint8_t res[4*LP_NATIVE_VECTOR_WIDTH/8]; - ALIGN16_ATTRIB uint8_t ref[4*LP_NATIVE_VECTOR_WIDTH/8]; + PIPE_ALIGN_VAR(16) uint8_t src[4*LP_NATIVE_VECTOR_WIDTH/8]; + PIPE_ALIGN_VAR(16) uint8_t dst[4*LP_NATIVE_VECTOR_WIDTH/8]; + PIPE_ALIGN_VAR(16) uint8_t con[4*LP_NATIVE_VECTOR_WIDTH/8]; + PIPE_ALIGN_VAR(16) uint8_t res[4*LP_NATIVE_VECTOR_WIDTH/8]; + PIPE_ALIGN_VAR(16) uint8_t ref[4*LP_NATIVE_VECTOR_WIDTH/8]; int64_t start_counter = 0; int64_t end_counter = 0; boolean mismatch; @@ -806,14 +807,14 @@ test_all(unsigned verbose, FILE *fp) continue; memset(&blend, 0, sizeof blend); - blend.blend_enable = 1; - blend.rgb_func = *rgb_func; - blend.rgb_src_factor = *rgb_src_factor; - blend.rgb_dst_factor = *rgb_dst_factor; - blend.alpha_func = *alpha_func; - blend.alpha_src_factor = *alpha_src_factor; - blend.alpha_dst_factor = *alpha_dst_factor; - blend.colormask = PIPE_MASK_RGBA; + blend.rt[0].blend_enable = 1; + blend.rt[0].rgb_func = *rgb_func; + blend.rt[0].rgb_src_factor = *rgb_src_factor; + blend.rt[0].rgb_dst_factor = *rgb_dst_factor; + blend.rt[0].alpha_func = *alpha_func; + blend.rt[0].alpha_src_factor = *alpha_src_factor; + blend.rt[0].alpha_dst_factor = *alpha_dst_factor; + blend.rt[0].colormask = PIPE_MASK_RGBA; if(!test_one(verbose, fp, &blend, mode, *type)) success = FALSE; @@ -865,14 +866,14 @@ test_some(unsigned verbose, FILE *fp, unsigned long n) type = &blend_types[rand() % num_types]; memset(&blend, 0, sizeof blend); - blend.blend_enable = 1; - blend.rgb_func = *rgb_func; - blend.rgb_src_factor = *rgb_src_factor; - blend.rgb_dst_factor = *rgb_dst_factor; - blend.alpha_func = *alpha_func; - blend.alpha_src_factor = *alpha_src_factor; - blend.alpha_dst_factor = *alpha_dst_factor; - blend.colormask = PIPE_MASK_RGBA; + blend.rt[0].blend_enable = 1; + blend.rt[0].rgb_func = *rgb_func; + blend.rt[0].rgb_src_factor = *rgb_src_factor; + blend.rt[0].rgb_dst_factor = *rgb_dst_factor; + blend.rt[0].alpha_func = *alpha_func; + blend.rt[0].alpha_src_factor = *alpha_src_factor; + blend.rt[0].alpha_dst_factor = *alpha_dst_factor; + blend.rt[0].colormask = PIPE_MASK_RGBA; if(!test_one(verbose, fp, &blend, mode, *type)) success = FALSE; diff --git a/src/gallium/drivers/llvmpipe/lp_test_conv.c b/src/gallium/drivers/llvmpipe/lp_test_conv.c index faddfb9677..958cc40538 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_conv.c +++ b/src/gallium/drivers/llvmpipe/lp_test_conv.c @@ -34,10 +34,10 @@ */ -#include "lp_bld_type.h" -#include "lp_bld_const.h" -#include "lp_bld_conv.h" -#include "lp_bld_debug.h" +#include "gallivm/lp_bld_type.h" +#include "gallivm/lp_bld_const.h" +#include "gallivm/lp_bld_conv.h" +#include "gallivm/lp_bld_debug.h" #include "lp_test.h" @@ -142,7 +142,7 @@ add_conv_test(LLVMModuleRef module, } -ALIGN_STACK +PIPE_ALIGN_STACK static boolean test_one(unsigned verbose, FILE *fp, @@ -230,8 +230,8 @@ test_one(unsigned verbose, for(i = 0; i < n && success; ++i) { unsigned src_stride = src_type.length*src_type.width/8; unsigned dst_stride = dst_type.length*dst_type.width/8; - ALIGN16_ATTRIB uint8_t src[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH]; - ALIGN16_ATTRIB uint8_t dst[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH]; + PIPE_ALIGN_VAR(16) uint8_t src[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH]; + PIPE_ALIGN_VAR(16) uint8_t dst[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH]; double fref[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH]; uint8_t ref[LP_MAX_VECTOR_LENGTH*LP_MAX_VECTOR_LENGTH]; int64_t start_counter = 0; diff --git a/src/gallium/drivers/llvmpipe/lp_test_format.c b/src/gallium/drivers/llvmpipe/lp_test_format.c index 23ea9ebbe7..48828bd0a0 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_format.c +++ b/src/gallium/drivers/llvmpipe/lp_test_format.c @@ -38,7 +38,7 @@ #include "util/u_cpu_detect.h" #include "util/u_format.h" -#include "lp_bld_format.h" +#include "gallivm/lp_bld_format.h" #include "lp_test.h" @@ -199,7 +199,7 @@ add_store_rgba_test(LLVMModuleRef module, } -ALIGN_STACK +PIPE_ALIGN_STACK static boolean test_format(unsigned verbose, FILE *fp, const struct pixel_test_case *test) { diff --git a/src/gallium/drivers/llvmpipe/lp_test_main.c b/src/gallium/drivers/llvmpipe/lp_test_main.c index 314544aa9a..14ff00469b 100644 --- a/src/gallium/drivers/llvmpipe/lp_test_main.c +++ b/src/gallium/drivers/llvmpipe/lp_test_main.c @@ -36,8 +36,8 @@ #include "util/u_cpu_detect.h" -#include "lp_bld_const.h" -#include "lp_bld_misc.h" +#include "gallivm/lp_bld_const.h" +#include "gallivm/lp_bld_misc.h" #include "lp_test.h" diff --git a/src/gallium/drivers/llvmpipe/lp_tex_cache.c b/src/gallium/drivers/llvmpipe/lp_tex_cache.c deleted file mode 100644 index a6d9a2c1ac..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_tex_cache.c +++ /dev/null @@ -1,304 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 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. - * - **************************************************************************/ - -/** - * Texture tile caching. - * - * Author: - * Brian Paul - */ - -#include "pipe/p_inlines.h" -#include "util/u_memory.h" -#include "util/u_tile.h" -#include "util/u_format.h" -#include "util/u_math.h" -#include "lp_context.h" -#include "lp_surface.h" -#include "lp_texture.h" -#include "lp_tex_cache.h" - - - -/** - * Return the position in the cache for the tile that contains win pos (x,y). - * We currently use a direct mapped cache so this is like a hack key. - * At some point we should investige something more sophisticated, like - * a LRU replacement policy. - */ -#define CACHE_POS(x, y) \ - (((x) + (y) * 5) % NUM_ENTRIES) - - - -/** - * Is the tile at (x,y) in cleared state? - */ -static INLINE uint -is_clear_flag_set(const uint *bitvec, union tex_tile_address addr) -{ - int pos, bit; - pos = addr.bits.y * (MAX_TEX_WIDTH / TEX_TILE_SIZE) + addr.bits.x; - assert(pos / 32 < (MAX_TEX_WIDTH / TEX_TILE_SIZE) * (MAX_TEX_HEIGHT / TEX_TILE_SIZE) / 32); - bit = bitvec[pos / 32] & (1 << (pos & 31)); - return bit; -} - - -/** - * Mark the tile at (x,y) as not cleared. - */ -static INLINE void -clear_clear_flag(uint *bitvec, union tex_tile_address addr) -{ - int pos; - pos = addr.bits.y * (MAX_TEX_WIDTH / TEX_TILE_SIZE) + addr.bits.x; - assert(pos / 32 < (MAX_TEX_WIDTH / TEX_TILE_SIZE) * (MAX_TEX_HEIGHT / TEX_TILE_SIZE) / 32); - bitvec[pos / 32] &= ~(1 << (pos & 31)); -} - - -struct llvmpipe_tex_tile_cache * -lp_create_tex_tile_cache( struct pipe_screen *screen ) -{ - struct llvmpipe_tex_tile_cache *tc; - uint pos; - - tc = CALLOC_STRUCT( llvmpipe_tex_tile_cache ); - if (tc) { - tc->screen = screen; - for (pos = 0; pos < NUM_ENTRIES; pos++) { - tc->entries[pos].addr.bits.invalid = 1; - } - tc->last_tile = &tc->entries[0]; /* any tile */ - } - return tc; -} - - -void -lp_destroy_tex_tile_cache(struct llvmpipe_tex_tile_cache *tc) -{ - struct pipe_screen *screen; - uint pos; - - for (pos = 0; pos < NUM_ENTRIES; pos++) { - /*assert(tc->entries[pos].x < 0);*/ - } - if (tc->transfer) { - screen = tc->transfer->texture->screen; - screen->tex_transfer_destroy(tc->transfer); - } - if (tc->tex_trans) { - screen = tc->tex_trans->texture->screen; - screen->tex_transfer_destroy(tc->tex_trans); - } - - FREE( tc ); -} - - -void -lp_tex_tile_cache_map_transfers(struct llvmpipe_tex_tile_cache *tc) -{ - if (tc->transfer && !tc->transfer_map) - tc->transfer_map = tc->screen->transfer_map(tc->screen, tc->transfer); - - if (tc->tex_trans && !tc->tex_trans_map) - tc->tex_trans_map = tc->screen->transfer_map(tc->screen, tc->tex_trans); -} - - -void -lp_tex_tile_cache_unmap_transfers(struct llvmpipe_tex_tile_cache *tc) -{ - if (tc->transfer_map) { - tc->screen->transfer_unmap(tc->screen, tc->transfer); - tc->transfer_map = NULL; - } - - if (tc->tex_trans_map) { - tc->screen->transfer_unmap(tc->screen, tc->tex_trans); - tc->tex_trans_map = NULL; - } -} - -void -lp_tex_tile_cache_validate_texture(struct llvmpipe_tex_tile_cache *tc) -{ - if (tc->texture) { - struct llvmpipe_texture *lpt = llvmpipe_texture(tc->texture); - if (lpt->timestamp != tc->timestamp) { - /* texture was modified, invalidate all cached tiles */ - uint i; - for (i = 0; i < NUM_ENTRIES; i++) { - tc->entries[i].addr.bits.invalid = 1; - } - - tc->timestamp = lpt->timestamp; - } - } -} - -/** - * Specify the texture to cache. - */ -void -lp_tex_tile_cache_set_texture(struct llvmpipe_tex_tile_cache *tc, - struct pipe_texture *texture) -{ - uint i; - - assert(!tc->transfer); - - if (tc->texture != texture) { - pipe_texture_reference(&tc->texture, texture); - - if (tc->tex_trans) { - struct pipe_screen *screen = tc->tex_trans->texture->screen; - - if (tc->tex_trans_map) { - screen->transfer_unmap(screen, tc->tex_trans); - tc->tex_trans_map = NULL; - } - - screen->tex_transfer_destroy(tc->tex_trans); - tc->tex_trans = NULL; - } - - /* mark as entries as invalid/empty */ - /* XXX we should try to avoid this when the teximage hasn't changed */ - for (i = 0; i < NUM_ENTRIES; i++) { - tc->entries[i].addr.bits.invalid = 1; - } - - tc->tex_face = -1; /* any invalid value here */ - } -} - - -/** - * Given the texture face, level, zslice, x and y values, compute - * the cache entry position/index where we'd hope to find the - * cached texture tile. - * This is basically a direct-map cache. - * XXX There's probably lots of ways in which we can improve this. - */ -static INLINE uint -tex_cache_pos( union tex_tile_address addr ) -{ - uint entry = (addr.bits.x + - addr.bits.y * 9 + - addr.bits.z * 3 + - addr.bits.face + - addr.bits.level * 7); - - return entry % NUM_ENTRIES; -} - -/** - * Similar to lp_get_cached_tile() but for textures. - * Tiles are read-only and indexed with more params. - */ -const struct llvmpipe_cached_tex_tile * -lp_find_cached_tex_tile(struct llvmpipe_tex_tile_cache *tc, - union tex_tile_address addr ) -{ - struct pipe_screen *screen = tc->screen; - struct llvmpipe_cached_tex_tile *tile; - - tile = tc->entries + tex_cache_pos( addr ); - - if (addr.value != tile->addr.value) { - - /* cache miss. Most misses are because we've invaldiated the - * texture cache previously -- most commonly on binding a new - * texture. Currently we effectively flush the cache on texture - * bind. - */ -#if 0 - _debug_printf("miss at %u: x=%d y=%d z=%d face=%d level=%d\n" - " tile %u: x=%d y=%d z=%d face=%d level=%d\n", - pos, x/TEX_TILE_SIZE, y/TEX_TILE_SIZE, z, face, level, - pos, tile->addr.bits.x, tile->addr.bits.y, tile->z, tile->face, tile->level); -#endif - - /* check if we need to get a new transfer */ - if (!tc->tex_trans || - tc->tex_face != addr.bits.face || - tc->tex_level != addr.bits.level || - tc->tex_z != addr.bits.z) { - /* get new transfer (view into texture) */ - - if (tc->tex_trans) { - if (tc->tex_trans_map) { - tc->screen->transfer_unmap(tc->screen, tc->tex_trans); - tc->tex_trans_map = NULL; - } - - screen->tex_transfer_destroy(tc->tex_trans); - tc->tex_trans = NULL; - } - - tc->tex_trans = - screen->get_tex_transfer(screen, tc->texture, - addr.bits.face, - addr.bits.level, - addr.bits.z, - PIPE_TRANSFER_READ, 0, 0, - u_minify(tc->texture->width0, addr.bits.level), - u_minify(tc->texture->height0, addr.bits.level)); - - tc->tex_trans_map = screen->transfer_map(screen, tc->tex_trans); - - tc->tex_face = addr.bits.face; - tc->tex_level = addr.bits.level; - tc->tex_z = addr.bits.z; - } - - { - unsigned x = addr.bits.x * TEX_TILE_SIZE; - unsigned y = addr.bits.y * TEX_TILE_SIZE; - unsigned w = TEX_TILE_SIZE; - unsigned h = TEX_TILE_SIZE; - - if (pipe_clip_tile(x, y, &w, &h, tc->tex_trans)) { - assert(0); - } - - util_format_read_4ub(tc->tex_trans->texture->format, - (uint8_t *)tile->color, sizeof tile->color[0], - tc->tex_trans_map, tc->tex_trans->stride, - x, y, w, h); - } - - tile->addr = addr; - } - - tc->last_tile = tile; - return tile; -} diff --git a/src/gallium/drivers/llvmpipe/lp_tex_cache.h b/src/gallium/drivers/llvmpipe/lp_tex_cache.h deleted file mode 100644 index 05fded78e1..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_tex_cache.h +++ /dev/null @@ -1,151 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 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 LP_TEX_CACHE_H -#define LP_TEX_CACHE_H - - -#include "pipe/p_compiler.h" - - -struct llvmpipe_context; -struct llvmpipe_tex_tile_cache; - - -/** - * Cache tile size (width and height). This needs to be a power of two. - */ -#define TEX_TILE_SIZE 64 - - -/* If we need to support > 4096, just expand this to be a 64 bit - * union, or consider tiling in Z as well. - */ -union tex_tile_address { - struct { - unsigned x:6; /* 4096 / TEX_TILE_SIZE */ - unsigned y:6; /* 4096 / TEX_TILE_SIZE */ - unsigned z:12; /* 4096 -- z not tiled */ - unsigned face:3; - unsigned level:4; - unsigned invalid:1; - } bits; - unsigned value; -}; - - -struct llvmpipe_cached_tex_tile -{ - union tex_tile_address addr; - uint8_t color[TEX_TILE_SIZE][TEX_TILE_SIZE][4]; -}; - -#define NUM_ENTRIES 50 - - -/** XXX move these */ -#define MAX_TEX_WIDTH 2048 -#define MAX_TEX_HEIGHT 2048 - - -struct llvmpipe_tex_tile_cache -{ - struct pipe_screen *screen; - struct pipe_surface *surface; /**< the surface we're caching */ - struct pipe_transfer *transfer; - void *transfer_map; - - struct pipe_texture *texture; /**< if caching a texture */ - unsigned timestamp; - - struct llvmpipe_cached_tex_tile entries[NUM_ENTRIES]; - - struct pipe_transfer *tex_trans; - void *tex_trans_map; - int tex_face, tex_level, tex_z; - - struct llvmpipe_cached_tex_tile *last_tile; /**< most recently retrieved tile */ -}; - - -extern struct llvmpipe_tex_tile_cache * -lp_create_tex_tile_cache( struct pipe_screen *screen ); - -extern void -lp_destroy_tex_tile_cache(struct llvmpipe_tex_tile_cache *tc); - -extern void -lp_tex_tile_cache_map_transfers(struct llvmpipe_tex_tile_cache *tc); - -extern void -lp_tex_tile_cache_unmap_transfers(struct llvmpipe_tex_tile_cache *tc); - -extern void -lp_tex_tile_cache_set_texture(struct llvmpipe_tex_tile_cache *tc, - struct pipe_texture *texture); - -void -lp_tex_tile_cache_validate_texture(struct llvmpipe_tex_tile_cache *tc); - -extern const struct llvmpipe_cached_tex_tile * -lp_find_cached_tex_tile(struct llvmpipe_tex_tile_cache *tc, - union tex_tile_address addr ); - -static INLINE union tex_tile_address -tex_tile_address( unsigned x, - unsigned y, - unsigned z, - unsigned face, - unsigned level ) -{ - union tex_tile_address addr; - - addr.value = 0; - addr.bits.x = x / TEX_TILE_SIZE; - addr.bits.y = y / TEX_TILE_SIZE; - addr.bits.z = z; - addr.bits.face = face; - addr.bits.level = level; - - return addr; -} - -/* Quickly retrieve tile if it matches last lookup. - */ -static INLINE const struct llvmpipe_cached_tex_tile * -lp_get_cached_tex_tile(struct llvmpipe_tex_tile_cache *tc, - union tex_tile_address addr ) -{ - if (tc->last_tile->addr.value == addr.value) - return tc->last_tile; - - return lp_find_cached_tex_tile( tc, addr ); -} - - -#endif /* LP_TEX_CACHE_H */ - diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c b/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c index d2a6ae21f5..2533275dc1 100644 --- a/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c +++ b/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c @@ -42,12 +42,11 @@ #include "pipe/p_defines.h" #include "pipe/p_shader_tokens.h" -#include "lp_bld_debug.h" -#include "lp_bld_type.h" -#include "lp_bld_intr.h" -#include "lp_bld_sample.h" -#include "lp_bld_tgsi.h" -#include "lp_state.h" +#include "gallivm/lp_bld_debug.h" +#include "gallivm/lp_bld_type.h" +#include "gallivm/lp_bld_sample.h" +#include "gallivm/lp_bld_tgsi.h" +#include "lp_jit.h" #include "lp_tex_sample.h" diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index 2c135029ea..022bf92cb4 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -32,45 +32,42 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" -#include "pipe/p_inlines.h" -#include "pipe/internal/p_winsys_screen.h" +#include "util/u_inlines.h" #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" #include "lp_context.h" -#include "lp_state.h" -#include "lp_texture.h" -#include "lp_tex_cache.h" #include "lp_screen.h" +#include "lp_texture.h" +#include "lp_tile_size.h" #include "lp_winsys.h" -/* Simple, maximally packed layout. - */ - -/* Conventional allocation path for non-display textures: +/** + * Conventional allocation path for non-display textures: + * Simple, maximally packed layout. */ static boolean llvmpipe_texture_layout(struct llvmpipe_screen *screen, - struct llvmpipe_texture * lpt) + struct llvmpipe_texture *lpt) { struct pipe_texture *pt = &lpt->base; unsigned level; unsigned width = pt->width0; unsigned height = pt->height0; unsigned depth = pt->depth0; - unsigned buffer_size = 0; for (level = 0; level <= pt->last_level; level++) { unsigned nblocksx, nblocksy; /* Allocate storage for whole quads. This is particularly important - * for depth surfaces, which are currently stored in a swizzled format. */ - nblocksx = util_format_get_nblocksx(pt->format, align(width, 2)); - nblocksy = util_format_get_nblocksy(pt->format, align(height, 2)); + * for depth surfaces, which are currently stored in a swizzled format. + */ + nblocksx = util_format_get_nblocksx(pt->format, align(width, TILE_SIZE)); + nblocksy = util_format_get_nblocksy(pt->format, align(height, TILE_SIZE)); lpt->stride[level] = align(nblocksx * util_format_get_blocksize(pt->format), 16); @@ -80,7 +77,7 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen, ((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) * lpt->stride[level]); - width = u_minify(width, 1); + width = u_minify(width, 1); height = u_minify(height, 1); depth = u_minify(depth, 1); } @@ -90,16 +87,23 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen, return lpt->data != NULL; } + + static boolean llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, - struct llvmpipe_texture * lpt) + struct llvmpipe_texture *lpt) { struct llvmpipe_winsys *winsys = screen->winsys; + /* Round up the surface size to a multiple of the tile size to + * avoid tile clipping. + */ + unsigned width = align(lpt->base.width0, TILE_SIZE); + unsigned height = align(lpt->base.height0, TILE_SIZE); + lpt->dt = winsys->displaytarget_create(winsys, lpt->base.format, - lpt->base.width0, - lpt->base.height0, + width, height, 16, &lpt->stride[0] ); @@ -107,9 +111,6 @@ llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, } - - - static struct pipe_texture * llvmpipe_texture_create(struct pipe_screen *_screen, const struct pipe_texture *templat) @@ -126,7 +127,7 @@ llvmpipe_texture_create(struct pipe_screen *_screen, /* XXX: The xlib state tracker is brain-dead and will request * PIPE_FORMAT_Z16_UNORM no matter how much we tell it we don't support it. */ - if(lpt->base.format == PIPE_FORMAT_Z16_UNORM) + if (lpt->base.format == PIPE_FORMAT_Z16_UNORM) lpt->base.format = PIPE_FORMAT_Z32_UNORM; if (lpt->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | @@ -178,6 +179,7 @@ llvmpipe_texture_blanket(struct pipe_screen * screen, return &lpt->base; #else + debug_printf("llvmpipe_texture_blanket() not implemented!"); return NULL; #endif } @@ -189,12 +191,15 @@ llvmpipe_texture_destroy(struct pipe_texture *pt) struct llvmpipe_screen *screen = llvmpipe_screen(pt->screen); struct llvmpipe_texture *lpt = llvmpipe_texture(pt); - if(lpt->dt) { + if (lpt->dt) { + /* display target */ struct llvmpipe_winsys *winsys = screen->winsys; winsys->displaytarget_destroy(winsys, lpt->dt); } - else + else { + /* regular texture */ align_free(lpt->data); + } FREE(lpt); } @@ -236,7 +241,7 @@ llvmpipe_get_tex_surface(struct pipe_screen *screen, if (ps->usage & (PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_GPU_WRITE)) { - /* Mark the surface as dirty. The tile cache will look for this. */ + /* Mark the surface as dirty. */ lpt->timestamp++; llvmpipe_screen(screen)->timestamp++; } @@ -298,8 +303,8 @@ llvmpipe_get_tex_transfer(struct pipe_screen *screen, pipe_texture_reference(&pt->texture, texture); pt->x = x; pt->y = y; - pt->width = w; - pt->height = h; + pt->width = align(w, TILE_SIZE); + pt->height = align(h, TILE_SIZE); pt->stride = lptex->stride[level]; pt->usage = usage; pt->face = face; @@ -356,7 +361,8 @@ llvmpipe_transfer_map( struct pipe_screen *_screen, lpt = llvmpipe_texture(transfer->texture); format = lpt->base.format; - if(lpt->dt) { + if (lpt->dt) { + /* display target */ struct llvmpipe_winsys *winsys = screen->winsys; map = winsys->displaytarget_map(winsys, lpt->dt, @@ -364,16 +370,16 @@ llvmpipe_transfer_map( struct pipe_screen *_screen, if (map == NULL) return NULL; } - else + else { + /* regular texture */ map = lpt->data; + } /* May want to different things here depending on read/write nature * of the map: */ - if (transfer->texture && (transfer->usage & PIPE_TRANSFER_WRITE)) - { + if (transfer->texture && (transfer->usage & PIPE_TRANSFER_WRITE)) { /* Do something to notify sharing contexts of a texture change. - * In llvmpipe, that would mean flushing the texture cache. */ screen->timestamp++; } @@ -387,29 +393,24 @@ llvmpipe_transfer_map( struct pipe_screen *_screen, static void -llvmpipe_transfer_unmap(struct pipe_screen *_screen, +llvmpipe_transfer_unmap(struct pipe_screen *screen, struct pipe_transfer *transfer) { - struct llvmpipe_screen *screen = llvmpipe_screen(_screen); + struct llvmpipe_screen *lp_screen = llvmpipe_screen(screen); struct llvmpipe_texture *lpt; assert(transfer->texture); lpt = llvmpipe_texture(transfer->texture); - if(lpt->dt) { - struct llvmpipe_winsys *winsys = screen->winsys; + if (lpt->dt) { + /* display target */ + struct llvmpipe_winsys *winsys = lp_screen->winsys; winsys->displaytarget_unmap(winsys, lpt->dt); } } void -llvmpipe_init_texture_funcs(struct llvmpipe_context *lp) -{ -} - - -void llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen) { screen->texture_create = llvmpipe_texture_create; diff --git a/src/gallium/drivers/llvmpipe/lp_texture.h b/src/gallium/drivers/llvmpipe/lp_texture.h index 00a20763e4..87c905bc02 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.h +++ b/src/gallium/drivers/llvmpipe/lp_texture.h @@ -37,6 +37,7 @@ struct pipe_screen; struct llvmpipe_context; struct llvmpipe_displaytarget; + struct llvmpipe_texture { struct pipe_texture base; @@ -58,6 +59,7 @@ struct llvmpipe_texture unsigned timestamp; }; + struct llvmpipe_transfer { struct pipe_transfer base; @@ -73,6 +75,14 @@ llvmpipe_texture(struct pipe_texture *pt) return (struct llvmpipe_texture *) pt; } + +static INLINE const struct llvmpipe_texture * +llvmpipe_texture_const(const struct pipe_texture *pt) +{ + return (const struct llvmpipe_texture *) pt; +} + + static INLINE struct llvmpipe_transfer * llvmpipe_transfer(struct pipe_transfer *pt) { @@ -81,10 +91,7 @@ llvmpipe_transfer(struct pipe_transfer *pt) extern void -llvmpipe_init_texture_funcs( struct llvmpipe_context *llvmpipe ); - -extern void llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen); -#endif /* LP_TEXTURE */ +#endif /* LP_TEXTURE_H */ diff --git a/src/gallium/drivers/llvmpipe/lp_tile_cache.c b/src/gallium/drivers/llvmpipe/lp_tile_cache.c deleted file mode 100644 index 7a1ecf5107..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_tile_cache.c +++ /dev/null @@ -1,358 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 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. - * - **************************************************************************/ - -/** - * Texture tile caching. - * - * Author: - * Brian Paul - */ - -#include "pipe/p_inlines.h" -#include "util/u_memory.h" -#include "util/u_math.h" -#include "util/u_tile.h" -#include "util/u_rect.h" -#include "lp_context.h" -#include "lp_surface.h" -#include "lp_texture.h" -#include "lp_tile_soa.h" -#include "lp_tile_cache.h" - - -#define MAX_WIDTH 4096 -#define MAX_HEIGHT 4096 - - -enum llvmpipe_tile_status -{ - LP_TILE_STATUS_UNDEFINED = 0, - LP_TILE_STATUS_CLEAR = 1, - LP_TILE_STATUS_DEFINED = 2 -}; - - -struct llvmpipe_cached_tile -{ - enum llvmpipe_tile_status status; - - /** color in SOA format */ - uint8_t *color; -}; - - -struct llvmpipe_tile_cache -{ - struct pipe_screen *screen; - struct pipe_surface *surface; /**< the surface we're caching */ - struct pipe_transfer *transfer; - void *transfer_map; - - struct llvmpipe_cached_tile entries[MAX_WIDTH/TILE_SIZE][MAX_HEIGHT/TILE_SIZE]; - - uint8_t clear_color[4]; /**< for color bufs */ - uint clear_val; /**< for z+stencil, or packed color clear value */ - - struct llvmpipe_cached_tile *last_tile; /**< most recently retrieved tile */ -}; - - -struct llvmpipe_tile_cache * -lp_create_tile_cache( struct pipe_screen *screen ) -{ - struct llvmpipe_tile_cache *tc; - int maxLevels, maxTexSize; - - /* sanity checking: max sure MAX_WIDTH/HEIGHT >= largest texture image */ - maxLevels = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS); - maxTexSize = 1 << (maxLevels - 1); - assert(MAX_WIDTH >= maxTexSize); - - tc = CALLOC_STRUCT( llvmpipe_tile_cache ); - if(!tc) - return NULL; - - tc->screen = screen; - - return tc; -} - - -void -lp_destroy_tile_cache(struct llvmpipe_tile_cache *tc) -{ - struct pipe_screen *screen; - unsigned x, y; - - for (y = 0; y < MAX_HEIGHT; y += TILE_SIZE) { - for (x = 0; x < MAX_WIDTH; x += TILE_SIZE) { - struct llvmpipe_cached_tile *tile = &tc->entries[y/TILE_SIZE][x/TILE_SIZE]; - - if(tile->color) - align_free(tile->color); - } - } - - if (tc->transfer) { - screen = tc->transfer->texture->screen; - screen->tex_transfer_destroy(tc->transfer); - } - - FREE( tc ); -} - - -/** - * Specify the surface to cache. - */ -void -lp_tile_cache_set_surface(struct llvmpipe_tile_cache *tc, - struct pipe_surface *ps) -{ - if (tc->transfer) { - struct pipe_screen *screen = tc->transfer->texture->screen; - - if (ps == tc->surface) - return; - - if (tc->transfer_map) { - screen->transfer_unmap(screen, tc->transfer); - tc->transfer_map = NULL; - } - - screen->tex_transfer_destroy(tc->transfer); - tc->transfer = NULL; - } - - tc->surface = ps; - - if (ps) { - struct pipe_screen *screen = ps->texture->screen; - unsigned x, y; - - tc->transfer = screen->get_tex_transfer(screen, ps->texture, ps->face, - ps->level, ps->zslice, - PIPE_TRANSFER_READ_WRITE, - 0, 0, ps->width, ps->height); - - for (y = 0; y < ps->height; y += TILE_SIZE) { - for (x = 0; x < ps->width; x += TILE_SIZE) { - struct llvmpipe_cached_tile *tile = &tc->entries[y/TILE_SIZE][x/TILE_SIZE]; - - tile->status = LP_TILE_STATUS_UNDEFINED; - - if(!tile->color) - tile->color = align_malloc( TILE_SIZE*TILE_SIZE*NUM_CHANNELS, 16 ); - } - } - } -} - - -/** - * Return the transfer being cached. - */ -struct pipe_surface * -lp_tile_cache_get_surface(struct llvmpipe_tile_cache *tc) -{ - return tc->surface; -} - - -void -lp_tile_cache_map_transfers(struct llvmpipe_tile_cache *tc) -{ - if (tc->transfer && !tc->transfer_map) - tc->transfer_map = tc->screen->transfer_map(tc->screen, tc->transfer); -} - - -void -lp_tile_cache_unmap_transfers(struct llvmpipe_tile_cache *tc) -{ - if (tc->transfer_map) { - tc->screen->transfer_unmap(tc->screen, tc->transfer); - tc->transfer_map = NULL; - } -} - - -/** - * Set a tile to a solid color. - */ -static void -clear_tile(struct llvmpipe_cached_tile *tile, - uint8_t clear_color[4]) -{ - if (clear_color[0] == clear_color[1] && - clear_color[1] == clear_color[2] && - clear_color[2] == clear_color[3]) { - memset(tile->color, clear_color[0], TILE_SIZE * TILE_SIZE * 4); - } - else { - uint x, y, chan; - for (y = 0; y < TILE_SIZE; y++) - for (x = 0; x < TILE_SIZE; x++) - for (chan = 0; chan < 4; ++chan) - TILE_PIXEL(tile->color, x, y, chan) = clear_color[chan]; - } -} - - -/** - * Flush the tile cache: write all dirty tiles back to the transfer. - * any tiles "flagged" as cleared will be "really" cleared. - */ -void -lp_flush_tile_cache(struct llvmpipe_tile_cache *tc) -{ - struct pipe_transfer *pt = tc->transfer; - unsigned x, y; - - if(!pt) - return; - - assert(tc->transfer_map); - - /* push the tile to all positions marked as clear */ - for (y = 0; y < pt->height; y += TILE_SIZE) { - for (x = 0; x < pt->width; x += TILE_SIZE) { - struct llvmpipe_cached_tile *tile = &tc->entries[y/TILE_SIZE][x/TILE_SIZE]; - - if(tile->status != LP_TILE_STATUS_UNDEFINED) { - unsigned w = TILE_SIZE; - unsigned h = TILE_SIZE; - - if (!pipe_clip_tile(x, y, &w, &h, pt)) { - switch(tile->status) { - case LP_TILE_STATUS_CLEAR: - /* Actually clear the tiles which were flagged as being in a - * clear state. */ - util_fill_rect(tc->transfer_map, pt->texture->format, pt->stride, - x, y, w, h, - tc->clear_val); - break; - - case LP_TILE_STATUS_DEFINED: - lp_tile_write_4ub(pt->texture->format, - tile->color, - tc->transfer_map, pt->stride, - x, y, w, h); - break; - - default: - assert(0); - break; - } - } - - tile->status = LP_TILE_STATUS_UNDEFINED; - } - } - } -} - - -/** - * Get a tile from the cache. - * \param x, y position of tile, in pixels - */ -void * -lp_get_cached_tile(struct llvmpipe_tile_cache *tc, - unsigned x, unsigned y ) -{ - struct llvmpipe_cached_tile *tile = &tc->entries[y/TILE_SIZE][x/TILE_SIZE]; - struct pipe_transfer *pt = tc->transfer; - - assert(tc->surface); - assert(tc->transfer); - - if(!tc->transfer_map) - lp_tile_cache_map_transfers(tc); - - assert(tc->transfer_map); - - switch(tile->status) { - case LP_TILE_STATUS_CLEAR: - /* don't get tile from framebuffer, just clear it */ - clear_tile(tile, tc->clear_color); - tile->status = LP_TILE_STATUS_DEFINED; - break; - - case LP_TILE_STATUS_UNDEFINED: { - unsigned w = TILE_SIZE; - unsigned h = TILE_SIZE; - - x &= ~(TILE_SIZE - 1); - y &= ~(TILE_SIZE - 1); - - if (!pipe_clip_tile(x, y, &w, &h, tc->transfer)) - lp_tile_read_4ub(pt->texture->format, - tile->color, - tc->transfer_map, tc->transfer->stride, - x, y, w, h); - - tile->status = LP_TILE_STATUS_DEFINED; - break; - } - - case LP_TILE_STATUS_DEFINED: - /* nothing to do */ - break; - } - - return tile->color; -} - - -/** - * When a whole surface is being cleared to a value we can avoid - * fetching tiles above. - * Save the color and set a 'clearflag' for each tile of the screen. - */ -void -lp_tile_cache_clear(struct llvmpipe_tile_cache *tc, const float *rgba, - uint clearValue) -{ - struct pipe_transfer *pt = tc->transfer; - const unsigned w = pt->width; - const unsigned h = pt->height; - unsigned x, y, chan; - - for(chan = 0; chan < 4; ++chan) - tc->clear_color[chan] = float_to_ubyte(rgba[chan]); - - tc->clear_val = clearValue; - - /* push the tile to all positions marked as clear */ - for (y = 0; y < h; y += TILE_SIZE) { - for (x = 0; x < w; x += TILE_SIZE) { - struct llvmpipe_cached_tile *tile = &tc->entries[y/TILE_SIZE][x/TILE_SIZE]; - tile->status = LP_TILE_STATUS_CLEAR; - } - } -} diff --git a/src/gallium/drivers/llvmpipe/lp_tile_cache.h b/src/gallium/drivers/llvmpipe/lp_tile_cache.h deleted file mode 100644 index 161bab3799..0000000000 --- a/src/gallium/drivers/llvmpipe/lp_tile_cache.h +++ /dev/null @@ -1,71 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 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 LP_TILE_CACHE_H -#define LP_TILE_CACHE_H - - -#include "pipe/p_compiler.h" -#include "lp_tile_soa.h" - - -struct llvmpipe_tile_cache; /* opaque */ - - -extern struct llvmpipe_tile_cache * -lp_create_tile_cache( struct pipe_screen *screen ); - -extern void -lp_destroy_tile_cache(struct llvmpipe_tile_cache *tc); - -extern void -lp_tile_cache_set_surface(struct llvmpipe_tile_cache *tc, - struct pipe_surface *lps); - -extern struct pipe_surface * -lp_tile_cache_get_surface(struct llvmpipe_tile_cache *tc); - -extern void -lp_tile_cache_map_transfers(struct llvmpipe_tile_cache *tc); - -extern void -lp_tile_cache_unmap_transfers(struct llvmpipe_tile_cache *tc); - -extern void -lp_flush_tile_cache(struct llvmpipe_tile_cache *tc); - -extern void -lp_tile_cache_clear(struct llvmpipe_tile_cache *tc, const float *rgba, - uint clearValue); - -extern void * -lp_get_cached_tile(struct llvmpipe_tile_cache *tc, - unsigned x, unsigned y ); - - -#endif /* LP_TILE_CACHE_H */ - diff --git a/src/gallium/drivers/llvmpipe/lp_tile_size.h b/src/gallium/drivers/llvmpipe/lp_tile_size.h new file mode 100644 index 0000000000..f0b983c063 --- /dev/null +++ b/src/gallium/drivers/llvmpipe/lp_tile_size.h @@ -0,0 +1,39 @@ +/************************************************************************** + * + * Copyright 2010 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 THE 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 USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef LP_TILE_SIZE_H +#define LP_TILE_SIZE_H + + +/** + * Tile size (width and height). This needs to be a power of two. + */ +#define TILE_ORDER 6 +#define TILE_SIZE (1 << TILE_ORDER) + + +#endif diff --git a/src/gallium/drivers/llvmpipe/lp_tile_soa.h b/src/gallium/drivers/llvmpipe/lp_tile_soa.h index 19d00b58d3..eea3ab8499 100644 --- a/src/gallium/drivers/llvmpipe/lp_tile_soa.h +++ b/src/gallium/drivers/llvmpipe/lp_tile_soa.h @@ -30,7 +30,7 @@ #include "pipe/p_compiler.h" #include "tgsi/tgsi_exec.h" /* for NUM_CHANNELS */ - +#include "lp_tile_size.h" #ifdef __cplusplus extern "C" { @@ -40,26 +40,20 @@ extern "C" { struct pipe_transfer; -/** - * Cache tile size (width and height). This needs to be a power of two. - */ -#define TILE_SIZE 64 - - -#define TILE_VECTOR_HEIGHT 2 -#define TILE_VECTOR_WIDTH 8 +#define TILE_VECTOR_HEIGHT 4 +#define TILE_VECTOR_WIDTH 4 extern const unsigned char tile_offset[TILE_VECTOR_HEIGHT][TILE_VECTOR_WIDTH]; -#define TILE_C_STRIDE (TILE_VECTOR_HEIGHT*TILE_VECTOR_WIDTH) -#define TILE_X_STRIDE (NUM_CHANNELS*TILE_C_STRIDE) -#define TILE_Y_STRIDE (TILE_VECTOR_HEIGHT*TILE_SIZE*NUM_CHANNELS) +#define TILE_C_STRIDE (TILE_VECTOR_HEIGHT * TILE_VECTOR_WIDTH) //16 +#define TILE_X_STRIDE (NUM_CHANNELS * TILE_C_STRIDE) //64 +#define TILE_Y_STRIDE (TILE_VECTOR_HEIGHT * TILE_SIZE * NUM_CHANNELS) //1024 #define TILE_PIXEL(_p, _x, _y, _c) \ - ((_p)[((_y)/TILE_VECTOR_HEIGHT)*TILE_Y_STRIDE + \ - ((_x)/TILE_VECTOR_WIDTH)*TILE_X_STRIDE + \ - (_c)*TILE_C_STRIDE + \ + ((_p)[((_y) / TILE_VECTOR_HEIGHT) * TILE_Y_STRIDE + \ + ((_x) / TILE_VECTOR_WIDTH) * TILE_X_STRIDE + \ + (_c) * TILE_C_STRIDE + \ tile_offset[(_y) % TILE_VECTOR_HEIGHT][(_x) % TILE_VECTOR_WIDTH]]) diff --git a/src/gallium/drivers/llvmpipe/lp_tile_soa.py b/src/gallium/drivers/llvmpipe/lp_tile_soa.py index 004c5c979e..5d53689a3d 100644 --- a/src/gallium/drivers/llvmpipe/lp_tile_soa.py +++ b/src/gallium/drivers/llvmpipe/lp_tile_soa.py @@ -129,22 +129,8 @@ def generate_format_read(format, dst_type, dst_native_type, dst_suffix): print -def generate_format_write(format, src_type, src_native_type, src_suffix): - '''Generate the function to write pixels to a particular format''' - - name = short_name(format) - - dst_native_type = native_type(format) - - print 'static void' - print 'lp_tile_%s_write_%s(const %s *src, uint8_t *dst, unsigned dst_stride, unsigned x0, unsigned y0, unsigned w, unsigned h)' % (name, src_suffix, src_native_type) - print '{' - print ' unsigned x, y;' - print ' uint8_t *dst_row = dst + y0*dst_stride;' - print ' for (y = 0; y < h; ++y) {' - print ' %s *dst_pixel = (%s *)(dst_row + x0*%u);' % (dst_native_type, dst_native_type, format.stride()) - print ' for (x = 0; x < w; ++x) {' - +def compute_inverse_swizzle(format): + '''Return an array[4] of inverse swizzle terms''' inv_swizzle = [None]*4 if format.colorspace == 'rgb': for i in range(4): @@ -155,8 +141,86 @@ def generate_format_write(format, src_type, src_native_type, src_suffix): swizzle = format.out_swizzle[0] if swizzle < 4: inv_swizzle[swizzle] = 0 - else: - assert False + return inv_swizzle + + +def pack_rgba(format, src_type, r, g, b, a): + """Return an expression for packing r, g, b, a into a pixel of the + given format. Ex: '(b << 24) | (g << 16) | (r << 8) | (a << 0)' + """ + assert format.colorspace == 'rgb' + inv_swizzle = compute_inverse_swizzle(format) + shift = 0 + expr = None + for i in range(4): + # choose r, g, b, or a depending on the inverse swizzle term + if inv_swizzle[i] == 0: + value = r + elif inv_swizzle[i] == 1: + value = g + elif inv_swizzle[i] == 2: + value = b + elif inv_swizzle[i] == 3: + value = a + else: + value = None + + if value: + dst_type = format.in_types[i] + dst_native_type = native_type(format) + value = conversion_expr(src_type, dst_type, dst_native_type, value) + term = "((%s) << %d)" % (value, shift) + if expr: + expr = expr + " | " + term + else: + expr = term + + width = format.in_types[i].size + shift = shift + width + return expr + + +def emit_unrolled_write_code(format, src_type): + '''Emit code for writing a block based on unrolled loops. + This is considerably faster than the TILE_PIXEL-based code below. + ''' + dst_native_type = native_type(format) + print ' const unsigned dstpix_stride = dst_stride / %d;' % format.stride() + print ' %s *dstpix = (%s *) dst;' % (dst_native_type, dst_native_type) + print ' unsigned int qx, qy, i;' + print + print ' for (qy = 0; qy < h; qy += TILE_VECTOR_HEIGHT) {' + print ' const unsigned py = y0 + qy;' + print ' for (qx = 0; qx < w; qx += TILE_VECTOR_WIDTH) {' + print ' const unsigned px = x0 + qx;' + print ' const uint8_t *r = src + 0 * TILE_C_STRIDE;' + print ' const uint8_t *g = src + 1 * TILE_C_STRIDE;' + print ' const uint8_t *b = src + 2 * TILE_C_STRIDE;' + print ' const uint8_t *a = src + 3 * TILE_C_STRIDE;' + print ' (void) r; (void) g; (void) b; (void) a; /* silence warnings */' + print ' for (i = 0; i < TILE_C_STRIDE; i += 2) {' + print ' const uint32_t pixel0 = %s;' % pack_rgba(format, src_type, "r[i+0]", "g[i+0]", "b[i+0]", "a[i+0]") + print ' const uint32_t pixel1 = %s;' % pack_rgba(format, src_type, "r[i+1]", "g[i+1]", "b[i+1]", "a[i+1]") + print ' const unsigned offset = (py + tile_y_offset[i]) * dstpix_stride + (px + tile_x_offset[i]);' + print ' dstpix[offset + 0] = pixel0;' + print ' dstpix[offset + 1] = pixel1;' + print ' }' + print ' src += TILE_X_STRIDE;' + print ' }' + print ' }' + + +def emit_tile_pixel_write_code(format, src_type): + '''Emit code for writing a block based on the TILE_PIXEL macro.''' + dst_native_type = native_type(format) + + inv_swizzle = compute_inverse_swizzle(format) + + print ' unsigned x, y;' + print ' uint8_t *dst_row = dst + y0*dst_stride;' + print ' for (y = 0; y < h; ++y) {' + print ' %s *dst_pixel = (%s *)(dst_row + x0*%u);' % (dst_native_type, dst_native_type, format.stride()) + print ' for (x = 0; x < w; ++x) {' if format.layout == ARITH: print ' %s pixel = 0;' % dst_native_type @@ -185,6 +249,20 @@ def generate_format_write(format, src_type, src_native_type, src_suffix): print ' }' print ' dst_row += dst_stride;' print ' }' + + +def generate_format_write(format, src_type, src_native_type, src_suffix): + '''Generate the function to write pixels to a particular format''' + + name = short_name(format) + + print 'static void' + print 'lp_tile_%s_write_%s(const %s *src, uint8_t *dst, unsigned dst_stride, unsigned x0, unsigned y0, unsigned w, unsigned h)' % (name, src_suffix, src_native_type) + print '{' + if format.layout == ARITH and format.colorspace == 'rgb': + emit_unrolled_write_code(format, src_type) + else: + emit_tile_pixel_write_code(format, src_type) print '}' print @@ -259,8 +337,23 @@ def main(): print print 'const unsigned char' print 'tile_offset[TILE_VECTOR_HEIGHT][TILE_VECTOR_WIDTH] = {' - print ' { 0, 1, 4, 5, 8, 9, 12, 13},' - print ' { 2, 3, 6, 7, 10, 11, 14, 15}' + print ' { 0, 1, 4, 5},' + print ' { 2, 3, 6, 7},' + print ' { 8, 9, 12, 13},' + print ' { 10, 11, 14, 15}' + print '};' + print + print '/* Note: these lookup tables could be replaced with some' + print ' * bit-twiddling code, but this is a little faster.' + print ' */' + print 'static unsigned tile_x_offset[TILE_VECTOR_WIDTH * TILE_VECTOR_HEIGHT] = {' + print ' 0, 1, 0, 1, 2, 3, 2, 3,' + print ' 0, 1, 0, 1, 2, 3, 2, 3' + print '};' + print + print 'static unsigned tile_y_offset[TILE_VECTOR_WIDTH * TILE_VECTOR_HEIGHT] = {' + print ' 0, 0, 1, 1, 0, 0, 1, 1,' + print ' 2, 2, 3, 3, 2, 2, 3, 3' print '};' print diff --git a/src/gallium/drivers/llvmpipe/lp_winsys.h b/src/gallium/drivers/llvmpipe/lp_winsys.h index 74b472b653..ce11fa9304 100644 --- a/src/gallium/drivers/llvmpipe/lp_winsys.h +++ b/src/gallium/drivers/llvmpipe/lp_winsys.h @@ -113,9 +113,6 @@ struct llvmpipe_winsys }; -struct pipe_context * -llvmpipe_create( struct pipe_screen * ); - struct pipe_screen * llvmpipe_create_screen( struct llvmpipe_winsys * ); diff --git a/src/gallium/drivers/nouveau/Makefile b/src/gallium/drivers/nouveau/Makefile index 0cb66041d5..0e02680bc6 100644 --- a/src/gallium/drivers/nouveau/Makefile +++ b/src/gallium/drivers/nouveau/Makefile @@ -4,6 +4,7 @@ include $(TOP)/configs/current LIBNAME = nouveau C_SOURCES = nouveau_screen.c \ - nouveau_context.c + nouveau_context.c \ + nv04_surface_2d.c include ../../Makefile.template diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c index 7ebc94ed6c..156cb2d229 100644 --- a/src/gallium/drivers/nouveau/nouveau_screen.c +++ b/src/gallium/drivers/nouveau/nouveau_screen.c @@ -3,7 +3,9 @@ #include <pipe/p_state.h> #include <util/u_memory.h> +#include <util/u_inlines.h> +#include <stdio.h> #include <errno.h> #include "nouveau/nouveau_bo.h" @@ -260,6 +262,8 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev) void nouveau_screen_fini(struct nouveau_screen *screen) { + struct pipe_winsys *ws = screen->base.winsys; nouveau_channel_free(&screen->channel); + ws->destroy(ws); } diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h index 4c3e08a43f..af9ddd558c 100644 --- a/src/gallium/drivers/nouveau/nouveau_winsys.h +++ b/src/gallium/drivers/nouveau/nouveau_winsys.h @@ -2,7 +2,7 @@ #define NOUVEAU_WINSYS_H #include <stdint.h> -#include "pipe/internal/p_winsys_screen.h" +#include "util/u_simple_screen.h" #include "pipe/p_defines.h" #include "nouveau/nouveau_bo.h" @@ -27,39 +27,12 @@ #define NOUVEAU_BUFFER_USAGE_NO_RENDER (1 << 19) extern struct pipe_screen * -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_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_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_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_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_device *); -extern struct pipe_context * -nv50_create(struct pipe_screen *, unsigned pctx_id); - #endif diff --git a/src/gallium/drivers/nv04/nv04_surface_2d.c b/src/gallium/drivers/nouveau/nv04_surface_2d.c index b24a9cee5a..42c2ca932d 100644 --- a/src/gallium/drivers/nv04/nv04_surface_2d.c +++ b/src/gallium/drivers/nouveau/nv04_surface_2d.c @@ -60,17 +60,17 @@ nv04_scaled_image_format(enum pipe_format format) case PIPE_FORMAT_A8_UNORM: case PIPE_FORMAT_L8_UNORM: case PIPE_FORMAT_I8_UNORM: - return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_Y8; + return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_Y8; case PIPE_FORMAT_A1R5G5B5_UNORM: - return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5; + return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5; case PIPE_FORMAT_A8R8G8B8_UNORM: - return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8; + return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8; case PIPE_FORMAT_X8R8G8B8_UNORM: - return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8; + return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8; case PIPE_FORMAT_R5G6B5_UNORM: case PIPE_FORMAT_R16_SNORM: case PIPE_FORMAT_A8L8_UNORM: - return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5; + return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5; default: return -1; } @@ -155,7 +155,7 @@ nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx, log2i(dst->width) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT | log2i(dst->height) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT); - BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1); + BEGIN_RING(chan, sifm, NV03_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE, 1); OUT_RELOCo(chan, src_bo, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE, 1); @@ -173,22 +173,22 @@ nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx, OUT_RELOCl(chan, dst_bo, dst->offset, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 9); - OUT_RING (chan, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE); + BEGIN_RING(chan, sifm, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 9); + OUT_RING (chan, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE); OUT_RING (chan, nv04_scaled_image_format(src->format)); - OUT_RING (chan, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY); - OUT_RING (chan, (x + dx) | ((y + dy) << NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_Y_SHIFT)); - OUT_RING (chan, sub_h << NV04_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_H_SHIFT | sub_w); - OUT_RING (chan, (x + dx) | ((y + dy) << NV04_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_Y_SHIFT)); - OUT_RING (chan, sub_h << NV04_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_H_SHIFT | sub_w); + OUT_RING (chan, NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY); + OUT_RING (chan, (x + dx) | ((y + dy) << NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_POINT_Y_SHIFT)); + OUT_RING (chan, sub_h << NV03_SCALED_IMAGE_FROM_MEMORY_CLIP_SIZE_H_SHIFT | sub_w); + OUT_RING (chan, (x + dx) | ((y + dy) << NV03_SCALED_IMAGE_FROM_MEMORY_OUT_POINT_Y_SHIFT)); + OUT_RING (chan, sub_h << NV03_SCALED_IMAGE_FROM_MEMORY_OUT_SIZE_H_SHIFT | sub_w); OUT_RING (chan, 1 << 20); OUT_RING (chan, 1 << 20); - BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SIZE, 4); - OUT_RING (chan, sub_h << NV04_SCALED_IMAGE_FROM_MEMORY_SIZE_H_SHIFT | sub_w); + BEGIN_RING(chan, sifm, NV03_SCALED_IMAGE_FROM_MEMORY_SIZE, 4); + OUT_RING (chan, sub_h << NV03_SCALED_IMAGE_FROM_MEMORY_SIZE_H_SHIFT | sub_w); OUT_RING (chan, src_pitch | - NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER | - NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE); + NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER | + NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE); OUT_RELOCl(chan, src_bo, src->offset + (sy+y) * src_pitch + (sx+x) * util_format_get_blocksize(src->texture->format), NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); OUT_RING (chan, 0); @@ -421,12 +421,12 @@ nv04_surface_2d_init(struct nouveau_screen *screen) return NULL; } - BEGIN_RING(chan, ctx->blit, NV04_IMAGE_BLIT_DMA_NOTIFY, 1); + BEGIN_RING(chan, ctx->blit, NV01_IMAGE_BLIT_DMA_NOTIFY, 1); OUT_RING (chan, ctx->ntfy->handle); BEGIN_RING(chan, ctx->blit, NV04_IMAGE_BLIT_SURFACE, 1); OUT_RING (chan, ctx->surf2d->handle); - BEGIN_RING(chan, ctx->blit, NV04_IMAGE_BLIT_OPERATION, 1); - OUT_RING (chan, NV04_IMAGE_BLIT_OPERATION_SRCCOPY); + BEGIN_RING(chan, ctx->blit, NV01_IMAGE_BLIT_OPERATION, 1); + OUT_RING (chan, NV01_IMAGE_BLIT_OPERATION_SRCCOPY); ret = nouveau_grobj_alloc(chan, handle++, NV04_GDI_RECTANGLE_TEXT, &ctx->rect); diff --git a/src/gallium/drivers/nv04/nv04_surface_2d.h b/src/gallium/drivers/nouveau/nv04_surface_2d.h index ce696a11a3..ce696a11a3 100644 --- a/src/gallium/drivers/nv04/nv04_surface_2d.h +++ b/src/gallium/drivers/nouveau/nv04_surface_2d.h diff --git a/src/gallium/drivers/nv04/Makefile b/src/gallium/drivers/nv04/Makefile deleted file mode 100644 index 7c14bacb1d..0000000000 --- a/src/gallium/drivers/nv04/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -TOP = ../../../.. -include $(TOP)/configs/current - -LIBNAME = nv04 - -C_SOURCES = \ - nv04_surface_2d.c \ - nv04_clear.c \ - nv04_context.c \ - nv04_fragprog.c \ - nv04_fragtex.c \ - nv04_miptree.c \ - nv04_prim_vbuf.c \ - nv04_screen.c \ - nv04_state.c \ - nv04_state_emit.c \ - nv04_surface.c \ - nv04_transfer.c \ - nv04_vbo.c - -include ../../Makefile.template diff --git a/src/gallium/drivers/nv04/nv04_clear.c b/src/gallium/drivers/nv04/nv04_clear.c deleted file mode 100644 index 01cacd36fe..0000000000 --- a/src/gallium/drivers/nv04/nv04_clear.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" - -#include "nv04_context.h" - -void -nv04_clear(struct pipe_context *pipe, struct pipe_surface *ps, - unsigned clearValue) -{ - pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue); -} diff --git a/src/gallium/drivers/nv04/nv04_context.c b/src/gallium/drivers/nv04/nv04_context.c deleted file mode 100644 index edd96859cf..0000000000 --- a/src/gallium/drivers/nv04/nv04_context.c +++ /dev/null @@ -1,112 +0,0 @@ -#include "draw/draw_context.h" -#include "pipe/p_defines.h" -#include "pipe/internal/p_winsys_screen.h" - -#include "nv04_context.h" -#include "nv04_screen.h" - -static void -nv04_flush(struct pipe_context *pipe, unsigned flags, - struct pipe_fence_handle **fence) -{ - struct nv04_context *nv04 = nv04_context(pipe); - struct nv04_screen *screen = nv04->screen; - struct nouveau_channel *chan = screen->base.channel; - - draw_flush(nv04->draw); - - FIRE_RING(chan); - if (fence) - *fence = NULL; -} - -static void -nv04_destroy(struct pipe_context *pipe) -{ - struct nv04_context *nv04 = nv04_context(pipe); - - if (nv04->draw) - draw_destroy(nv04->draw); - - FREE(nv04); -} - -static boolean -nv04_init_hwctx(struct nv04_context *nv04) -{ - struct nv04_screen *screen = nv04->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *fahrenheit = screen->fahrenheit; - - // requires a valid handle -// BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_NOTIFY, 1); -// OUT_RING(0); - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_NOP, 1); - OUT_RING(chan, 0); - - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_CONTROL, 1); - OUT_RING(chan, 0x40182800); -// OUT_RING(1<<20/*no cull*/); - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_BLEND, 1); -// OUT_RING(0x24|(1<<6)|(1<<8)); - OUT_RING(chan, 0x120001a4); - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_FORMAT, 1); - OUT_RING(chan, 0x332213a1); - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_FILTER, 1); - OUT_RING(chan, 0x11001010); - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_COLORKEY, 1); - OUT_RING(chan, 0x0); -// BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_OFFSET, 1); -// OUT_RING(SCREEN_OFFSET); - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_FOGCOLOR, 1); - OUT_RING(chan, 0xff000000); - - - - FIRE_RING (chan); - return TRUE; -} - -struct pipe_context * -nv04_create(struct pipe_screen *pscreen, unsigned pctx_id) -{ - struct nv04_screen *screen = nv04_screen(pscreen); - struct pipe_winsys *ws = pscreen->winsys; - struct nv04_context *nv04; - struct nouveau_winsys *nvws = screen->nvws; - - nv04 = CALLOC(1, sizeof(struct nv04_context)); - if (!nv04) - return NULL; - nv04->screen = screen; - nv04->pctx_id = pctx_id; - - nv04->nvws = nvws; - - nv04->pipe.winsys = ws; - nv04->pipe.screen = pscreen; - nv04->pipe.destroy = nv04_destroy; - nv04->pipe.draw_arrays = nv04_draw_arrays; - nv04->pipe.draw_elements = nv04_draw_elements; - nv04->pipe.clear = nv04_clear; - nv04->pipe.flush = nv04_flush; - - nv04->pipe.is_texture_referenced = nouveau_is_texture_referenced; - nv04->pipe.is_buffer_referenced = nouveau_is_buffer_referenced; - - nv04_init_surface_functions(nv04); - nv04_init_state_functions(nv04); - - nv04->draw = draw_create(); - assert(nv04->draw); - draw_wide_point_threshold(nv04->draw, 0.0); - draw_wide_line_threshold(nv04->draw, 0.0); - draw_enable_line_stipple(nv04->draw, FALSE); - draw_enable_point_sprites(nv04->draw, FALSE); - draw_set_rasterize_stage(nv04->draw, nv04_draw_vbuf_stage(nv04)); - - nv04_init_hwctx(nv04); - - return &nv04->pipe; -} - diff --git a/src/gallium/drivers/nv04/nv04_context.h b/src/gallium/drivers/nv04/nv04_context.h deleted file mode 100644 index fe3b527423..0000000000 --- a/src/gallium/drivers/nv04/nv04_context.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef __NV04_CONTEXT_H__ -#define __NV04_CONTEXT_H__ - -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "pipe/p_compiler.h" - -#include "util/u_memory.h" -#include "util/u_math.h" - -#include "draw/draw_vertex.h" - -#include "nouveau/nouveau_winsys.h" -#include "nouveau/nouveau_gldefs.h" -#include "nouveau/nouveau_context.h" - -#include "nv04_state.h" - -#define NOUVEAU_ERR(fmt, args...) \ - fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args); -#define NOUVEAU_MSG(fmt, args...) \ - fprintf(stderr, "nouveau: "fmt, ##args); - -#include "nv04_screen.h" - -#define NV04_NEW_VERTPROG (1 << 1) -#define NV04_NEW_FRAGPROG (1 << 2) -#define NV04_NEW_BLEND (1 << 3) -#define NV04_NEW_RAST (1 << 4) -#define NV04_NEW_CONTROL (1 << 5) -#define NV04_NEW_VIEWPORT (1 << 6) -#define NV04_NEW_SAMPLER (1 << 7) -#define NV04_NEW_FRAMEBUFFER (1 << 8) -#define NV04_NEW_VTXARRAYS (1 << 9) - -struct nv04_context { - struct pipe_context pipe; - - struct nouveau_winsys *nvws; - struct nv04_screen *screen; - unsigned pctx_id; - - struct draw_context *draw; - - int chipset; - struct nouveau_notifier *sync; - - uint32_t dirty; - - struct nv04_blend_state *blend; - struct nv04_sampler_state *sampler[PIPE_MAX_SAMPLERS]; - struct nv04_fragtex_state fragtex; - struct nv04_rasterizer_state *rast; - struct nv04_depth_stencil_alpha_state *dsa; - - struct nv04_miptree *tex_miptree[PIPE_MAX_SAMPLERS]; - unsigned dirty_samplers; - unsigned fp_samplers; - unsigned vp_samplers; - - uint32_t rt_enable; - struct pipe_framebuffer_state *framebuffer; - struct pipe_surface *rt; - struct pipe_surface *zeta; - - struct { - struct pipe_buffer *buffer; - uint32_t format; - } tex[16]; - - unsigned vb_enable; - struct { - struct pipe_buffer *buffer; - unsigned delta; - } vb[16]; - - float *constbuf[PIPE_SHADER_TYPES][32][4]; - unsigned constbuf_nr[PIPE_SHADER_TYPES]; - - struct vertex_info vertex_info; - struct { - - struct nouveau_resource *exec_heap; - struct nouveau_resource *data_heap; - - struct nv04_vertex_program *active; - - struct nv04_vertex_program *current; - struct pipe_buffer *constant_buf; - } vertprog; - - struct { - struct nv04_fragment_program *active; - - struct nv04_fragment_program *current; - struct pipe_buffer *constant_buf; - } fragprog; - - struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; - struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS]; - - struct pipe_viewport_state viewport; -}; - -static INLINE struct nv04_context * -nv04_context(struct pipe_context *pipe) -{ - return (struct nv04_context *)pipe; -} - -extern void nv04_init_state_functions(struct nv04_context *nv04); -extern void nv04_init_surface_functions(struct nv04_context *nv04); -extern void nv04_screen_init_miptree_functions(struct pipe_screen *screen); - -/* nv04_clear.c */ -extern void nv04_clear(struct pipe_context *pipe, struct pipe_surface *ps, - unsigned clearValue); - -/* nv04_draw.c */ -extern struct draw_stage *nv04_draw_render_stage(struct nv04_context *nv04); - -/* nv04_fragprog.c */ -extern void nv04_fragprog_bind(struct nv04_context *, - struct nv04_fragment_program *); -extern void nv04_fragprog_destroy(struct nv04_context *, - struct nv04_fragment_program *); - -/* nv04_fragtex.c */ -extern void nv04_fragtex_bind(struct nv04_context *); - -/* nv04_prim_vbuf.c */ -struct draw_stage *nv04_draw_vbuf_stage( struct nv04_context *nv04 ); - -/* nv04_state.c and friends */ -extern void nv04_emit_hw_state(struct nv04_context *nv04); -extern void nv04_state_tex_update(struct nv04_context *nv04); - -/* nv04_vbo.c */ -extern void nv04_draw_arrays(struct pipe_context *, unsigned mode, - unsigned start, unsigned count); -extern void nv04_draw_elements( struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, - unsigned indexSize, - unsigned prim, unsigned start, unsigned count); - - -#endif diff --git a/src/gallium/drivers/nv04/nv04_fragprog.c b/src/gallium/drivers/nv04/nv04_fragprog.c deleted file mode 100644 index 8a2af41fe0..0000000000 --- a/src/gallium/drivers/nv04/nv04_fragprog.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" - -#include "pipe/p_shader_tokens.h" -#include "tgsi/tgsi_parse.h" -#include "tgsi/tgsi_util.h" - -#include "nv04_context.h" - -void -nv04_fragprog_bind(struct nv04_context *nv04, struct nv04_fragment_program *fp) -{ -} - -void -nv04_fragprog_destroy(struct nv04_context *nv04, - struct nv04_fragment_program *fp) -{ -} - diff --git a/src/gallium/drivers/nv04/nv04_fragtex.c b/src/gallium/drivers/nv04/nv04_fragtex.c deleted file mode 100644 index c152b52119..0000000000 --- a/src/gallium/drivers/nv04/nv04_fragtex.c +++ /dev/null @@ -1,73 +0,0 @@ -#include "nv04_context.h" -#include "nouveau/nouveau_util.h" - -#define _(m,tf) \ -{ \ - PIPE_FORMAT_##m, \ - NV04_TEXTURED_TRIANGLE_FORMAT_COLOR_##tf, \ -} - -struct nv04_texture_format { - uint pipe; - int format; -}; - -static struct nv04_texture_format -nv04_texture_formats[] = { - _(A8R8G8B8_UNORM, A8R8G8B8), - _(X8R8G8B8_UNORM, X8R8G8B8), - _(A1R5G5B5_UNORM, A1R5G5B5), - _(A4R4G4B4_UNORM, A4R4G4B4), - _(L8_UNORM, Y8 ), - _(A8_UNORM, Y8 ), -}; - -static uint32_t -nv04_fragtex_format(uint pipe_format) -{ - struct nv04_texture_format *tf = nv04_texture_formats; - int i; - - for (i=0; i< sizeof(nv04_texture_formats)/sizeof(nv04_texture_formats[0]); i++) { - if (tf->pipe == pipe_format) - return tf->format; - tf++; - } - - NOUVEAU_ERR("unknown texture format %s\n", pf_name(pipe_format)); - return 0; -} - - -static void -nv04_fragtex_build(struct nv04_context *nv04, int unit) -{ - struct nv04_miptree *nv04mt = nv04->tex_miptree[unit]; - struct pipe_texture *pt = &nv04mt->base; - - switch (pt->target) { - case PIPE_TEXTURE_2D: - break; - default: - NOUVEAU_ERR("Unknown target %d\n", pt->target); - return; - } - - nv04->fragtex.format = NV04_TEXTURED_TRIANGLE_FORMAT_ORIGIN_ZOH_CORNER - | NV04_TEXTURED_TRIANGLE_FORMAT_ORIGIN_FOH_CORNER - | nv04_fragtex_format(pt->format) - | ( (pt->last_level + 1) << NV04_TEXTURED_TRIANGLE_FORMAT_MIPMAP_LEVELS_SHIFT ) - | ( log2i(pt->width0) << NV04_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_U_SHIFT ) - | ( log2i(pt->height0) << NV04_TEXTURED_TRIANGLE_FORMAT_BASE_SIZE_V_SHIFT ) - | NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_EDGE - | NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_CLAMP_TO_EDGE - ; -} - - -void -nv04_fragtex_bind(struct nv04_context *nv04) -{ - nv04_fragtex_build(nv04, 0); -} - diff --git a/src/gallium/drivers/nv04/nv04_miptree.c b/src/gallium/drivers/nv04/nv04_miptree.c deleted file mode 100644 index e0a6948aeb..0000000000 --- a/src/gallium/drivers/nv04/nv04_miptree.c +++ /dev/null @@ -1,146 +0,0 @@ -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "pipe/p_inlines.h" -#include "util/u_math.h" - -#include "nv04_context.h" -#include "nv04_screen.h" - -static void -nv04_miptree_layout(struct nv04_miptree *nv04mt) -{ - struct pipe_texture *pt = &nv04mt->base; - uint offset = 0; - int nr_faces, l; - - nr_faces = 1; - - for (l = 0; l <= pt->last_level; l++) { - nv04mt->level[l].pitch = pt->width0; - nv04mt->level[l].pitch = (nv04mt->level[l].pitch + 63) & ~63; - } - - for (l = 0; l <= pt->last_level; l++) { - nv04mt->level[l].image_offset = - CALLOC(nr_faces, sizeof(unsigned)); - /* XXX guess was obviously missing */ - nv04mt->level[l].image_offset[0] = offset; - offset += nv04mt->level[l].pitch * u_minify(pt->height0, l); - } - - nv04mt->total_size = offset; -} - -static struct pipe_texture * -nv04_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) -{ - struct nv04_miptree *mt; - - mt = MALLOC(sizeof(struct nv04_miptree)); - if (!mt) - return NULL; - mt->base = *pt; - pipe_reference_init(&mt->base.reference, 1); - mt->base.screen = pscreen; - - //mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - - nv04_miptree_layout(mt); - - mt->buffer = pscreen->buffer_create(pscreen, 256, PIPE_BUFFER_USAGE_PIXEL | - NOUVEAU_BUFFER_USAGE_TEXTURE, - mt->total_size); - if (!mt->buffer) { - printf("failed %d byte alloc\n",mt->total_size); - FREE(mt); - return NULL; - } - mt->bo = nouveau_bo(mt->buffer); - return &mt->base; -} - -static struct pipe_texture * -nv04_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt, - const unsigned *stride, struct pipe_buffer *pb) -{ - struct nv04_miptree *mt; - - /* Only supports 2D, non-mipmapped textures for the moment */ - if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 || - pt->depth0 != 1) - return NULL; - - mt = CALLOC_STRUCT(nv04_miptree); - if (!mt) - return NULL; - - mt->base = *pt; - pipe_reference_init(&mt->base.reference, 1); - mt->base.screen = pscreen; - mt->level[0].pitch = stride[0]; - mt->level[0].image_offset = CALLOC(1, sizeof(unsigned)); - - pipe_buffer_reference(&mt->buffer, pb); - mt->bo = nouveau_bo(mt->buffer); - return &mt->base; -} - -static void -nv04_miptree_destroy(struct pipe_texture *pt) -{ - struct nv04_miptree *mt = (struct nv04_miptree *)pt; - int l; - - pipe_buffer_reference(&mt->buffer, NULL); - for (l = 0; l <= pt->last_level; l++) { - if (mt->level[l].image_offset) - FREE(mt->level[l].image_offset); - } - - FREE(mt); -} - -static struct pipe_surface * -nv04_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned flags) -{ - struct nv04_miptree *nv04mt = (struct nv04_miptree *)pt; - struct nv04_surface *ns; - - ns = CALLOC_STRUCT(nv04_surface); - if (!ns) - return NULL; - pipe_texture_reference(&ns->base.texture, pt); - ns->base.format = pt->format; - ns->base.width = u_minify(pt->width0, level); - ns->base.height = u_minify(pt->height0, level); - ns->base.usage = flags; - pipe_reference_init(&ns->base.reference, 1); - ns->base.face = face; - ns->base.level = level; - ns->base.zslice = zslice; - ns->pitch = nv04mt->level[level].pitch; - - ns->base.offset = nv04mt->level[level].image_offset[0]; - - return &ns->base; -} - -static void -nv04_miptree_surface_del(struct pipe_surface *ps) -{ - pipe_texture_reference(&ps->texture, NULL); - FREE(ps); -} - -void -nv04_screen_init_miptree_functions(struct pipe_screen *pscreen) -{ - pscreen->texture_create = nv04_miptree_create; - pscreen->texture_blanket = nv04_miptree_blanket; - pscreen->texture_destroy = nv04_miptree_destroy; - pscreen->get_tex_surface = nv04_miptree_surface_new; - pscreen->tex_surface_destroy = nv04_miptree_surface_del; -} - diff --git a/src/gallium/drivers/nv04/nv04_prim_vbuf.c b/src/gallium/drivers/nv04/nv04_prim_vbuf.c deleted file mode 100644 index 0b795ea243..0000000000 --- a/src/gallium/drivers/nv04/nv04_prim_vbuf.c +++ /dev/null @@ -1,339 +0,0 @@ - -#include "util/u_debug.h" -#include "pipe/p_inlines.h" -#include "pipe/internal/p_winsys_screen.h" -#include "pipe/p_compiler.h" - -#include "draw/draw_vbuf.h" - -#include "nv04_context.h" -#include "nv04_state.h" - -#define VERTEX_SIZE 40 -#define VERTEX_BUFFER_SIZE (4096*VERTEX_SIZE) // 4096 vertices of 40 bytes each - -/** - * Primitive renderer for nv04. - */ -struct nv04_vbuf_render { - struct vbuf_render base; - - struct nv04_context *nv04; - - /** Vertex buffer */ - unsigned char* buffer; - - /** Vertex size in bytes */ - unsigned vertex_size; - - /** Current primitive */ - unsigned prim; -}; - - -/** - * Basically a cast wrapper. - */ -static INLINE struct nv04_vbuf_render * -nv04_vbuf_render( struct vbuf_render *render ) -{ - assert(render); - return (struct nv04_vbuf_render *)render; -} - - -static const struct vertex_info * -nv04_vbuf_render_get_vertex_info( struct vbuf_render *render ) -{ - struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render); - struct nv04_context *nv04 = nv04_render->nv04; - return &nv04->vertex_info; -} - - -static boolean -nv04_vbuf_render_allocate_vertices( struct vbuf_render *render, - ushort vertex_size, - ushort nr_vertices ) -{ - struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render); - - nv04_render->buffer = (unsigned char*) MALLOC(VERTEX_BUFFER_SIZE); - assert(!nv04_render->buffer); - - return nv04_render->buffer ? TRUE : FALSE; -} - -static void * -nv04_vbuf_render_map_vertices( struct vbuf_render *render ) -{ - struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render); - return nv04_render->buffer; -} - -static void -nv04_vbuf_render_unmap_vertices( struct vbuf_render *render, - ushort min_index, - ushort max_index ) -{ -} - -static boolean -nv04_vbuf_render_set_primitive( struct vbuf_render *render, - unsigned prim ) -{ - struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render); - - if (prim <= PIPE_PRIM_LINE_STRIP) - return FALSE; - - nv04_render->prim = prim; - return TRUE; -} - -static INLINE void nv04_2triangles(struct nv04_context* nv04, unsigned char* buffer, ushort v0, ushort v1, ushort v2, ushort v3, ushort v4, ushort v5) -{ - struct nv04_screen *screen = nv04->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *fahrenheit = screen->fahrenheit; - - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_TLVERTEX_SX(0xA), 49); - OUT_RINGp(chan, buffer + VERTEX_SIZE * v0,8); - OUT_RINGp(chan, buffer + VERTEX_SIZE * v1,8); - OUT_RINGp(chan, buffer + VERTEX_SIZE * v2,8); - OUT_RINGp(chan, buffer + VERTEX_SIZE * v3,8); - OUT_RINGp(chan, buffer + VERTEX_SIZE * v4,8); - OUT_RINGp(chan, buffer + VERTEX_SIZE * v5,8); - OUT_RING(chan, 0xFEDCBA); -} - -static INLINE void nv04_1triangle(struct nv04_context* nv04, unsigned char* buffer, ushort v0, ushort v1, ushort v2) -{ - struct nv04_screen *screen = nv04->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *fahrenheit = screen->fahrenheit; - - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_TLVERTEX_SX(0xD), 25); - OUT_RINGp(chan, buffer + VERTEX_SIZE * v0,8); - OUT_RINGp(chan, buffer + VERTEX_SIZE * v1,8); - OUT_RINGp(chan, buffer + VERTEX_SIZE * v2,8); - OUT_RING(chan, 0xFED); -} - -static INLINE void nv04_1quad(struct nv04_context* nv04, unsigned char* buffer, ushort v0, ushort v1, ushort v2, ushort v3) -{ - struct nv04_screen *screen = nv04->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *fahrenheit = screen->fahrenheit; - - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_TLVERTEX_SX(0xC), 33); - OUT_RINGp(chan, buffer + VERTEX_SIZE * v0,8); - OUT_RINGp(chan, buffer + VERTEX_SIZE * v1,8); - OUT_RINGp(chan, buffer + VERTEX_SIZE * v2,8); - OUT_RINGp(chan, buffer + VERTEX_SIZE * v3,8); - OUT_RING(chan, 0xFECEDC); -} - -static void nv04_vbuf_render_triangles_elts(struct nv04_vbuf_render * render, const ushort * indices, uint nr_indices) -{ - unsigned char* buffer = render->buffer; - struct nv04_context* nv04 = render->nv04; - int i; - - for( i=0; i< nr_indices-5; i+=6) - nv04_2triangles(nv04, - buffer, - indices[i+0], - indices[i+1], - indices[i+2], - indices[i+3], - indices[i+4], - indices[i+5] - ); - if (i != nr_indices) - { - nv04_1triangle(nv04, - buffer, - indices[i+0], - indices[i+1], - indices[i+2] - ); - i+=3; - } - if (i != nr_indices) - NOUVEAU_ERR("Houston, we have lost some vertices\n"); -} - -static void nv04_vbuf_render_tri_strip_elts(struct nv04_vbuf_render* render, const ushort* indices, uint nr_indices) -{ - const uint32_t striptbl[]={0x321210,0x543432,0x765654,0x987876,0xBA9A98,0xDCBCBA,0xFEDEDC}; - unsigned char* buffer = render->buffer; - struct nv04_context *nv04 = render->nv04; - struct nv04_screen *screen = nv04->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *fahrenheit = screen->fahrenheit; - int i,j; - - for(i = 0; i<nr_indices; i+=14) - { - int numvert = MIN2(16, nr_indices - i); - int numtri = numvert - 2; - if (numvert<3) - break; - - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0), numvert*8); - for(j = 0; j<numvert; j++) - OUT_RINGp(chan, buffer + VERTEX_SIZE * indices [i+j], 8 ); - - BEGIN_RING_NI(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE(0), (numtri+1)/2 ); - for(j = 0; j<numtri/2; j++ ) - OUT_RING(chan, striptbl[j]); - if (numtri%2) - OUT_RING(chan, striptbl[numtri/2]&0xFFF); - } -} - -static void nv04_vbuf_render_tri_fan_elts(struct nv04_vbuf_render* render, const ushort* indices, uint nr_indices) -{ - const uint32_t fantbl[]={0x320210,0x540430,0x760650,0x980870,0xBA0A90,0xDC0CB0,0xFE0ED0}; - unsigned char* buffer = render->buffer; - struct nv04_context *nv04 = render->nv04; - struct nv04_screen *screen = nv04->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *fahrenheit = screen->fahrenheit; - int i,j; - - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0), 8); - OUT_RINGp(chan, buffer + VERTEX_SIZE * indices[0], 8); - - for(i = 1; i<nr_indices; i+=14) - { - int numvert=MIN2(15, nr_indices - i); - int numtri=numvert-2; - if (numvert < 3) - break; - - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_TLVERTEX_SX(0x1), numvert*8); - - for(j=0;j<numvert;j++) - OUT_RINGp(chan, buffer + VERTEX_SIZE * indices[ i+j ], 8 ); - - BEGIN_RING_NI(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_DRAWPRIMITIVE(0), (numtri+1)/2); - for(j = 0; j<numtri/2; j++) - OUT_RING(chan, fantbl[j]); - if (numtri%2) - OUT_RING(chan, fantbl[numtri/2]&0xFFF); - } -} - -static void nv04_vbuf_render_quads_elts(struct nv04_vbuf_render* render, const ushort* indices, uint nr_indices) -{ - unsigned char* buffer = render->buffer; - struct nv04_context* nv04 = render->nv04; - int i; - - for(i = 0; i < nr_indices; i += 4) - nv04_1quad(nv04, - buffer, - indices[i+0], - indices[i+1], - indices[i+2], - indices[i+3] - ); -} - - -static void -nv04_vbuf_render_draw( struct vbuf_render *render, - const ushort *indices, - uint nr_indices) -{ - struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render); - - // emit the indices - switch( nv04_render->prim ) - { - case PIPE_PRIM_TRIANGLES: - nv04_vbuf_render_triangles_elts(nv04_render, indices, nr_indices); - break; - case PIPE_PRIM_QUAD_STRIP: - case PIPE_PRIM_TRIANGLE_STRIP: - nv04_vbuf_render_tri_strip_elts(nv04_render, indices, nr_indices); - break; - case PIPE_PRIM_TRIANGLE_FAN: - case PIPE_PRIM_POLYGON: - nv04_vbuf_render_tri_fan_elts(nv04_render, indices, nr_indices); - break; - case PIPE_PRIM_QUADS: - nv04_vbuf_render_quads_elts(nv04_render, indices, nr_indices); - break; - default: - NOUVEAU_ERR("You have to implement primitive %d, young padawan\n", nv04_render->prim); - break; - } -} - - -static void -nv04_vbuf_render_release_vertices( struct vbuf_render *render ) -{ - struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render); - - free(nv04_render->buffer); - nv04_render->buffer = NULL; -} - - -static void -nv04_vbuf_render_destroy( struct vbuf_render *render ) -{ - struct nv04_vbuf_render *nv04_render = nv04_vbuf_render(render); - FREE(nv04_render); -} - - -/** - * Create a new primitive render. - */ -static struct vbuf_render * -nv04_vbuf_render_create( struct nv04_context *nv04 ) -{ - struct nv04_vbuf_render *nv04_render = CALLOC_STRUCT(nv04_vbuf_render); - - nv04_render->nv04 = nv04; - - nv04_render->base.max_vertex_buffer_bytes = VERTEX_BUFFER_SIZE; - nv04_render->base.max_indices = 65536; - nv04_render->base.get_vertex_info = nv04_vbuf_render_get_vertex_info; - nv04_render->base.allocate_vertices = nv04_vbuf_render_allocate_vertices; - nv04_render->base.map_vertices = nv04_vbuf_render_map_vertices; - nv04_render->base.unmap_vertices = nv04_vbuf_render_unmap_vertices; - nv04_render->base.set_primitive = nv04_vbuf_render_set_primitive; - nv04_render->base.draw = nv04_vbuf_render_draw; - nv04_render->base.release_vertices = nv04_vbuf_render_release_vertices; - nv04_render->base.destroy = nv04_vbuf_render_destroy; - - return &nv04_render->base; -} - - -/** - * Create a new primitive vbuf/render stage. - */ -struct draw_stage *nv04_draw_vbuf_stage( struct nv04_context *nv04 ) -{ - struct vbuf_render *render; - struct draw_stage *stage; - - render = nv04_vbuf_render_create(nv04); - if(!render) - return NULL; - - stage = draw_vbuf_stage( nv04->draw, render ); - if(!stage) { - render->destroy(render); - return NULL; - } - - return stage; -} diff --git a/src/gallium/drivers/nv04/nv04_screen.c b/src/gallium/drivers/nv04/nv04_screen.c deleted file mode 100644 index 7c5b6e8229..0000000000 --- a/src/gallium/drivers/nv04/nv04_screen.c +++ /dev/null @@ -1,212 +0,0 @@ -#include "pipe/p_screen.h" -#include "pipe/p_inlines.h" - -#include "nv04_context.h" -#include "nv04_screen.h" - -static int -nv04_screen_get_param(struct pipe_screen *screen, int param) -{ - switch (param) { - case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: - return 1; - case PIPE_CAP_NPOT_TEXTURES: - return 0; - case PIPE_CAP_TWO_SIDED_STENCIL: - return 0; - case PIPE_CAP_GLSL: - return 0; - case PIPE_CAP_ANISOTROPIC_FILTER: - return 0; - case PIPE_CAP_POINT_SPRITE: - return 0; - case PIPE_CAP_MAX_RENDER_TARGETS: - return 1; - case PIPE_CAP_OCCLUSION_QUERY: - return 0; - case PIPE_CAP_TEXTURE_SHADOW_MAP: - return 0; - case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: - return 10; - case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: - return 0; - case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - return 0; - case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: - return 0; - case PIPE_CAP_TEXTURE_MIRROR_CLAMP: - 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; - default: - NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); - return 0; - } -} - -static float -nv04_screen_get_paramf(struct pipe_screen *screen, int param) -{ - switch (param) { - case PIPE_CAP_MAX_LINE_WIDTH: - case PIPE_CAP_MAX_LINE_WIDTH_AA: - return 0.0; - case PIPE_CAP_MAX_POINT_WIDTH: - case PIPE_CAP_MAX_POINT_WIDTH_AA: - return 0.0; - case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: - return 0.0; - case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: - return 0.0; - default: - NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); - return 0.0; - } -} - -static boolean -nv04_screen_is_format_supported(struct pipe_screen *screen, - enum pipe_format format, - enum pipe_texture_target target, - unsigned tex_usage, unsigned geom_flags) -{ - if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) { - 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: - break; - } - } else { - switch (format) { - case PIPE_FORMAT_A8R8G8B8_UNORM: - case PIPE_FORMAT_X8R8G8B8_UNORM: - case PIPE_FORMAT_A1R5G5B5_UNORM: - case PIPE_FORMAT_R5G6B5_UNORM: - case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_A8_UNORM: - return TRUE; - default: - break; - } - } - - return FALSE; -} - -static void -nv04_screen_destroy(struct pipe_screen *pscreen) -{ - struct nv04_screen *screen = nv04_screen(pscreen); - - nouveau_notifier_free(&screen->sync); - nouveau_grobj_free(&screen->fahrenheit); - nv04_surface_2d_takedown(&screen->eng2d); - - nouveau_screen_fini(&screen->base); - - FREE(pscreen); -} - -static struct pipe_buffer * -nv04_surface_buffer(struct pipe_surface *surf) -{ - struct nv04_miptree *mt = (struct nv04_miptree *)surf->texture; - - return mt->buffer; -} - -struct pipe_screen * -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; - int ret; - - if (!screen) - return NULL; - 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; - - nv04_screen_init_miptree_functions(pscreen); - nv04_screen_init_transfer_functions(pscreen); - - if (dev->chipset >= 0x20) { - fahrenheit_class = 0; - sub3d_class = 0; - } else if (dev->chipset >= 0x10) { - fahrenheit_class = NV10_TEXTURED_TRIANGLE; - sub3d_class = NV10_CONTEXT_SURFACES_3D; - } else { - fahrenheit_class=NV04_TEXTURED_TRIANGLE; - sub3d_class = NV04_CONTEXT_SURFACES_3D; - } - - if (!fahrenheit_class) { - NOUVEAU_ERR("Unknown nv04 chipset: nv%02x\n", dev->chipset); - return NULL; - } - - /* 3D object */ - 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 = 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 = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); - if (ret) { - NOUVEAU_ERR("Error creating notifier object: %d\n", ret); - nv04_screen_destroy(pscreen); - return NULL; - } - - return pscreen; -} - diff --git a/src/gallium/drivers/nv04/nv04_screen.h b/src/gallium/drivers/nv04/nv04_screen.h deleted file mode 100644 index 11466b9442..0000000000 --- a/src/gallium/drivers/nv04/nv04_screen.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __NV04_SCREEN_H__ -#define __NV04_SCREEN_H__ - -#include "nouveau/nouveau_screen.h" -#include "nv04_surface_2d.h" - -struct nv04_screen { - struct nouveau_screen base; - - struct nouveau_winsys *nvws; - unsigned chipset; - - /* HW graphics objects */ - struct nv04_surface_2d *eng2d; - struct nouveau_grobj *fahrenheit; - struct nouveau_grobj *context_surfaces_3d; - struct nouveau_notifier *sync; - -}; - -static INLINE struct nv04_screen * -nv04_screen(struct pipe_screen *screen) -{ - return (struct nv04_screen *)screen; -} - -void -nv04_screen_init_transfer_functions(struct pipe_screen *pscreen); - -#endif diff --git a/src/gallium/drivers/nv04/nv04_state.c b/src/gallium/drivers/nv04/nv04_state.c deleted file mode 100644 index e3dc4c5bf4..0000000000 --- a/src/gallium/drivers/nv04/nv04_state.c +++ /dev/null @@ -1,459 +0,0 @@ -#include "draw/draw_context.h" -#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" - -#include "nv04_context.h" -#include "nv04_state.h" - -static void * -nv04_blend_state_create(struct pipe_context *pipe, - const struct pipe_blend_state *cso) -{ - struct nv04_blend_state *cb; - - cb = MALLOC(sizeof(struct nv04_blend_state)); - - cb->b_enable = cso->blend_enable ? 1 : 0; - cb->b_src = ((nvgl_blend_func(cso->alpha_src_factor)<<16) | - (nvgl_blend_func(cso->rgb_src_factor))); - cb->b_dst = ((nvgl_blend_func(cso->alpha_dst_factor)<<16) | - (nvgl_blend_func(cso->rgb_dst_factor))); - - - return (void *)cb; -} - -static void -nv04_blend_state_bind(struct pipe_context *pipe, void *blend) -{ - struct nv04_context *nv04 = nv04_context(pipe); - - nv04->blend = (struct nv04_blend_state*)blend; - - nv04->dirty |= NV04_NEW_BLEND; -} - -static void -nv04_blend_state_delete(struct pipe_context *pipe, void *hwcso) -{ - free(hwcso); -} - - -static INLINE unsigned -wrap_mode(unsigned wrap) { - unsigned ret; - - switch (wrap) { - case PIPE_TEX_WRAP_REPEAT: - ret = NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_REPEAT; - break; - case PIPE_TEX_WRAP_MIRROR_REPEAT: - ret = NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_MIRRORED_REPEAT; - break; - case PIPE_TEX_WRAP_CLAMP_TO_EDGE: - ret = NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_EDGE; - break; - case PIPE_TEX_WRAP_CLAMP_TO_BORDER: - ret = NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP_TO_BORDER; - break; - case PIPE_TEX_WRAP_CLAMP: - ret = NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP; - break; - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: - case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: - case PIPE_TEX_WRAP_MIRROR_CLAMP: - default: - NOUVEAU_ERR("unknown wrap mode: %d\n", wrap); - ret = NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_CLAMP; - } - return ret >> NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_SHIFT; -} - -static void * -nv04_sampler_state_create(struct pipe_context *pipe, - const struct pipe_sampler_state *cso) -{ - - struct nv04_sampler_state *ss; - uint32_t filter = 0; - - ss = MALLOC(sizeof(struct nv04_sampler_state)); - - ss->format = ((wrap_mode(cso->wrap_s) << NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSU_SHIFT) | - (wrap_mode(cso->wrap_t) << NV04_TEXTURED_TRIANGLE_FORMAT_ADDRESSV_SHIFT)); - - if (cso->max_anisotropy > 1.0) { - filter |= NV04_TEXTURED_TRIANGLE_FILTER_ANISOTROPIC_MINIFY_ENABLE | NV04_TEXTURED_TRIANGLE_FILTER_ANISOTROPIC_MAGNIFY_ENABLE; - } - - switch (cso->mag_img_filter) { - case PIPE_TEX_FILTER_LINEAR: - filter |= NV04_TEXTURED_TRIANGLE_FILTER_MAGNIFY_LINEAR; - break; - case PIPE_TEX_FILTER_NEAREST: - default: - filter |= NV04_TEXTURED_TRIANGLE_FILTER_MAGNIFY_NEAREST; - break; - } - - switch (cso->min_img_filter) { - case PIPE_TEX_FILTER_LINEAR: - switch (cso->min_mip_filter) { - case PIPE_TEX_MIPFILTER_NEAREST: - filter |= NV04_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_NEAREST; - break; - case PIPE_TEX_MIPFILTER_LINEAR: - filter |= NV04_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR_MIPMAP_LINEAR; - break; - case PIPE_TEX_MIPFILTER_NONE: - default: - filter |= NV04_TEXTURED_TRIANGLE_FILTER_MINIFY_LINEAR; - break; - } - break; - case PIPE_TEX_FILTER_NEAREST: - default: - switch (cso->min_mip_filter) { - case PIPE_TEX_MIPFILTER_NEAREST: - filter |= NV04_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_NEAREST; - break; - case PIPE_TEX_MIPFILTER_LINEAR: - filter |= NV04_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST_MIPMAP_LINEAR; - break; - case PIPE_TEX_MIPFILTER_NONE: - default: - filter |= NV04_TEXTURED_TRIANGLE_FILTER_MINIFY_NEAREST; - break; - } - break; - } - - ss->filter = filter; - - return (void *)ss; -} - -static void -nv04_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler) -{ - struct nv04_context *nv04 = nv04_context(pipe); - unsigned unit; - - for (unit = 0; unit < nr; unit++) { - nv04->sampler[unit] = sampler[unit]; - nv04->dirty_samplers |= (1 << unit); - } -} - -static void -nv04_sampler_state_delete(struct pipe_context *pipe, void *hwcso) -{ - free(hwcso); -} - -static void -nv04_set_sampler_texture(struct pipe_context *pipe, unsigned nr, - struct pipe_texture **miptree) -{ - struct nv04_context *nv04 = nv04_context(pipe); - unsigned unit; - - for (unit = 0; unit < nr; unit++) { - nv04->tex_miptree[unit] = (struct nv04_miptree *)miptree[unit]; - nv04->dirty_samplers |= (1 << unit); - } -} - -static void * -nv04_rasterizer_state_create(struct pipe_context *pipe, - const struct pipe_rasterizer_state *cso) -{ - struct nv04_rasterizer_state *rs; - - /*XXX: ignored: - * scissor - * points/lines (no hw support, emulated with tris in gallium) - */ - rs = MALLOC(sizeof(struct nv04_rasterizer_state)); - - rs->blend = cso->flatshade ? NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_FLAT : NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_GOURAUD; - - return (void *)rs; -} - -static void -nv04_rasterizer_state_bind(struct pipe_context *pipe, void *rast) -{ - struct nv04_context *nv04 = nv04_context(pipe); - - nv04->rast = (struct nv04_rasterizer_state*)rast; - - draw_set_rasterizer_state(nv04->draw, (nv04->rast ? nv04->rast->templ : NULL)); - - nv04->dirty |= NV04_NEW_RAST | NV04_NEW_BLEND; -} - -static void -nv04_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso) -{ - free(hwcso); -} - -static INLINE uint32_t nv04_compare_func(uint32_t f) -{ - switch ( f ) { - case PIPE_FUNC_NEVER: return 1; - case PIPE_FUNC_LESS: return 2; - case PIPE_FUNC_EQUAL: return 3; - case PIPE_FUNC_LEQUAL: return 4; - case PIPE_FUNC_GREATER: return 5; - case PIPE_FUNC_NOTEQUAL: return 6; - case PIPE_FUNC_GEQUAL: return 7; - case PIPE_FUNC_ALWAYS: return 8; - } - NOUVEAU_MSG("Unable to find the function\n"); - return 0; -} - -static void * -nv04_depth_stencil_alpha_state_create(struct pipe_context *pipe, - const struct pipe_depth_stencil_alpha_state *cso) -{ - struct nv04_depth_stencil_alpha_state *hw; - - hw = MALLOC(sizeof(struct nv04_depth_stencil_alpha_state)); - - hw->control = float_to_ubyte(cso->alpha.ref_value); - hw->control |= ( nv04_compare_func(cso->alpha.func) << NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_FUNC_SHIFT ); - hw->control |= cso->alpha.enabled ? NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_ENABLE : 0; - hw->control |= NV04_TEXTURED_TRIANGLE_CONTROL_ORIGIN; - hw->control |= cso->depth.enabled ? NV04_TEXTURED_TRIANGLE_CONTROL_Z_ENABLE : 0; - hw->control |= ( nv04_compare_func(cso->depth.func)<< NV04_TEXTURED_TRIANGLE_CONTROL_Z_FUNC_SHIFT ); - hw->control |= 1 << NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_SHIFT; // no culling, handled by the draw module - hw->control |= NV04_TEXTURED_TRIANGLE_CONTROL_DITHER_ENABLE; - hw->control |= NV04_TEXTURED_TRIANGLE_CONTROL_Z_PERSPECTIVE_ENABLE; - hw->control |= cso->depth.writemask ? NV04_TEXTURED_TRIANGLE_CONTROL_Z_WRITE : 0; - hw->control |= 1 << NV04_TEXTURED_TRIANGLE_CONTROL_Z_FORMAT_SHIFT; // integer zbuffer format - - return (void *)hw; -} - -static void -nv04_depth_stencil_alpha_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv04_context *nv04 = nv04_context(pipe); - - nv04->dsa = hwcso; - nv04->dirty |= NV04_NEW_CONTROL; -} - -static void -nv04_depth_stencil_alpha_state_delete(struct pipe_context *pipe, void *hwcso) -{ - free(hwcso); -} - -static void * -nv04_vp_state_create(struct pipe_context *pipe, - const struct pipe_shader_state *templ) -{ - struct nv04_context *nv04 = nv04_context(pipe); - - return draw_create_vertex_shader(nv04->draw, templ); -} - -static void -nv04_vp_state_bind(struct pipe_context *pipe, void *shader) -{ - struct nv04_context *nv04 = nv04_context(pipe); - - draw_bind_vertex_shader(nv04->draw, (struct draw_vertex_shader *) shader); - - nv04->dirty |= NV04_NEW_VERTPROG; -} - -static void -nv04_vp_state_delete(struct pipe_context *pipe, void *shader) -{ - struct nv04_context *nv04 = nv04_context(pipe); - - draw_delete_vertex_shader(nv04->draw, (struct draw_vertex_shader *) shader); -} - -static void * -nv04_fp_state_create(struct pipe_context *pipe, - const struct pipe_shader_state *cso) -{ - struct nv04_fragment_program *fp; - - fp = CALLOC(1, sizeof(struct nv04_fragment_program)); - fp->pipe.tokens = tgsi_dup_tokens(cso->tokens); - - return (void *)fp; -} - -static void -nv04_fp_state_bind(struct pipe_context *pipe, void *hwcso) -{ - struct nv04_context *nv04 = nv04_context(pipe); - struct nv04_fragment_program *fp = hwcso; - - nv04->fragprog.current = fp; - nv04->dirty |= NV04_NEW_FRAGPROG; -} - -static void -nv04_fp_state_delete(struct pipe_context *pipe, void *hwcso) -{ - struct nv04_context *nv04 = nv04_context(pipe); - struct nv04_fragment_program *fp = hwcso; - - nv04_fragprog_destroy(nv04, fp); - free((void*)fp->pipe.tokens); - free(fp); -} - -static void -nv04_set_blend_color(struct pipe_context *pipe, - const struct pipe_blend_color *bcol) -{ -} - -static void -nv04_set_clip_state(struct pipe_context *pipe, - const struct pipe_clip_state *clip) -{ -} - -static void -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_screen *pscreen = pipe->screen; - - assert(shader < PIPE_SHADER_TYPES); - assert(index == 0); - - if (buf) { - void *mapped; - if (buf->buffer && buf->buffer->size && - (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)); - pipe_buffer_unmap(pscreen, buf->buffer); - } - } -} - -static void -nv04_set_framebuffer_state(struct pipe_context *pipe, - const struct pipe_framebuffer_state *fb) -{ - struct nv04_context *nv04 = nv04_context(pipe); - - nv04->framebuffer = (struct pipe_framebuffer_state*)fb; - - nv04->dirty |= NV04_NEW_FRAMEBUFFER; -} -static void -nv04_set_polygon_stipple(struct pipe_context *pipe, - const struct pipe_poly_stipple *stipple) -{ - NOUVEAU_ERR("line stipple hahaha\n"); -} - -static void -nv04_set_scissor_state(struct pipe_context *pipe, - const struct pipe_scissor_state *s) -{ -/* struct nv04_context *nv04 = nv04_context(pipe); - - // XXX - BEGIN_RING(fahrenheit, NV04_TEXTURED_TRIANGLE_SCISSOR_HORIZ, 2); - OUT_RING (((s->maxx - s->minx) << 16) | s->minx); - OUT_RING (((s->maxy - s->miny) << 16) | s->miny);*/ -} - -static void -nv04_set_viewport_state(struct pipe_context *pipe, - const struct pipe_viewport_state *viewport) -{ - struct nv04_context *nv04 = nv04_context(pipe); - - nv04->viewport = *viewport; - - draw_set_viewport_state(nv04->draw, &nv04->viewport); -} - -static void -nv04_set_vertex_buffers(struct pipe_context *pipe, unsigned count, - const struct pipe_vertex_buffer *buffers) -{ - struct nv04_context *nv04 = nv04_context(pipe); - - memcpy(nv04->vtxbuf, buffers, count * sizeof(buffers[0])); - nv04->dirty |= NV04_NEW_VTXARRAYS; - - draw_set_vertex_buffers(nv04->draw, count, buffers); -} - -static void -nv04_set_vertex_elements(struct pipe_context *pipe, unsigned count, - const struct pipe_vertex_element *elements) -{ - struct nv04_context *nv04 = nv04_context(pipe); - - memcpy(nv04->vtxelt, elements, sizeof(*elements) * count); - nv04->dirty |= NV04_NEW_VTXARRAYS; - - draw_set_vertex_elements(nv04->draw, count, elements); -} - -void -nv04_init_state_functions(struct nv04_context *nv04) -{ - nv04->pipe.create_blend_state = nv04_blend_state_create; - nv04->pipe.bind_blend_state = nv04_blend_state_bind; - nv04->pipe.delete_blend_state = nv04_blend_state_delete; - - nv04->pipe.create_sampler_state = nv04_sampler_state_create; - nv04->pipe.bind_fragment_sampler_states = nv04_sampler_state_bind; - nv04->pipe.delete_sampler_state = nv04_sampler_state_delete; - nv04->pipe.set_fragment_sampler_textures = nv04_set_sampler_texture; - - nv04->pipe.create_rasterizer_state = nv04_rasterizer_state_create; - nv04->pipe.bind_rasterizer_state = nv04_rasterizer_state_bind; - nv04->pipe.delete_rasterizer_state = nv04_rasterizer_state_delete; - - nv04->pipe.create_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_create; - nv04->pipe.bind_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_bind; - nv04->pipe.delete_depth_stencil_alpha_state = nv04_depth_stencil_alpha_state_delete; - - nv04->pipe.create_vs_state = nv04_vp_state_create; - nv04->pipe.bind_vs_state = nv04_vp_state_bind; - nv04->pipe.delete_vs_state = nv04_vp_state_delete; - - nv04->pipe.create_fs_state = nv04_fp_state_create; - nv04->pipe.bind_fs_state = nv04_fp_state_bind; - nv04->pipe.delete_fs_state = nv04_fp_state_delete; - - nv04->pipe.set_blend_color = nv04_set_blend_color; - nv04->pipe.set_clip_state = nv04_set_clip_state; - nv04->pipe.set_constant_buffer = nv04_set_constant_buffer; - nv04->pipe.set_framebuffer_state = nv04_set_framebuffer_state; - nv04->pipe.set_polygon_stipple = nv04_set_polygon_stipple; - nv04->pipe.set_scissor_state = nv04_set_scissor_state; - nv04->pipe.set_viewport_state = nv04_set_viewport_state; - - nv04->pipe.set_vertex_buffers = nv04_set_vertex_buffers; - nv04->pipe.set_vertex_elements = nv04_set_vertex_elements; -} - diff --git a/src/gallium/drivers/nv04/nv04_state.h b/src/gallium/drivers/nv04/nv04_state.h deleted file mode 100644 index 81d1d2ebaa..0000000000 --- a/src/gallium/drivers/nv04/nv04_state.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef __NV04_STATE_H__ -#define __NV04_STATE_H__ - -#include "pipe/p_state.h" -#include "tgsi/tgsi_scan.h" - -struct nv04_blend_state { - uint32_t b_enable; - uint32_t b_src; - uint32_t b_dst; -}; - -struct nv04_fragtex_state { - uint32_t format; -}; - -struct nv04_sampler_state { - uint32_t filter; - uint32_t format; -}; - -struct nv04_depth_stencil_alpha_state { - uint32_t control; -}; - -struct nv04_rasterizer_state { - uint32_t blend; - - const struct pipe_rasterizer_state *templ; -}; - -struct nv04_miptree { - struct pipe_texture base; - struct nouveau_bo *bo; - - struct pipe_buffer *buffer; - uint total_size; - - struct { - uint pitch; - uint *image_offset; - } level[PIPE_MAX_TEXTURE_LEVELS]; -}; - -struct nv04_fragment_program_data { - unsigned offset; - unsigned index; -}; - -struct nv04_fragment_program { - struct pipe_shader_state pipe; - struct tgsi_shader_info info; - - boolean translated; - boolean on_hw; - unsigned samplers; - - uint32_t *insn; - int insn_len; - - struct nv04_fragment_program_data *consts; - unsigned nr_consts; - - struct pipe_buffer *buffer; - - uint32_t fp_control; - uint32_t fp_reg_control; -}; - - - -#endif diff --git a/src/gallium/drivers/nv04/nv04_state_emit.c b/src/gallium/drivers/nv04/nv04_state_emit.c deleted file mode 100644 index b8d6dc560f..0000000000 --- a/src/gallium/drivers/nv04/nv04_state_emit.c +++ /dev/null @@ -1,246 +0,0 @@ -#include "nv04_context.h" -#include "nv04_state.h" - -static void nv04_vertex_layout(struct pipe_context* pipe) -{ - struct nv04_context *nv04 = nv04_context(pipe); - struct nv04_fragment_program *fp = nv04->fragprog.current; - uint32_t src = 0; - int i; - struct vertex_info vinfo; - - memset(&vinfo, 0, sizeof(vinfo)); - - for (i = 0; i < fp->info.num_inputs; i++) { - int isn = fp->info.input_semantic_name[i]; - int isi = fp->info.input_semantic_index[i]; - switch (isn) { - case TGSI_SEMANTIC_POSITION: - draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++); - break; - case TGSI_SEMANTIC_COLOR: - draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++); - break; - default: - case TGSI_SEMANTIC_GENERIC: - draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++); - break; - case TGSI_SEMANTIC_FOG: - draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++); - break; - } - } - - printf("%d vertex input\n",fp->info.num_inputs); - draw_compute_vertex_size(&vinfo); -} - -static uint32_t nv04_blend_func(uint32_t f) -{ - switch ( f ) { - case PIPE_BLENDFACTOR_ZERO: return 0x1; - case PIPE_BLENDFACTOR_ONE: return 0x2; - case PIPE_BLENDFACTOR_SRC_COLOR: return 0x3; - case PIPE_BLENDFACTOR_INV_SRC_COLOR: return 0x4; - case PIPE_BLENDFACTOR_SRC_ALPHA: return 0x5; - case PIPE_BLENDFACTOR_INV_SRC_ALPHA: return 0x6; - case PIPE_BLENDFACTOR_DST_ALPHA: return 0x7; - case PIPE_BLENDFACTOR_INV_DST_ALPHA: return 0x8; - case PIPE_BLENDFACTOR_DST_COLOR: return 0x9; - case PIPE_BLENDFACTOR_INV_DST_COLOR: return 0xA; - case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE: return 0xB; - } - NOUVEAU_MSG("Unable to find the blend function 0x%x\n",f); - return 0; -} - -static void nv04_emit_control(struct nv04_context* nv04) -{ - uint32_t control = nv04->dsa->control; - struct nv04_screen *screen = nv04->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *fahrenheit = screen->fahrenheit; - - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_CONTROL, 1); - OUT_RING(chan, control); -} - -static void nv04_emit_blend(struct nv04_context* nv04) -{ - struct nv04_screen *screen = nv04->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *fahrenheit = screen->fahrenheit; - uint32_t blend; - - blend=0x4; // texture MODULATE_ALPHA - blend|=0x20; // alpha is MSB - blend|=(2<<6); // flat shading - blend|=(1<<8); // persp correct - blend|=(0<<16); // no fog - blend|=(nv04->blend->b_enable<<20); - blend|=(nv04_blend_func(nv04->blend->b_src)<<24); - blend|=(nv04_blend_func(nv04->blend->b_dst)<<28); - - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_BLEND, 1); - OUT_RING(chan, blend); -} - -static void nv04_emit_sampler(struct nv04_context *nv04, int unit) -{ - struct nv04_miptree *nv04mt = nv04->tex_miptree[unit]; - struct pipe_texture *pt = &nv04mt->base; - struct nv04_screen *screen = nv04->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *fahrenheit = screen->fahrenheit; - struct nouveau_bo *bo = nouveau_bo(nv04mt->buffer); - - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_OFFSET, 3); - OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); - OUT_RELOCd(chan, bo, (nv04->fragtex.format | nv04->sampler[unit]->format), NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/); - OUT_RING(chan, nv04->sampler[unit]->filter); -} - -static void nv04_state_emit_framebuffer(struct nv04_context* nv04) -{ - struct pipe_framebuffer_state* fb = nv04->framebuffer; - struct nv04_surface *rt, *zeta; - uint32_t rt_format, w, h; - int colour_format = 0, zeta_format = 0; - struct nv04_miptree *nv04mt = 0; - struct nv04_screen *screen = nv04->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *context_surfaces_3d = screen->context_surfaces_3d; - struct nouveau_bo *bo; - - w = fb->cbufs[0]->width; - h = fb->cbufs[0]->height; - colour_format = fb->cbufs[0]->format; - rt = (struct nv04_surface *)fb->cbufs[0]; - - if (fb->zsbuf) { - if (colour_format) { - assert(w == fb->zsbuf->width); - assert(h == fb->zsbuf->height); - } else { - w = fb->zsbuf->width; - h = fb->zsbuf->height; - } - - zeta_format = fb->zsbuf->format; - zeta = (struct nv04_surface *)fb->zsbuf; - } - - switch (colour_format) { - case PIPE_FORMAT_A8R8G8B8_UNORM: - case 0: - rt_format = 0x108; - break; - case PIPE_FORMAT_R5G6B5_UNORM: - rt_format = 0x103; - break; - default: - assert(0); - } - - BEGIN_RING(chan, context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_FORMAT, 1); - OUT_RING(chan, rt_format); - - nv04mt = (struct nv04_miptree *)rt->base.texture; - bo = nouveau_bo(nv04mt->buffer); - /* FIXME pitches have to be aligned ! */ - BEGIN_RING(chan, context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_PITCH, 2); - OUT_RING(chan, rt->pitch|(zeta->pitch<<16)); - OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - if (fb->zsbuf) { - nv04mt = (struct nv04_miptree *)zeta->base.texture; - BEGIN_RING(chan, context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA, 1); - OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - } -} - -void -nv04_emit_hw_state(struct nv04_context *nv04) -{ - struct nv04_screen *screen = nv04->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *fahrenheit = screen->fahrenheit; - struct nouveau_grobj *context_surfaces_3d = screen->context_surfaces_3d; - int i; - - if (nv04->dirty & NV04_NEW_VERTPROG) { - //nv04_vertprog_bind(nv04, nv04->vertprog.current); - nv04->dirty &= ~NV04_NEW_VERTPROG; - } - - if (nv04->dirty & NV04_NEW_FRAGPROG) { - nv04_fragprog_bind(nv04, nv04->fragprog.current); - nv04->dirty &= ~NV04_NEW_FRAGPROG; - nv04->dirty_samplers |= (1<<10); - nv04->dirty_samplers = 0; - } - - if (nv04->dirty & NV04_NEW_CONTROL) { - nv04->dirty &= ~NV04_NEW_CONTROL; - - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_CONTROL, 1); - OUT_RING(chan, nv04->dsa->control); - } - - if (nv04->dirty & NV04_NEW_BLEND) { - nv04->dirty &= ~NV04_NEW_BLEND; - - nv04_emit_blend(nv04); - } - - if (nv04->dirty & NV04_NEW_VTXARRAYS) { - nv04->dirty &= ~NV04_NEW_VTXARRAYS; - nv04_vertex_layout(nv04); - } - - if (nv04->dirty & NV04_NEW_SAMPLER) { - nv04->dirty &= ~NV04_NEW_SAMPLER; - - nv04_emit_sampler(nv04, 0); - } - - if (nv04->dirty & NV04_NEW_VIEWPORT) { - nv04->dirty &= ~NV04_NEW_VIEWPORT; -// nv04_state_emit_viewport(nv04); - } - - if (nv04->dirty & NV04_NEW_FRAMEBUFFER) { - nv04->dirty &= ~NV04_NEW_FRAMEBUFFER; - nv04_state_emit_framebuffer(nv04); - } - - /* Emit relocs for every referenced buffer. - * This is to ensure the bufmgr has an accurate idea of how - * the buffer is used. This isn't very efficient, but we don't - * seem to take a significant performance hit. Will be improved - * at some point. Vertex arrays are emitted by nv04_vbo.c - */ - - /* Render target */ - unsigned rt_pitch = ((struct nv04_surface *)nv04->rt)->pitch; - unsigned zeta_pitch = ((struct nv04_surface *)nv04->zeta)->pitch; - - BEGIN_RING(chan, context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_PITCH, 2); - OUT_RING(chan, rt_pitch|(zeta_pitch<<16)); - OUT_RELOCl(chan, nouveau_bo(nv04->rt), 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - if (nv04->zeta) { - BEGIN_RING(chan, context_surfaces_3d, NV04_CONTEXT_SURFACES_3D_OFFSET_ZETA, 1); - OUT_RELOCl(chan, nouveau_bo(nv04->zeta), 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - } - - /* Texture images */ - for (i = 0; i < 1; i++) { - if (!(nv04->fp_samplers & (1 << i))) - continue; - struct nv04_miptree *nv04mt = nv04->tex_miptree[i]; - struct nouveau_bo *bo = nouveau_bo(nv04mt->buffer); - BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_OFFSET, 2); - OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); - OUT_RELOCd(chan, bo, (nv04->fragtex.format | nv04->sampler[i]->format), NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/); - } -} - diff --git a/src/gallium/drivers/nv04/nv04_surface.c b/src/gallium/drivers/nv04/nv04_surface.c deleted file mode 100644 index 0387ff4e78..0000000000 --- a/src/gallium/drivers/nv04/nv04_surface.c +++ /dev/null @@ -1,63 +0,0 @@ - -/************************************************************************** - * - * Copyright 2003 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 "nv04_context.h" -#include "pipe/p_defines.h" -#include "pipe/internal/p_winsys_screen.h" -#include "pipe/p_inlines.h" -#include "util/u_tile.h" - -static void -nv04_surface_copy(struct pipe_context *pipe, - struct pipe_surface *dest, unsigned destx, unsigned desty, - struct pipe_surface *src, unsigned srcx, unsigned srcy, - unsigned width, unsigned height) -{ - struct nv04_context *nv04 = nv04_context(pipe); - struct nv04_surface_2d *eng2d = nv04->screen->eng2d; - - eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height); -} - -static void -nv04_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, - unsigned destx, unsigned desty, unsigned width, - unsigned height, unsigned value) -{ - struct nv04_context *nv04 = nv04_context(pipe); - struct nv04_surface_2d *eng2d = nv04->screen->eng2d; - - eng2d->fill(eng2d, dest, destx, desty, width, height, value); -} - -void -nv04_init_surface_functions(struct nv04_context *nv04) -{ - nv04->pipe.surface_copy = nv04_surface_copy; - nv04->pipe.surface_fill = nv04_surface_fill; -} diff --git a/src/gallium/drivers/nv04/nv04_transfer.c b/src/gallium/drivers/nv04/nv04_transfer.c deleted file mode 100644 index 2dd2e146a8..0000000000 --- a/src/gallium/drivers/nv04/nv04_transfer.c +++ /dev/null @@ -1,178 +0,0 @@ -#include <pipe/p_state.h> -#include <pipe/p_defines.h> -#include <pipe/p_inlines.h> -#include <util/u_format.h> -#include <util/u_memory.h> -#include <util/u_math.h> -#include <nouveau/nouveau_winsys.h> -#include "nv04_context.h" -#include "nv04_screen.h" -#include "nv04_state.h" - -struct nv04_transfer { - struct pipe_transfer base; - struct pipe_surface *surface; - boolean direct; -}; - -static void -nv04_compatible_transfer_tex(struct pipe_texture *pt, unsigned width, unsigned height, - struct pipe_texture *template) -{ - memset(template, 0, sizeof(struct pipe_texture)); - template->target = pt->target; - template->format = pt->format; - template->width0 = width; - template->height0 = height; - template->depth0 = 1; - template->last_level = 0; - template->nr_samples = pt->nr_samples; - - template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC | - NOUVEAU_TEXTURE_USAGE_LINEAR; -} - -static struct pipe_transfer * -nv04_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, - unsigned face, unsigned level, unsigned zslice, - enum pipe_transfer_usage usage, - unsigned x, unsigned y, unsigned w, unsigned h) -{ - struct nv04_miptree *mt = (struct nv04_miptree *)pt; - struct nv04_transfer *tx; - struct pipe_texture tx_tex_template, *tx_tex; - - tx = CALLOC_STRUCT(nv04_transfer); - if (!tx) - return NULL; - - pipe_texture_reference(&tx->base.texture, pt); - tx->base.x = x; - tx->base.y = y; - tx->base.width = w; - tx->base.height = h; - tx->base.stride = mt->level[level].pitch; - tx->base.usage = usage; - tx->base.face = face; - tx->base.level = level; - tx->base.zslice = zslice; - - /* Direct access to texture */ - if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC || - debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) && - pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) - { - tx->direct = true; - tx->surface = pscreen->get_tex_surface(pscreen, pt, - 0, 0, 0, - pipe_transfer_buffer_flags(&tx->base)); - return &tx->base; - } - - tx->direct = false; - - nv04_compatible_transfer_tex(pt, w, h, &tx_tex_template); - - tx_tex = pscreen->texture_create(pscreen, &tx_tex_template); - if (!tx_tex) - { - FREE(tx); - return NULL; - } - - tx->base.stride = ((struct nv04_miptree*)tx_tex)->level[0].pitch; - - tx->surface = pscreen->get_tex_surface(pscreen, tx_tex, - face, level, zslice, - pipe_transfer_buffer_flags(&tx->base)); - - pipe_texture_reference(&tx_tex, NULL); - - if (!tx->surface) - { - pipe_surface_reference(&tx->surface, NULL); - FREE(tx); - return NULL; - } - - if (usage & PIPE_TRANSFER_READ) { - struct nv04_screen *nvscreen = nv04_screen(pscreen); - struct pipe_surface *src; - - src = pscreen->get_tex_surface(pscreen, pt, - face, level, zslice, - PIPE_BUFFER_USAGE_GPU_READ); - - /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ - /* TODO: Check if SIFM can un-swizzle */ - nvscreen->eng2d->copy(nvscreen->eng2d, - tx->surface, 0, 0, - src, x, y, - w, h); - - pipe_surface_reference(&src, NULL); - } - - return &tx->base; -} - -static void -nv04_transfer_del(struct pipe_transfer *ptx) -{ - struct nv04_transfer *tx = (struct nv04_transfer *)ptx; - - if (!tx->direct && (ptx->usage & PIPE_TRANSFER_WRITE)) { - struct pipe_screen *pscreen = ptx->texture->screen; - struct nv04_screen *nvscreen = nv04_screen(pscreen); - struct pipe_surface *dst; - - dst = pscreen->get_tex_surface(pscreen, ptx->texture, - ptx->face, ptx->level, ptx->zslice, - PIPE_BUFFER_USAGE_GPU_WRITE); - - /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ - nvscreen->eng2d->copy(nvscreen->eng2d, - dst, tx->base.x, tx->base.y, - tx->surface, 0, 0, - tx->base.width, tx->base.height); - - pipe_surface_reference(&dst, NULL); - } - - pipe_surface_reference(&tx->surface, NULL); - pipe_texture_reference(&ptx->texture, NULL); - FREE(ptx); -} - -static void * -nv04_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) -{ - struct nv04_transfer *tx = (struct nv04_transfer *)ptx; - struct nv04_surface *ns = (struct nv04_surface *)tx->surface; - struct nv04_miptree *mt = (struct nv04_miptree *)tx->surface->texture; - void *map = pipe_buffer_map(pscreen, mt->buffer, - pipe_transfer_buffer_flags(ptx)); - - if(!tx->direct) - return map + ns->base.offset; - else - return map + ns->base.offset + ptx->y * ns->pitch + ptx->x * util_format_get_blocksize(ptx->texture->format); -} - -static void -nv04_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) -{ - struct nv04_transfer *tx = (struct nv04_transfer *)ptx; - struct nv04_miptree *mt = (struct nv04_miptree *)tx->surface->texture; - - pipe_buffer_unmap(pscreen, mt->buffer); -} - -void -nv04_screen_init_transfer_functions(struct pipe_screen *pscreen) -{ - pscreen->get_tex_transfer = nv04_transfer_new; - pscreen->tex_transfer_destroy = nv04_transfer_del; - pscreen->transfer_map = nv04_transfer_map; - pscreen->transfer_unmap = nv04_transfer_unmap; -} diff --git a/src/gallium/drivers/nv04/nv04_vbo.c b/src/gallium/drivers/nv04/nv04_vbo.c deleted file mode 100644 index 3484771814..0000000000 --- a/src/gallium/drivers/nv04/nv04_vbo.c +++ /dev/null @@ -1,78 +0,0 @@ -#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" - -#include "nouveau/nouveau_channel.h" -#include "nouveau/nouveau_pushbuf.h" - -void nv04_draw_elements( struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, - 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; - - nv04_emit_hw_state(nv04); - - /* - * Map vertex buffers - */ - for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { - if (nv04->vtxbuf[i].buffer) { - void *buf - = 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_buffer_map(pscreen, indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); - draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes); - } - else { - /* no index/element buffer */ - draw_set_mapped_element_buffer(draw, 0, NULL); - } - - draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, - nv04->constbuf[PIPE_SHADER_VERTEX], - nv04->constbuf_nr[PIPE_SHADER_VERTEX]); - - /* draw! */ - draw_arrays(nv04->draw, prim, start, count); - - /* - * unmap vertex/index buffers - */ - for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { - if (nv04->vtxbuf[i].buffer) { - pipe_buffer_unmap(pscreen, nv04->vtxbuf[i].buffer); - draw_set_mapped_vertex_buffer(draw, i, NULL); - } - } - if (indexBuffer) { - pipe_buffer_unmap(pscreen, indexBuffer); - draw_set_mapped_element_buffer(draw, 0, NULL); - } -} - -void nv04_draw_arrays( struct pipe_context *pipe, - unsigned prim, unsigned start, unsigned count) -{ - printf("coucou in draw arrays\n"); - nv04_draw_elements(pipe, NULL, 0, prim, start, count); -} - - - diff --git a/src/gallium/drivers/nv10/Makefile b/src/gallium/drivers/nv10/Makefile deleted file mode 100644 index 62677f5194..0000000000 --- a/src/gallium/drivers/nv10/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -TOP = ../../../.. -include $(TOP)/configs/current - -LIBNAME = nv10 - -C_SOURCES = \ - nv10_clear.c \ - nv10_context.c \ - nv10_fragprog.c \ - nv10_fragtex.c \ - nv10_miptree.c \ - nv10_prim_vbuf.c \ - nv10_screen.c \ - nv10_state.c \ - nv10_state_emit.c \ - nv10_surface.c \ - nv10_transfer.c \ - nv10_vbo.c - -include ../../Makefile.template diff --git a/src/gallium/drivers/nv10/nv10_clear.c b/src/gallium/drivers/nv10/nv10_clear.c deleted file mode 100644 index a39a2b5f52..0000000000 --- a/src/gallium/drivers/nv10/nv10_clear.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "util/u_clear.h" - -#include "nv10_context.h" - -void -nv10_clear(struct pipe_context *pipe, unsigned buffers, - const float *rgba, double depth, unsigned stencil) -{ - util_clear(pipe, nv10_context(pipe)->framebuffer, buffers, rgba, depth, - stencil); -} diff --git a/src/gallium/drivers/nv10/nv10_context.c b/src/gallium/drivers/nv10/nv10_context.c deleted file mode 100644 index 1ecb73d06e..0000000000 --- a/src/gallium/drivers/nv10/nv10_context.c +++ /dev/null @@ -1,298 +0,0 @@ -#include "draw/draw_context.h" -#include "pipe/p_defines.h" -#include "pipe/internal/p_winsys_screen.h" - -#include "nv10_context.h" -#include "nv10_screen.h" - -static void -nv10_flush(struct pipe_context *pipe, unsigned flags, - struct pipe_fence_handle **fence) -{ - struct nv10_context *nv10 = nv10_context(pipe); - struct nv10_screen *screen = nv10->screen; - struct nouveau_channel *chan = screen->base.channel; - - draw_flush(nv10->draw); - - FIRE_RING(chan); - if (fence) - *fence = NULL; -} - -static void -nv10_destroy(struct pipe_context *pipe) -{ - struct nv10_context *nv10 = nv10_context(pipe); - - if (nv10->draw) - draw_destroy(nv10->draw); - - FREE(nv10); -} - -static void nv10_init_hwctx(struct nv10_context *nv10) -{ - struct nv10_screen *screen = nv10->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *celsius = screen->celsius; - int i; - float projectionmatrix[16]; - - BEGIN_RING(chan, celsius, NV10TCL_DMA_NOTIFY, 1); - OUT_RING (chan, screen->sync->handle); - BEGIN_RING(chan, celsius, NV10TCL_DMA_IN_MEMORY0, 2); - OUT_RING (chan, chan->vram->handle); - OUT_RING (chan, chan->gart->handle); - BEGIN_RING(chan, celsius, NV10TCL_DMA_IN_MEMORY2, 2); - OUT_RING (chan, chan->vram->handle); - OUT_RING (chan, chan->vram->handle); - - BEGIN_RING(chan, celsius, NV10TCL_NOP, 1); - OUT_RING (chan, 0); - - BEGIN_RING(chan, celsius, NV10TCL_RT_HORIZ, 2); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - - BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 1); - OUT_RING (chan, (0x7ff<<16)|0x800); - BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_VERT(0), 1); - OUT_RING (chan, (0x7ff<<16)|0x800); - - for (i=1;i<8;i++) { - BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(i), 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_VERT(i), 1); - OUT_RING (chan, 0); - } - - BEGIN_RING(chan, celsius, 0x290, 1); - OUT_RING (chan, (0x10<<16)|1); - BEGIN_RING(chan, celsius, 0x3f4, 1); - OUT_RING (chan, 0); - - BEGIN_RING(chan, celsius, NV10TCL_NOP, 1); - OUT_RING (chan, 0); - - if (nv10->screen->celsius->grclass != NV10TCL) { - /* For nv11, nv17 */ - BEGIN_RING(chan, celsius, 0x120, 3); - OUT_RING (chan, 0); - OUT_RING (chan, 1); - OUT_RING (chan, 2); - - BEGIN_RING(chan, celsius, NV10TCL_NOP, 1); - OUT_RING (chan, 0); - } - - BEGIN_RING(chan, celsius, NV10TCL_NOP, 1); - OUT_RING (chan, 0); - - /* Set state */ - BEGIN_RING(chan, celsius, NV10TCL_FOG_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_ALPHA_FUNC_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_ALPHA_FUNC_FUNC, 2); - OUT_RING (chan, 0x207); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_TX_ENABLE(0), 2); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - - BEGIN_RING(chan, celsius, NV10TCL_RC_IN_ALPHA(0), 12); - OUT_RING (chan, 0x30141010); - OUT_RING (chan, 0); - OUT_RING (chan, 0x20040000); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - OUT_RING (chan, 0x00000c00); - OUT_RING (chan, 0); - OUT_RING (chan, 0x00000c00); - OUT_RING (chan, 0x18000000); - OUT_RING (chan, 0x300e0300); - OUT_RING (chan, 0x0c091c80); - - BEGIN_RING(chan, celsius, NV10TCL_BLEND_FUNC_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_DITHER_ENABLE, 2); - OUT_RING (chan, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_LINE_SMOOTH_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_VERTEX_WEIGHT_ENABLE, 2); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_BLEND_FUNC_SRC, 4); - OUT_RING (chan, 1); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - OUT_RING (chan, 0x8006); - BEGIN_RING(chan, celsius, NV10TCL_STENCIL_MASK, 8); - OUT_RING (chan, 0xff); - OUT_RING (chan, 0x207); - OUT_RING (chan, 0); - OUT_RING (chan, 0xff); - OUT_RING (chan, 0x1e00); - OUT_RING (chan, 0x1e00); - OUT_RING (chan, 0x1e00); - OUT_RING (chan, 0x1d01); - BEGIN_RING(chan, celsius, NV10TCL_NORMALIZE_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_FOG_ENABLE, 2); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_LIGHT_MODEL, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_COLOR_CONTROL, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_ENABLED_LIGHTS, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_POLYGON_OFFSET_POINT_ENABLE, 3); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_DEPTH_FUNC, 1); - OUT_RING (chan, 0x201); - BEGIN_RING(chan, celsius, NV10TCL_DEPTH_WRITE_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_DEPTH_TEST_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_POLYGON_OFFSET_FACTOR, 2); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_POINT_SIZE, 1); - OUT_RING (chan, 8); - BEGIN_RING(chan, celsius, NV10TCL_POINT_PARAMETERS_ENABLE, 2); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_LINE_WIDTH, 1); - OUT_RING (chan, 8); - BEGIN_RING(chan, celsius, NV10TCL_LINE_SMOOTH_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_POLYGON_MODE_FRONT, 2); - OUT_RING (chan, 0x1b02); - OUT_RING (chan, 0x1b02); - BEGIN_RING(chan, celsius, NV10TCL_CULL_FACE, 2); - OUT_RING (chan, 0x405); - OUT_RING (chan, 0x901); - BEGIN_RING(chan, celsius, NV10TCL_POLYGON_SMOOTH_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_CULL_FACE_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_TX_GEN_S(0), 8); - for (i=0;i<8;i++) { - OUT_RING (chan, 0); - } - BEGIN_RING(chan, celsius, NV10TCL_FOG_EQUATION_CONSTANT, 3); - OUT_RING (chan, 0x3fc00000); /* -1.50 */ - OUT_RING (chan, 0xbdb8aa0a); /* -0.09 */ - OUT_RING (chan, 0); /* 0.00 */ - - BEGIN_RING(chan, celsius, NV10TCL_NOP, 1); - OUT_RING (chan, 0); - - BEGIN_RING(chan, celsius, NV10TCL_FOG_MODE, 2); - OUT_RING (chan, 0x802); - OUT_RING (chan, 2); - /* for some reason VIEW_MATRIX_ENABLE need to be 6 instead of 4 when - * using texturing, except when using the texture matrix - */ - BEGIN_RING(chan, celsius, NV10TCL_VIEW_MATRIX_ENABLE, 1); - OUT_RING (chan, 6); - BEGIN_RING(chan, celsius, NV10TCL_COLOR_MASK, 1); - OUT_RING (chan, 0x01010101); - - /* Set vertex component */ - BEGIN_RING(chan, celsius, NV10TCL_VERTEX_COL_4F_R, 4); - OUT_RINGf (chan, 1.0); - OUT_RINGf (chan, 1.0); - OUT_RINGf (chan, 1.0); - OUT_RINGf (chan, 1.0); - BEGIN_RING(chan, celsius, NV10TCL_VERTEX_COL2_3F_R, 3); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - BEGIN_RING(chan, celsius, NV10TCL_VERTEX_NOR_3F_X, 3); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - OUT_RINGf (chan, 1.0); - BEGIN_RING(chan, celsius, NV10TCL_VERTEX_TX0_4F_S, 4); - OUT_RINGf (chan, 0.0); - OUT_RINGf (chan, 0.0); - OUT_RINGf (chan, 0.0); - OUT_RINGf (chan, 1.0); - BEGIN_RING(chan, celsius, NV10TCL_VERTEX_TX1_4F_S, 4); - OUT_RINGf (chan, 0.0); - OUT_RINGf (chan, 0.0); - OUT_RINGf (chan, 0.0); - OUT_RINGf (chan, 1.0); - BEGIN_RING(chan, celsius, NV10TCL_VERTEX_FOG_1F, 1); - OUT_RINGf (chan, 0.0); - BEGIN_RING(chan, celsius, NV10TCL_EDGEFLAG_ENABLE, 1); - OUT_RING (chan, 1); - - memset(projectionmatrix, 0, sizeof(projectionmatrix)); - BEGIN_RING(chan, celsius, NV10TCL_PROJECTION_MATRIX(0), 16); - projectionmatrix[0*4+0] = 1.0; - projectionmatrix[1*4+1] = 1.0; - projectionmatrix[2*4+2] = 1.0; - projectionmatrix[3*4+3] = 1.0; - for (i=0;i<16;i++) { - OUT_RINGf (chan, projectionmatrix[i]); - } - - BEGIN_RING(chan, celsius, NV10TCL_DEPTH_RANGE_NEAR, 2); - OUT_RING (chan, 0.0); - OUT_RINGf (chan, 16777216.0); - - BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_TRANSLATE_X, 4); - OUT_RINGf (chan, -2048.0); - OUT_RINGf (chan, -2048.0); - OUT_RINGf (chan, 16777215.0 * 0.5); - OUT_RING (chan, 0); - - FIRE_RING (chan); -} - -struct pipe_context * -nv10_create(struct pipe_screen *pscreen, unsigned pctx_id) -{ - struct nv10_screen *screen = nv10_screen(pscreen); - struct pipe_winsys *ws = pscreen->winsys; - struct nv10_context *nv10; - struct nouveau_winsys *nvws = screen->nvws; - - nv10 = CALLOC(1, sizeof(struct nv10_context)); - if (!nv10) - return NULL; - nv10->screen = screen; - nv10->pctx_id = pctx_id; - - nv10->nvws = nvws; - - nv10->pipe.winsys = ws; - nv10->pipe.screen = pscreen; - nv10->pipe.destroy = nv10_destroy; - nv10->pipe.draw_arrays = nv10_draw_arrays; - nv10->pipe.draw_elements = nv10_draw_elements; - nv10->pipe.clear = nv10_clear; - nv10->pipe.flush = nv10_flush; - - nv10->pipe.is_texture_referenced = nouveau_is_texture_referenced; - nv10->pipe.is_buffer_referenced = nouveau_is_buffer_referenced; - - nv10_init_surface_functions(nv10); - nv10_init_state_functions(nv10); - - nv10->draw = draw_create(); - assert(nv10->draw); - draw_set_rasterize_stage(nv10->draw, nv10_draw_vbuf_stage(nv10)); - - nv10_init_hwctx(nv10); - - return &nv10->pipe; -} - diff --git a/src/gallium/drivers/nv10/nv10_context.h b/src/gallium/drivers/nv10/nv10_context.h deleted file mode 100644 index ab4b825487..0000000000 --- a/src/gallium/drivers/nv10/nv10_context.h +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef __NV10_CONTEXT_H__ -#define __NV10_CONTEXT_H__ - -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "pipe/p_compiler.h" - -#include "util/u_memory.h" -#include "util/u_math.h" - -#include "draw/draw_vertex.h" - -#include "nouveau/nouveau_winsys.h" -#include "nouveau/nouveau_gldefs.h" -#include "nouveau/nouveau_context.h" - -#include "nv10_state.h" - -#define NOUVEAU_ERR(fmt, args...) \ - fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args); -#define NOUVEAU_MSG(fmt, args...) \ - fprintf(stderr, "nouveau: "fmt, ##args); - -#define NV10_NEW_VERTPROG (1 << 0) -#define NV10_NEW_FRAGPROG (1 << 1) -#define NV10_NEW_VTXARRAYS (1 << 2) -#define NV10_NEW_BLEND (1 << 3) -#define NV10_NEW_BLENDCOL (1 << 4) -#define NV10_NEW_RAST (1 << 5) -#define NV10_NEW_DSA (1 << 6) -#define NV10_NEW_VIEWPORT (1 << 7) -#define NV10_NEW_SCISSOR (1 << 8) -#define NV10_NEW_FRAMEBUFFER (1 << 9) - -#include "nv10_screen.h" - -struct nv10_context { - struct pipe_context pipe; - - struct nouveau_winsys *nvws; - struct nv10_screen *screen; - unsigned pctx_id; - - struct draw_context *draw; - - uint32_t dirty; - - struct nv10_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS]; - struct nv10_miptree *tex_miptree[PIPE_MAX_SAMPLERS]; - unsigned dirty_samplers; - unsigned fp_samplers; - unsigned vp_samplers; - - uint32_t rt_enable; - struct pipe_buffer *rt[4]; - struct pipe_buffer *zeta; - uint32_t lma_offset; - - struct nv10_blend_state *blend; - struct pipe_blend_color *blend_color; - struct nv10_rasterizer_state *rast; - struct nv10_depth_stencil_alpha_state *dsa; - struct pipe_viewport_state *viewport; - struct pipe_scissor_state *scissor; - struct pipe_framebuffer_state *framebuffer; - - //struct pipe_buffer *constbuf[PIPE_SHADER_TYPES]; - float *constbuf[PIPE_SHADER_TYPES][32][4]; - unsigned constbuf_nr[PIPE_SHADER_TYPES]; - - struct vertex_info vertex_info; - - struct { - struct pipe_buffer *buffer; - uint32_t format; - } tex[2]; - - unsigned vb_enable; - struct { - struct pipe_buffer *buffer; - unsigned delta; - } vb[16]; - -/* struct { - - struct nouveau_resource *exec_heap; - struct nouveau_resource *data_heap; - - struct nv10_vertex_program *active; - - struct nv10_vertex_program *current; - } vertprog; -*/ - struct { - struct nv10_fragment_program *active; - - struct nv10_fragment_program *current; - struct pipe_buffer *constant_buf; - } fragprog; - - struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; - struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS]; -}; - -static INLINE struct nv10_context * -nv10_context(struct pipe_context *pipe) -{ - return (struct nv10_context *)pipe; -} - -extern void nv10_init_state_functions(struct nv10_context *nv10); -extern void nv10_init_surface_functions(struct nv10_context *nv10); - -extern void nv10_screen_init_miptree_functions(struct pipe_screen *pscreen); - -/* nv10_clear.c */ -extern void nv10_clear(struct pipe_context *pipe, unsigned buffers, - const float *rgba, double depth, unsigned stencil); - - -/* nv10_draw.c */ -extern struct draw_stage *nv10_draw_render_stage(struct nv10_context *nv10); - -/* nv10_fragprog.c */ -extern void nv10_fragprog_bind(struct nv10_context *, - struct nv10_fragment_program *); -extern void nv10_fragprog_destroy(struct nv10_context *, - struct nv10_fragment_program *); - -/* nv10_fragtex.c */ -extern void nv10_fragtex_bind(struct nv10_context *); - -/* nv10_prim_vbuf.c */ -struct draw_stage *nv10_draw_vbuf_stage( struct nv10_context *nv10 ); -extern void nv10_vtxbuf_bind(struct nv10_context* nv10); - -/* nv10_state.c and friends */ -extern void nv10_emit_hw_state(struct nv10_context *nv10); -extern void nv10_state_tex_update(struct nv10_context *nv10); - -/* nv10_vbo.c */ -extern void nv10_draw_arrays(struct pipe_context *, unsigned mode, - unsigned start, unsigned count); -extern void nv10_draw_elements( struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, - unsigned indexSize, - unsigned prim, unsigned start, unsigned count); - - -#endif diff --git a/src/gallium/drivers/nv10/nv10_fragprog.c b/src/gallium/drivers/nv10/nv10_fragprog.c deleted file mode 100644 index 698db5a16a..0000000000 --- a/src/gallium/drivers/nv10/nv10_fragprog.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" - -#include "pipe/p_shader_tokens.h" -#include "tgsi/tgsi_parse.h" -#include "tgsi/tgsi_util.h" - -#include "nv10_context.h" - -void -nv10_fragprog_bind(struct nv10_context *nv10, struct nv10_fragment_program *fp) -{ -} - -void -nv10_fragprog_destroy(struct nv10_context *nv10, - struct nv10_fragment_program *fp) -{ -} - diff --git a/src/gallium/drivers/nv10/nv10_fragtex.c b/src/gallium/drivers/nv10/nv10_fragtex.c deleted file mode 100644 index c1f7ccb9ab..0000000000 --- a/src/gallium/drivers/nv10/nv10_fragtex.c +++ /dev/null @@ -1,130 +0,0 @@ -#include "nv10_context.h" -#include "nouveau/nouveau_util.h" - -#define _(m,tf) \ -{ \ - TRUE, \ - PIPE_FORMAT_##m, \ - NV10TCL_TX_FORMAT_FORMAT_##tf, \ -} - -struct nv10_texture_format { - boolean defined; - uint pipe; - int format; -}; - -static struct nv10_texture_format -nv10_texture_formats[] = { - _(A8R8G8B8_UNORM, A8R8G8B8), - _(A1R5G5B5_UNORM, A1R5G5B5), - _(A4R4G4B4_UNORM, A4R4G4B4), - _(L8_UNORM , L8 ), - _(A8_UNORM , A8 ), - _(A8L8_UNORM , A8L8 ), -// _(RGB_DXT1 , DXT1, ), -// _(RGBA_DXT1 , DXT1, ), -// _(RGBA_DXT3 , DXT3, ), -// _(RGBA_DXT5 , DXT5, ), - {}, -}; - -static struct nv10_texture_format * -nv10_fragtex_format(uint pipe_format) -{ - struct nv10_texture_format *tf = nv10_texture_formats; - - while (tf->defined) { - if (tf->pipe == pipe_format) - return tf; - tf++; - } - - return NULL; -} - - -static void -nv10_fragtex_build(struct nv10_context *nv10, int unit) -{ -#if 0 - struct nv10_sampler_state *ps = nv10->tex_sampler[unit]; - struct nv10_miptree *nv10mt = nv10->tex_miptree[unit]; - struct pipe_texture *pt = &nv10mt->base; - struct nv10_texture_format *tf; - struct nv10_screen *screen = nv10->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *celsius = screen->celsius; - uint32_t txf, txs, txp; - - tf = nv10_fragtex_format(pt->format); - if (!tf || !tf->defined) { - NOUVEAU_ERR("Unsupported texture format: 0x%x\n", pt->format); - return; - } - - txf = tf->format << 8; - txf |= (pt->last_level + 1) << 16; - txf |= log2i(pt->width0) << 20; - txf |= log2i(pt->height0) << 24; - txf |= log2i(pt->depth0) << 28; - txf |= 8; - - switch (pt->target) { - case PIPE_TEXTURE_CUBE: - txf |= NV10TCL_TX_FORMAT_CUBE_MAP; - /* fall-through */ - case PIPE_TEXTURE_2D: - txf |= (2<<4); - break; - case PIPE_TEXTURE_1D: - txf |= (1<<4); - break; - default: - NOUVEAU_ERR("Unknown target %d\n", pt->target); - return; - } - - BEGIN_RING(chan, celsius, NV10TCL_TX_OFFSET(unit), 8); - OUT_RELOCl(chan, nouveau_bo(nv10mt->buffer), 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); - OUT_RELOCd(chan, nouveau_bo(nv10mt->buffer),txf,NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/); - OUT_RING (chan, ps->wrap); - OUT_RING (chan, 0x40000000); /* enable */ - OUT_RING (chan, txs); - OUT_RING (chan, ps->filt | 0x2000 /* magic */); - OUT_RING (chan, (pt->width0 << 16) | pt->height0); - OUT_RING (chan, ps->bcol); -#endif -} - -void -nv10_fragtex_bind(struct nv10_context *nv10) -{ -#if 0 - struct nv10_fragment_program *fp = nv10->fragprog.active; - struct nv10_screen *screen = nv10->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *celsius = screen->celsius; - unsigned samplers, unit; - - samplers = nv10->fp_samplers & ~fp->samplers; - while (samplers) { - unit = ffs(samplers) - 1; - samplers &= ~(1 << unit); - - BEGIN_RING(chan, celsius, NV10TCL_TX_ENABLE(unit), 1); - OUT_RING (chan, 0); - } - - samplers = nv10->dirty_samplers & fp->samplers; - while (samplers) { - unit = ffs(samplers) - 1; - samplers &= ~(1 << unit); - - nv10_fragtex_build(nv10, unit); - } - - nv10->fp_samplers = fp->samplers; -#endif -} - diff --git a/src/gallium/drivers/nv10/nv10_miptree.c b/src/gallium/drivers/nv10/nv10_miptree.c deleted file mode 100644 index 908482ad85..0000000000 --- a/src/gallium/drivers/nv10/nv10_miptree.c +++ /dev/null @@ -1,165 +0,0 @@ -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "pipe/p_inlines.h" -#include "util/u_format.h" -#include "util/u_math.h" - -#include "nv10_context.h" -#include "nv10_screen.h" - -static void -nv10_miptree_layout(struct nv10_miptree *nv10mt) -{ - struct pipe_texture *pt = &nv10mt->base; - boolean swizzled = FALSE; - uint width = pt->width0; - uint offset = 0; - int nr_faces, l, f; - - if (pt->target == PIPE_TEXTURE_CUBE) { - nr_faces = 6; - } else { - nr_faces = 1; - } - - for (l = 0; l <= pt->last_level; l++) { - if (swizzled) - nv10mt->level[l].pitch = util_format_get_stride(pt->format, width); - else - nv10mt->level[l].pitch = util_format_get_stride(pt->format, pt->width0); - nv10mt->level[l].pitch = (nv10mt->level[l].pitch + 63) & ~63; - - nv10mt->level[l].image_offset = - CALLOC(nr_faces, sizeof(unsigned)); - - width = u_minify(width, 1); - - } - - for (f = 0; f < nr_faces; f++) { - for (l = 0; l <= pt->last_level; l++) { - nv10mt->level[l].image_offset[f] = offset; - offset += nv10mt->level[l].pitch * u_minify(pt->height0, l); - } - } - - nv10mt->total_size = offset; -} - -static struct pipe_texture * -nv10_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt, - const unsigned *stride, struct pipe_buffer *pb) -{ - struct nv10_miptree *mt; - - /* Only supports 2D, non-mipmapped textures for the moment */ - if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 || - pt->depth0 != 1) - return NULL; - - mt = CALLOC_STRUCT(nv10_miptree); - if (!mt) - return NULL; - - mt->base = *pt; - pipe_reference_init(&mt->base.reference, 1); - mt->base.screen = pscreen; - mt->level[0].pitch = stride[0]; - mt->level[0].image_offset = CALLOC(1, sizeof(unsigned)); - - pipe_buffer_reference(&mt->buffer, pb); - mt->bo = nouveau_bo(mt->buffer); - return &mt->base; -} - -static struct pipe_texture * -nv10_miptree_create(struct pipe_screen *screen, const struct pipe_texture *pt) -{ - struct nv10_miptree *mt; - - mt = MALLOC(sizeof(struct nv10_miptree)); - if (!mt) - return NULL; - mt->base = *pt; - pipe_reference_init(&mt->base.reference, 1); - mt->base.screen = screen; - - nv10_miptree_layout(mt); - - mt->buffer = screen->buffer_create(screen, 256, PIPE_BUFFER_USAGE_PIXEL, - mt->total_size); - if (!mt->buffer) { - FREE(mt); - return NULL; - } - mt->bo = nouveau_bo(mt->buffer); - - return &mt->base; -} - -static void -nv10_miptree_destroy(struct pipe_texture *pt) -{ - struct nv10_miptree *nv10mt = (struct nv10_miptree *)pt; - int l; - - pipe_buffer_reference(&nv10mt->buffer, NULL); - for (l = 0; l <= pt->last_level; l++) { - if (nv10mt->level[l].image_offset) - FREE(nv10mt->level[l].image_offset); - } - FREE(nv10mt); -} - -static void -nv10_miptree_update(struct pipe_context *pipe, struct pipe_texture *mt, - uint face, uint levels) -{ -} - - -static struct pipe_surface * -nv10_miptree_surface_get(struct pipe_screen *screen, struct pipe_texture *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned flags) -{ - struct nv10_miptree *nv10mt = (struct nv10_miptree *)pt; - struct nv04_surface *ns; - - ns = CALLOC_STRUCT(nv04_surface); - if (!ns) - return NULL; - pipe_texture_reference(&ns->base.texture, pt); - ns->base.format = pt->format; - ns->base.width = u_minify(pt->width0, level); - ns->base.height = u_minify(pt->height0, level); - ns->base.usage = flags; - pipe_reference_init(&ns->base.reference, 1); - ns->base.face = face; - ns->base.level = level; - ns->base.zslice = zslice; - ns->pitch = nv10mt->level[level].pitch; - - if (pt->target == PIPE_TEXTURE_CUBE) { - ns->base.offset = nv10mt->level[level].image_offset[face]; - } else { - ns->base.offset = nv10mt->level[level].image_offset[0]; - } - - return &ns->base; -} - -static void -nv10_miptree_surface_destroy(struct pipe_surface *surface) -{ -} - -void nv10_screen_init_miptree_functions(struct pipe_screen *pscreen) -{ - pscreen->texture_create = nv10_miptree_create; - pscreen->texture_blanket = nv10_miptree_blanket; - pscreen->texture_destroy = nv10_miptree_destroy; - pscreen->get_tex_surface = nv10_miptree_surface_get; - pscreen->tex_surface_destroy = nv10_miptree_surface_destroy; -} - diff --git a/src/gallium/drivers/nv10/nv10_prim_vbuf.c b/src/gallium/drivers/nv10/nv10_prim_vbuf.c deleted file mode 100644 index c5dbe43dbc..0000000000 --- a/src/gallium/drivers/nv10/nv10_prim_vbuf.c +++ /dev/null @@ -1,267 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 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. - * - **************************************************************************/ - -/** - * \file - * Build post-transformation, post-clipping vertex buffers and element - * lists by hooking into the end of the primitive pipeline and - * manipulating the vertex_id field in the vertex headers. - * - * XXX: work in progress - * - * \author José Fonseca <jrfonseca@tungstengraphics.com> - * \author Keith Whitwell <keith@tungstengraphics.com> - */ - - -#include "util/u_debug.h" -#include "pipe/p_inlines.h" - -#include "nv10_context.h" -#include "nv10_state.h" - -#include "draw/draw_vbuf.h" - -/** - * Primitive renderer for nv10. - */ -struct nv10_vbuf_render { - struct vbuf_render base; - - struct nv10_context *nv10; - - /** Vertex buffer */ - struct pipe_buffer* buffer; - - /** Vertex size in bytes */ - unsigned vertex_size; - - /** Hardware primitive */ - unsigned hwprim; -}; - - -void nv10_vtxbuf_bind( struct nv10_context* nv10 ) -{ - struct nv10_screen *screen = nv10->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *celsius = screen->celsius; - int i; - for(i = 0; i < 8; i++) { - BEGIN_RING(chan, celsius, NV10TCL_VTXBUF_ADDRESS(i), 1); - OUT_RING(chan, 0/*nv10->vtxbuf*/); - BEGIN_RING(chan, celsius, NV10TCL_VTXFMT(i), 1); - OUT_RING(chan, 0/*XXX*/); - } -} - -/** - * Basically a cast wrapper. - */ -static INLINE struct nv10_vbuf_render * -nv10_vbuf_render( struct vbuf_render *render ) -{ - assert(render); - return (struct nv10_vbuf_render *)render; -} - - -static const struct vertex_info * -nv10_vbuf_render_get_vertex_info( struct vbuf_render *render ) -{ - struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); - struct nv10_context *nv10 = nv10_render->nv10; - - nv10_emit_hw_state(nv10); - - return &nv10->vertex_info; -} - -static boolean -nv10_vbuf_render_allocate_vertices( struct vbuf_render *render, - ushort vertex_size, - ushort nr_vertices ) -{ - struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); - struct nv10_context *nv10 = nv10_render->nv10; - struct pipe_screen *screen = nv10->pipe.screen; - size_t size = (size_t)vertex_size * (size_t)nr_vertices; - - assert(!nv10_render->buffer); - nv10_render->buffer = screen->buffer_create(screen, 64, PIPE_BUFFER_USAGE_VERTEX, size); - - nv10->dirty |= NV10_NEW_VTXARRAYS; - - if (nv10_render->buffer) - return FALSE; - return TRUE; -} - -static void * -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_screen *pscreen = nv10->pipe.screen; - - return pipe_buffer_map(pscreen, nv10_render->buffer, - PIPE_BUFFER_USAGE_CPU_WRITE); -} - -static void -nv10_vbuf_render_unmap_vertices( struct vbuf_render *render, - ushort min_index, - ushort max_index ) -{ - struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); - struct nv10_context *nv10 = nv10_render->nv10; - struct pipe_screen *pscreen = nv10->pipe.screen; - - assert(!nv10_render->buffer); - pipe_buffer_unmap(pscreen, nv10_render->buffer); -} - -static boolean -nv10_vbuf_render_set_primitive( struct vbuf_render *render, - unsigned prim ) -{ - struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); - unsigned hwp = nvgl_primitive(prim); - if (hwp == 0) - return FALSE; - - nv10_render->hwprim = hwp; - return TRUE; -} - - -static void -nv10_vbuf_render_draw( struct vbuf_render *render, - const ushort *indices, - uint nr_indices) -{ - struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); - struct nv10_context *nv10 = nv10_render->nv10; - struct nv10_screen *screen = nv10->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *celsius = screen->celsius; - int push, i; - - nv10_emit_hw_state(nv10); - - BEGIN_RING(chan, celsius, NV10TCL_VERTEX_ARRAY_OFFSET_POS, 1); - OUT_RELOCl(chan, nouveau_bo(nv10_render->buffer), 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); - - BEGIN_RING(chan, celsius, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1); - OUT_RING(chan, nv10_render->hwprim); - - if (nr_indices & 1) { - BEGIN_RING(chan, celsius, NV10TCL_VB_ELEMENT_U32, 1); - OUT_RING (chan, indices[0]); - indices++; nr_indices--; - } - - while (nr_indices) { - // XXX too big/small ? check the size - push = MIN2(nr_indices, 1200 * 2); - - BEGIN_RING_NI(chan, celsius, NV10TCL_VB_ELEMENT_U16, push >> 1); - for (i = 0; i < push; i+=2) - OUT_RING(chan, (indices[i+1] << 16) | indices[i]); - - nr_indices -= push; - indices += push; - } - - BEGIN_RING(chan, celsius, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1); - OUT_RING (chan, 0); -} - - -static void -nv10_vbuf_render_release_vertices( struct vbuf_render *render ) -{ - struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); - - assert(nv10_render->buffer); - pipe_buffer_reference(&nv10_render->buffer, NULL); -} - - -static void -nv10_vbuf_render_destroy( struct vbuf_render *render ) -{ - struct nv10_vbuf_render *nv10_render = nv10_vbuf_render(render); - FREE(nv10_render); -} - - -/** - * Create a new primitive render. - */ -static struct vbuf_render * -nv10_vbuf_render_create( struct nv10_context *nv10 ) -{ - struct nv10_vbuf_render *nv10_render = CALLOC_STRUCT(nv10_vbuf_render); - - nv10_render->nv10 = nv10; - - nv10_render->base.max_vertex_buffer_bytes = 16*1024; - nv10_render->base.max_indices = 1024; - nv10_render->base.get_vertex_info = nv10_vbuf_render_get_vertex_info; - nv10_render->base.allocate_vertices = nv10_vbuf_render_allocate_vertices; - nv10_render->base.map_vertices = nv10_vbuf_render_map_vertices; - nv10_render->base.unmap_vertices = nv10_vbuf_render_unmap_vertices; - nv10_render->base.set_primitive = nv10_vbuf_render_set_primitive; - nv10_render->base.draw = nv10_vbuf_render_draw; - nv10_render->base.release_vertices = nv10_vbuf_render_release_vertices; - nv10_render->base.destroy = nv10_vbuf_render_destroy; - - return &nv10_render->base; -} - - -/** - * Create a new primitive vbuf/render stage. - */ -struct draw_stage *nv10_draw_vbuf_stage( struct nv10_context *nv10 ) -{ - struct vbuf_render *render; - struct draw_stage *stage; - - render = nv10_vbuf_render_create(nv10); - if(!render) - return NULL; - - stage = draw_vbuf_stage( nv10->draw, render ); - if(!stage) { - render->destroy(render); - return NULL; - } - - return stage; -} diff --git a/src/gallium/drivers/nv10/nv10_screen.c b/src/gallium/drivers/nv10/nv10_screen.c deleted file mode 100644 index 69a6dab866..0000000000 --- a/src/gallium/drivers/nv10/nv10_screen.c +++ /dev/null @@ -1,198 +0,0 @@ -#include "pipe/p_screen.h" - -#include "nv10_context.h" -#include "nv10_screen.h" - -static int -nv10_screen_get_param(struct pipe_screen *screen, int param) -{ - switch (param) { - case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: - return 2; - case PIPE_CAP_NPOT_TEXTURES: - return 0; - case PIPE_CAP_TWO_SIDED_STENCIL: - return 0; - case PIPE_CAP_GLSL: - return 0; - case PIPE_CAP_ANISOTROPIC_FILTER: - return 1; - case PIPE_CAP_POINT_SPRITE: - return 0; - case PIPE_CAP_MAX_RENDER_TARGETS: - return 1; - case PIPE_CAP_OCCLUSION_QUERY: - return 0; - case PIPE_CAP_TEXTURE_SHADOW_MAP: - return 0; - case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: - return 12; - case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: - return 0; - case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - 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; - default: - NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); - return 0; - } -} - -static float -nv10_screen_get_paramf(struct pipe_screen *screen, int param) -{ - switch (param) { - case PIPE_CAP_MAX_LINE_WIDTH: - case PIPE_CAP_MAX_LINE_WIDTH_AA: - return 10.0; - case PIPE_CAP_MAX_POINT_WIDTH: - case PIPE_CAP_MAX_POINT_WIDTH_AA: - return 64.0; - case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: - return 2.0; - case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: - return 4.0; - default: - NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); - return 0.0; - } -} - -static boolean -nv10_screen_is_format_supported(struct pipe_screen *screen, - enum pipe_format format, - enum pipe_texture_target target, - unsigned tex_usage, unsigned geom_flags) -{ - if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) { - 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: - break; - } - } else { - switch (format) { - case PIPE_FORMAT_A8R8G8B8_UNORM: - case PIPE_FORMAT_A1R5G5B5_UNORM: - case PIPE_FORMAT_A4R4G4B4_UNORM: - case PIPE_FORMAT_R5G6B5_UNORM: - case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_A8_UNORM: - case PIPE_FORMAT_I8_UNORM: - return TRUE; - default: - break; - } - } - - return FALSE; -} - -static void -nv10_screen_destroy(struct pipe_screen *pscreen) -{ - struct nv10_screen *screen = nv10_screen(pscreen); - - nouveau_notifier_free(&screen->sync); - nouveau_grobj_free(&screen->celsius); - nv04_surface_2d_takedown(&screen->eng2d); - - nouveau_screen_fini(&screen->base); - - FREE(pscreen); -} - -static struct pipe_buffer * -nv10_surface_buffer(struct pipe_surface *surf) -{ - struct nv10_miptree *mt = (struct nv10_miptree *)surf->texture; - - return mt->buffer; -} - -struct pipe_screen * -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; - int ret; - - if (!screen) - return NULL; - pscreen = &screen->base.base; - - 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 (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; - - if (!celsius_class) { - NOUVEAU_ERR("Unknown nv1x chipset: nv%02x\n", dev->chipset); - return NULL; - } - - ret = nouveau_grobj_alloc(chan, 0xbeef0001, celsius_class, - &screen->celsius); - if (ret) { - NOUVEAU_ERR("Error creating 3D object: %d\n", ret); - return FALSE; - } - - /* 2D engine setup */ - screen->eng2d = nv04_surface_2d_init(&screen->base); - screen->eng2d->buf = nv10_surface_buffer; - - /* Notifier for sync purposes */ - ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); - if (ret) { - NOUVEAU_ERR("Error creating notifier object: %d\n", ret); - nv10_screen_destroy(pscreen); - return NULL; - } - - return pscreen; -} - diff --git a/src/gallium/drivers/nv10/nv10_screen.h b/src/gallium/drivers/nv10/nv10_screen.h deleted file mode 100644 index 86b6d8def5..0000000000 --- a/src/gallium/drivers/nv10/nv10_screen.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __NV10_SCREEN_H__ -#define __NV10_SCREEN_H__ - -#include "nouveau/nouveau_screen.h" -#include "nv04/nv04_surface_2d.h" - -struct nv10_screen { - struct nouveau_screen base; - - struct nouveau_winsys *nvws; - - /* HW graphics objects */ - struct nv04_surface_2d *eng2d; - struct nouveau_grobj *celsius; - struct nouveau_notifier *sync; -}; - -static INLINE struct nv10_screen * -nv10_screen(struct pipe_screen *screen) -{ - return (struct nv10_screen *)screen; -} - - -void -nv10_screen_init_transfer_functions(struct pipe_screen *pscreen); - -#endif diff --git a/src/gallium/drivers/nv10/nv10_state.h b/src/gallium/drivers/nv10/nv10_state.h deleted file mode 100644 index 2524ac02e2..0000000000 --- a/src/gallium/drivers/nv10/nv10_state.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef __NV10_STATE_H__ -#define __NV10_STATE_H__ - -#include "pipe/p_state.h" -#include "tgsi/tgsi_scan.h" - -struct nv10_blend_state { - uint32_t b_enable; - uint32_t b_srcfunc; - uint32_t b_dstfunc; - - uint32_t c_mask; - - uint32_t d_enable; -}; - -struct nv10_sampler_state { - uint32_t wrap; - uint32_t en; - uint32_t filt; - uint32_t bcol; -}; - -struct nv10_rasterizer_state { - uint32_t shade_model; - - uint32_t line_width; - uint32_t line_smooth_en; - - uint32_t point_size; - - uint32_t poly_smooth_en; - - uint32_t poly_mode_front; - uint32_t poly_mode_back; - - uint32_t front_face; - uint32_t cull_face; - uint32_t cull_face_en; - - uint32_t point_sprite; - - const struct pipe_rasterizer_state *templ; -}; - -struct nv10_vertex_program_exec { - uint32_t data[4]; - boolean has_branch_offset; - int const_index; -}; - -struct nv10_vertex_program_data { - int index; /* immediates == -1 */ - float value[4]; -}; - -struct nv10_vertex_program { - const struct pipe_shader_state *pipe; - - boolean translated; - struct nv10_vertex_program_exec *insns; - unsigned nr_insns; - struct nv10_vertex_program_data *consts; - unsigned nr_consts; - - struct nouveau_resource *exec; - unsigned exec_start; - struct nouveau_resource *data; - unsigned data_start; - unsigned data_start_min; - - uint32_t ir; - uint32_t or; -}; - -struct nv10_fragment_program_data { - unsigned offset; - unsigned index; -}; - -struct nv10_fragment_program { - struct pipe_shader_state pipe; - struct tgsi_shader_info info; - - boolean translated; - boolean on_hw; - unsigned samplers; - - uint32_t *insn; - int insn_len; - - struct nv10_fragment_program_data *consts; - unsigned nr_consts; - - struct pipe_buffer *buffer; - - uint32_t fp_control; - uint32_t fp_reg_control; -}; - - -struct nv10_depth_stencil_alpha_state { - struct { - uint32_t func; - uint32_t write_enable; - uint32_t test_enable; - } depth; - - struct { - uint32_t enable; - uint32_t wmask; - uint32_t func; - uint32_t ref; - uint32_t vmask; - uint32_t fail; - uint32_t zfail; - uint32_t zpass; - } stencil; - - struct { - uint32_t enabled; - uint32_t func; - uint32_t ref; - } alpha; -}; - -struct nv10_miptree { - struct pipe_texture base; - struct nouveau_bo *bo; - - struct pipe_buffer *buffer; - uint total_size; - - struct { - uint pitch; - uint *image_offset; - } level[PIPE_MAX_TEXTURE_LEVELS]; -}; - -#endif diff --git a/src/gallium/drivers/nv10/nv10_state_emit.c b/src/gallium/drivers/nv10/nv10_state_emit.c deleted file mode 100644 index 30a596ca60..0000000000 --- a/src/gallium/drivers/nv10/nv10_state_emit.c +++ /dev/null @@ -1,333 +0,0 @@ -#include "nv10_context.h" -#include "nv10_state.h" - -static void nv10_state_emit_blend(struct nv10_context* nv10) -{ - struct nv10_blend_state *b = nv10->blend; - struct nv10_screen *screen = nv10->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *celsius = screen->celsius; - - BEGIN_RING(chan, celsius, NV10TCL_DITHER_ENABLE, 1); - OUT_RING (chan, b->d_enable); - - BEGIN_RING(chan, celsius, NV10TCL_BLEND_FUNC_ENABLE, 3); - OUT_RING (chan, b->b_enable); - OUT_RING (chan, b->b_srcfunc); - OUT_RING (chan, b->b_dstfunc); - - BEGIN_RING(chan, celsius, NV10TCL_COLOR_MASK, 1); - OUT_RING (chan, b->c_mask); -} - -static void nv10_state_emit_blend_color(struct nv10_context* nv10) -{ - struct pipe_blend_color *c = nv10->blend_color; - struct nv10_screen *screen = nv10->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *celsius = screen->celsius; - - BEGIN_RING(chan, celsius, NV10TCL_BLEND_COLOR, 1); - OUT_RING (chan, - (float_to_ubyte(c->color[3]) << 24)| - (float_to_ubyte(c->color[0]) << 16)| - (float_to_ubyte(c->color[1]) << 8) | - (float_to_ubyte(c->color[2]) << 0)); -} - -static void nv10_state_emit_rast(struct nv10_context* nv10) -{ - struct nv10_rasterizer_state *r = nv10->rast; - struct nv10_screen *screen = nv10->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *celsius = screen->celsius; - - BEGIN_RING(chan, celsius, NV10TCL_SHADE_MODEL, 2); - OUT_RING (chan, r->shade_model); - OUT_RING (chan, r->line_width); - - - BEGIN_RING(chan, celsius, NV10TCL_POINT_SIZE, 1); - OUT_RING (chan, r->point_size); - - BEGIN_RING(chan, celsius, NV10TCL_POLYGON_MODE_FRONT, 2); - OUT_RING (chan, r->poly_mode_front); - OUT_RING (chan, r->poly_mode_back); - - - BEGIN_RING(chan, celsius, NV10TCL_CULL_FACE, 2); - OUT_RING (chan, r->cull_face); - OUT_RING (chan, r->front_face); - - BEGIN_RING(chan, celsius, NV10TCL_LINE_SMOOTH_ENABLE, 2); - OUT_RING (chan, r->line_smooth_en); - OUT_RING (chan, r->poly_smooth_en); - - BEGIN_RING(chan, celsius, NV10TCL_CULL_FACE_ENABLE, 1); - OUT_RING (chan, r->cull_face_en); -} - -static void nv10_state_emit_dsa(struct nv10_context* nv10) -{ - struct nv10_depth_stencil_alpha_state *d = nv10->dsa; - struct nv10_screen *screen = nv10->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *celsius = screen->celsius; - - BEGIN_RING(chan, celsius, NV10TCL_DEPTH_FUNC, 1); - OUT_RING (chan, d->depth.func); - - BEGIN_RING(chan, celsius, NV10TCL_DEPTH_WRITE_ENABLE, 1); - OUT_RING (chan, d->depth.write_enable); - - BEGIN_RING(chan, celsius, NV10TCL_DEPTH_TEST_ENABLE, 1); - OUT_RING (chan, d->depth.test_enable); - -#if 0 - BEGIN_RING(chan, celsius, NV10TCL_STENCIL_ENABLE, 1); - OUT_RING (chan, d->stencil.enable); - BEGIN_RING(chan, celsius, NV10TCL_STENCIL_MASK, 7); - OUT_RINGp (chan, (uint32_t *)&(d->stencil.wmask), 7); -#endif - - BEGIN_RING(chan, celsius, NV10TCL_ALPHA_FUNC_ENABLE, 1); - OUT_RING (chan, d->alpha.enabled); - - BEGIN_RING(chan, celsius, NV10TCL_ALPHA_FUNC_FUNC, 1); - OUT_RING (chan, d->alpha.func); - - BEGIN_RING(chan, celsius, NV10TCL_ALPHA_FUNC_REF, 1); - OUT_RING (chan, d->alpha.ref); -} - -static void nv10_state_emit_viewport(struct nv10_context* nv10) -{ -} - -static void nv10_state_emit_scissor(struct nv10_context* nv10) -{ - // XXX this is so not working -/* struct pipe_scissor_state *s = nv10->scissor; - BEGIN_RING(celsius, NV10TCL_SCISSOR_HORIZ, 2); - OUT_RING (((s->maxx - s->minx) << 16) | s->minx); - OUT_RING (((s->maxy - s->miny) << 16) | s->miny);*/ -} - -static void nv10_state_emit_framebuffer(struct nv10_context* nv10) -{ - struct pipe_framebuffer_state* fb = nv10->framebuffer; - struct nv04_surface *rt, *zeta = NULL; - uint32_t rt_format, w, h; - int colour_format = 0, zeta_format = 0; - struct nv10_miptree *nv10mt = 0; - - struct nv10_screen *screen = nv10->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *celsius = screen->celsius; - - w = fb->cbufs[0]->width; - h = fb->cbufs[0]->height; - colour_format = fb->cbufs[0]->format; - rt = (struct nv04_surface *)fb->cbufs[0]; - - if (fb->zsbuf) { - if (colour_format) { - assert(w == fb->zsbuf->width); - assert(h == fb->zsbuf->height); - } else { - w = fb->zsbuf->width; - h = fb->zsbuf->height; - } - - zeta_format = fb->zsbuf->format; - zeta = (struct nv04_surface *)fb->zsbuf; - } - - rt_format = NV10TCL_RT_FORMAT_TYPE_LINEAR; - - switch (colour_format) { - case PIPE_FORMAT_X8R8G8B8_UNORM: - rt_format |= NV10TCL_RT_FORMAT_COLOR_X8R8G8B8; - break; - case PIPE_FORMAT_A8R8G8B8_UNORM: - case 0: - rt_format |= NV10TCL_RT_FORMAT_COLOR_A8R8G8B8; - break; - case PIPE_FORMAT_R5G6B5_UNORM: - rt_format |= NV10TCL_RT_FORMAT_COLOR_R5G6B5; - break; - default: - assert(0); - } - - if (zeta) { - BEGIN_RING(chan, celsius, NV10TCL_RT_PITCH, 1); - OUT_RING (chan, rt->pitch | (zeta->pitch << 16)); - } else { - BEGIN_RING(chan, celsius, NV10TCL_RT_PITCH, 1); - OUT_RING (chan, rt->pitch | (rt->pitch << 16)); - } - - nv10mt = (struct nv10_miptree *)rt->base.texture; - nv10->rt[0] = nv10mt->buffer; - - if (zeta_format) - { - nv10mt = (struct nv10_miptree *)zeta->base.texture; - nv10->zeta = nv10mt->buffer; - } - - BEGIN_RING(chan, celsius, NV10TCL_RT_HORIZ, 3); - OUT_RING (chan, (w << 16) | 0); - OUT_RING (chan, (h << 16) | 0); - OUT_RING (chan, rt_format); - BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 2); - OUT_RING (chan, ((w - 1) << 16) | 0 | 0x08000800); - OUT_RING (chan, ((h - 1) << 16) | 0 | 0x08000800); -} - -static void nv10_vertex_layout(struct nv10_context *nv10) -{ - struct nv10_fragment_program *fp = nv10->fragprog.current; - uint32_t src = 0; - int i; - struct vertex_info vinfo; - - memset(&vinfo, 0, sizeof(vinfo)); - - for (i = 0; i < fp->info.num_inputs; i++) { - switch (fp->info.input_semantic_name[i]) { - case TGSI_SEMANTIC_POSITION: - draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++); - break; - case TGSI_SEMANTIC_COLOR: - draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src++); - break; - default: - case TGSI_SEMANTIC_GENERIC: - draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++); - break; - case TGSI_SEMANTIC_FOG: - draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src++); - break; - } - } - draw_compute_vertex_size(&vinfo); -} - -void -nv10_emit_hw_state(struct nv10_context *nv10) -{ - struct nv10_screen *screen = nv10->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *celsius = screen->celsius; - struct nouveau_bo *rt_bo; - int i; - - if (nv10->dirty & NV10_NEW_VERTPROG) { - //nv10_vertprog_bind(nv10, nv10->vertprog.current); - nv10->dirty &= ~NV10_NEW_VERTPROG; - } - - if (nv10->dirty & NV10_NEW_FRAGPROG) { - nv10_fragprog_bind(nv10, nv10->fragprog.current); - /*XXX: clear NV10_NEW_FRAGPROG if no new program uploaded */ - nv10->dirty_samplers |= (1<<10); - nv10->dirty_samplers = 0; - } - - if (nv10->dirty_samplers || (nv10->dirty & NV10_NEW_FRAGPROG)) { - nv10_fragtex_bind(nv10); - nv10->dirty &= ~NV10_NEW_FRAGPROG; - } - - if (nv10->dirty & NV10_NEW_VTXARRAYS) { - nv10->dirty &= ~NV10_NEW_VTXARRAYS; - nv10_vertex_layout(nv10); - nv10_vtxbuf_bind(nv10); - } - - if (nv10->dirty & NV10_NEW_BLEND) { - nv10->dirty &= ~NV10_NEW_BLEND; - nv10_state_emit_blend(nv10); - } - - if (nv10->dirty & NV10_NEW_BLENDCOL) { - nv10->dirty &= ~NV10_NEW_BLENDCOL; - nv10_state_emit_blend_color(nv10); - } - - if (nv10->dirty & NV10_NEW_RAST) { - nv10->dirty &= ~NV10_NEW_RAST; - nv10_state_emit_rast(nv10); - } - - if (nv10->dirty & NV10_NEW_DSA) { - nv10->dirty &= ~NV10_NEW_DSA; - nv10_state_emit_dsa(nv10); - } - - if (nv10->dirty & NV10_NEW_VIEWPORT) { - nv10->dirty &= ~NV10_NEW_VIEWPORT; - nv10_state_emit_viewport(nv10); - } - - if (nv10->dirty & NV10_NEW_SCISSOR) { - nv10->dirty &= ~NV10_NEW_SCISSOR; - nv10_state_emit_scissor(nv10); - } - - if (nv10->dirty & NV10_NEW_FRAMEBUFFER) { - nv10->dirty &= ~NV10_NEW_FRAMEBUFFER; - nv10_state_emit_framebuffer(nv10); - } - - /* Emit relocs for every referenced buffer. - * This is to ensure the bufmgr has an accurate idea of how - * the buffer is used. This isn't very efficient, but we don't - * seem to take a significant performance hit. Will be improved - * at some point. Vertex arrays are emitted by nv10_vbo.c - */ - - /* Render target */ - rt_bo = nouveau_bo(nv10->rt[0]); -// XXX figre out who's who for NV10TCL_DMA_* and fill accordingly -// BEGIN_RING(chan, celsius, NV10TCL_DMA_COLOR0, 1); -// OUT_RELOCo(chan, rt_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - BEGIN_RING(chan, celsius, NV10TCL_COLOR_OFFSET, 1); - OUT_RELOCl(chan, rt_bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - - if (nv10->zeta) { - struct nouveau_bo *zeta_bo = nouveau_bo(nv10->zeta); -// XXX -// BEGIN_RING(chan, celsius, NV10TCL_DMA_ZETA, 1); -// OUT_RELOCo(chan, zeta_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - BEGIN_RING(chan, celsius, NV10TCL_ZETA_OFFSET, 1); - OUT_RELOCl(chan, zeta_bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - /* XXX for when we allocate LMA on nv17 */ -/* BEGIN_RING(chan, celsius, NV10TCL_LMA_DEPTH_BUFFER_OFFSET, 1); - OUT_RELOCl(chan, nouveau_bo(nv10->zeta + lma_offset));*/ - } - - /* Vertex buffer */ - BEGIN_RING(chan, celsius, NV10TCL_DMA_VTXBUF0, 1); - OUT_RELOCo(chan, rt_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - BEGIN_RING(chan, celsius, NV10TCL_COLOR_OFFSET, 1); - OUT_RELOCl(chan, rt_bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - - /* Texture images */ - for (i = 0; i < 2; i++) { - if (!(nv10->fp_samplers & (1 << i))) - continue; - struct nouveau_bo *bo = nouveau_bo(nv10->tex[i].buffer); - BEGIN_RING(chan, celsius, NV10TCL_TX_OFFSET(i), 1); - OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | - NOUVEAU_BO_GART | NOUVEAU_BO_RD); - BEGIN_RING(chan, celsius, NV10TCL_TX_FORMAT(i), 1); - OUT_RELOCd(chan, bo, nv10->tex[i].format, - NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | - NOUVEAU_BO_OR, NV10TCL_TX_FORMAT_DMA0, - NV10TCL_TX_FORMAT_DMA1); - } -} - diff --git a/src/gallium/drivers/nv10/nv10_surface.c b/src/gallium/drivers/nv10/nv10_surface.c deleted file mode 100644 index 5b52246a9c..0000000000 --- a/src/gallium/drivers/nv10/nv10_surface.c +++ /dev/null @@ -1,63 +0,0 @@ - -/************************************************************************** - * - * Copyright 2003 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 "nv10_context.h" -#include "pipe/p_defines.h" -#include "pipe/internal/p_winsys_screen.h" -#include "pipe/p_inlines.h" -#include "util/u_tile.h" - -static void -nv10_surface_copy(struct pipe_context *pipe, - struct pipe_surface *dest, unsigned destx, unsigned desty, - struct pipe_surface *src, unsigned srcx, unsigned srcy, - unsigned width, unsigned height) -{ - struct nv10_context *nv10 = nv10_context(pipe); - struct nv04_surface_2d *eng2d = nv10->screen->eng2d; - - eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height); -} - -static void -nv10_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, - unsigned destx, unsigned desty, unsigned width, - unsigned height, unsigned value) -{ - struct nv10_context *nv10 = nv10_context(pipe); - struct nv04_surface_2d *eng2d = nv10->screen->eng2d; - - eng2d->fill(eng2d, dest, destx, desty, width, height, value); -} - -void -nv10_init_surface_functions(struct nv10_context *nv10) -{ - nv10->pipe.surface_copy = nv10_surface_copy; - nv10->pipe.surface_fill = nv10_surface_fill; -} diff --git a/src/gallium/drivers/nv10/nv10_transfer.c b/src/gallium/drivers/nv10/nv10_transfer.c deleted file mode 100644 index eb04af9782..0000000000 --- a/src/gallium/drivers/nv10/nv10_transfer.c +++ /dev/null @@ -1,178 +0,0 @@ -#include <pipe/p_state.h> -#include <pipe/p_defines.h> -#include <pipe/p_inlines.h> -#include <util/u_format.h> -#include <util/u_memory.h> -#include <util/u_math.h> -#include <nouveau/nouveau_winsys.h> -#include "nv10_context.h" -#include "nv10_screen.h" -#include "nv10_state.h" - -struct nv10_transfer { - struct pipe_transfer base; - struct pipe_surface *surface; - boolean direct; -}; - -static void -nv10_compatible_transfer_tex(struct pipe_texture *pt, unsigned width, unsigned height, - struct pipe_texture *template) -{ - memset(template, 0, sizeof(struct pipe_texture)); - template->target = pt->target; - template->format = pt->format; - template->width0 = width; - template->height0 = height; - template->depth0 = 1; - template->last_level = 0; - template->nr_samples = pt->nr_samples; - - template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC | - NOUVEAU_TEXTURE_USAGE_LINEAR; -} - -static struct pipe_transfer * -nv10_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, - unsigned face, unsigned level, unsigned zslice, - enum pipe_transfer_usage usage, - unsigned x, unsigned y, unsigned w, unsigned h) -{ - struct nv10_miptree *mt = (struct nv10_miptree *)pt; - struct nv10_transfer *tx; - struct pipe_texture tx_tex_template, *tx_tex; - - tx = CALLOC_STRUCT(nv10_transfer); - if (!tx) - return NULL; - - pipe_texture_reference(&tx->base.texture, pt); - tx->base.x = x; - tx->base.y = y; - tx->base.width = w; - tx->base.height = h; - tx->base.stride = mt->level[level].pitch; - tx->base.usage = usage; - tx->base.face = face; - tx->base.level = level; - tx->base.zslice = zslice; - - /* Direct access to texture */ - if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC || - debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) && - pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) - { - tx->direct = true; - tx->surface = pscreen->get_tex_surface(pscreen, pt, - 0, 0, 0, - pipe_transfer_buffer_flags(&tx->base)); - return &tx->base; - } - - tx->direct = false; - - nv10_compatible_transfer_tex(pt, w, h, &tx_tex_template); - - tx_tex = pscreen->texture_create(pscreen, &tx_tex_template); - if (!tx_tex) - { - FREE(tx); - return NULL; - } - - tx->base.stride = ((struct nv10_miptree*)tx_tex)->level[0].pitch; - - tx->surface = pscreen->get_tex_surface(pscreen, tx_tex, - face, level, zslice, - pipe_transfer_buffer_flags(&tx->base)); - - pipe_texture_reference(&tx_tex, NULL); - - if (!tx->surface) - { - pipe_surface_reference(&tx->surface, NULL); - FREE(tx); - return NULL; - } - - if (usage & PIPE_TRANSFER_READ) { - struct nv10_screen *nvscreen = nv10_screen(pscreen); - struct pipe_surface *src; - - src = pscreen->get_tex_surface(pscreen, pt, - face, level, zslice, - PIPE_BUFFER_USAGE_GPU_READ); - - /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ - /* TODO: Check if SIFM can un-swizzle */ - nvscreen->eng2d->copy(nvscreen->eng2d, - tx->surface, 0, 0, - src, x, y, - w, h); - - pipe_surface_reference(&src, NULL); - } - - return &tx->base; -} - -static void -nv10_transfer_del(struct pipe_transfer *ptx) -{ - struct nv10_transfer *tx = (struct nv10_transfer *)ptx; - - if (!tx->direct && (ptx->usage & PIPE_TRANSFER_WRITE)) { - struct pipe_screen *pscreen = ptx->texture->screen; - struct nv10_screen *nvscreen = nv10_screen(pscreen); - struct pipe_surface *dst; - - dst = pscreen->get_tex_surface(pscreen, ptx->texture, - ptx->face, ptx->level, ptx->zslice, - PIPE_BUFFER_USAGE_GPU_WRITE); - - /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ - nvscreen->eng2d->copy(nvscreen->eng2d, - dst, tx->base.x, tx->base.y, - tx->surface, 0, 0, - tx->base.width, tx->base.height); - - pipe_surface_reference(&dst, NULL); - } - - pipe_surface_reference(&tx->surface, NULL); - pipe_texture_reference(&ptx->texture, NULL); - FREE(ptx); -} - -static void * -nv10_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) -{ - struct nv10_transfer *tx = (struct nv10_transfer *)ptx; - struct nv04_surface *ns = (struct nv04_surface *)tx->surface; - struct nv10_miptree *mt = (struct nv10_miptree *)tx->surface->texture; - void *map = pipe_buffer_map(pscreen, mt->buffer, - pipe_transfer_buffer_flags(ptx)); - - if(!tx->direct) - return map + ns->base.offset; - else - return map + ns->base.offset + ptx->y * ns->pitch + ptx->x * util_format_get_blocksize(ptx->texture->format); -} - -static void -nv10_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) -{ - struct nv10_transfer *tx = (struct nv10_transfer *)ptx; - struct nv10_miptree *mt = (struct nv10_miptree *)tx->surface->texture; - - pipe_buffer_unmap(pscreen, mt->buffer); -} - -void -nv10_screen_init_transfer_functions(struct pipe_screen *pscreen) -{ - pscreen->get_tex_transfer = nv10_transfer_new; - pscreen->tex_transfer_destroy = nv10_transfer_del; - pscreen->transfer_map = nv10_transfer_map; - pscreen->transfer_unmap = nv10_transfer_unmap; -} diff --git a/src/gallium/drivers/nv10/nv10_vbo.c b/src/gallium/drivers/nv10/nv10_vbo.c deleted file mode 100644 index 9180c72c9b..0000000000 --- a/src/gallium/drivers/nv10/nv10_vbo.c +++ /dev/null @@ -1,77 +0,0 @@ -#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" - -#include "nouveau/nouveau_channel.h" -#include "nouveau/nouveau_pushbuf.h" - -void nv10_draw_elements( struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, - unsigned indexSize, - unsigned prim, unsigned start, unsigned count) -{ - 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); - - /* - * Map vertex buffers - */ - for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { - if (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); - } - } - /* Map index buffer, if present */ - if (indexBuffer) { - void *mapped_indexes - = pipe_buffer_map(pscreen, indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); - draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes); - } - else { - /* no index/element buffer */ - draw_set_mapped_element_buffer(draw, 0, NULL); - } - - draw_set_mapped_constant_buffer(draw, - PIPE_SHADER_VERTEX, - nv10->constbuf[PIPE_SHADER_VERTEX], - nv10->constbuf_nr[PIPE_SHADER_VERTEX]); - - /* draw! */ - draw_arrays(nv10->draw, prim, start, count); - - /* - * unmap vertex/index buffers - */ - for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { - if (nv10->vtxbuf[i].buffer) { - pipe_buffer_unmap(pscreen, nv10->vtxbuf[i].buffer); - draw_set_mapped_vertex_buffer(draw, i, NULL); - } - } - if (indexBuffer) { - pipe_buffer_unmap(pscreen, indexBuffer); - draw_set_mapped_element_buffer(draw, 0, NULL); - } -} - -void nv10_draw_arrays( struct pipe_context *pipe, - unsigned prim, unsigned start, unsigned count) -{ - nv10_draw_elements(pipe, NULL, 0, prim, start, count); -} - - - diff --git a/src/gallium/drivers/nv20/Makefile b/src/gallium/drivers/nv20/Makefile deleted file mode 100644 index 1305f26c59..0000000000 --- a/src/gallium/drivers/nv20/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -TOP = ../../../.. -include $(TOP)/configs/current - -LIBNAME = nv20 - -C_SOURCES = \ - nv20_clear.c \ - nv20_context.c \ - nv20_fragprog.c \ - nv20_fragtex.c \ - nv20_miptree.c \ - nv20_prim_vbuf.c \ - nv20_screen.c \ - nv20_state.c \ - nv20_state_emit.c \ - nv20_surface.c \ - nv20_transfer.c \ - nv20_vbo.c -# nv20_vertprog.c - -include ../../Makefile.template diff --git a/src/gallium/drivers/nv20/nv20_clear.c b/src/gallium/drivers/nv20/nv20_clear.c deleted file mode 100644 index 2b4490fa5e..0000000000 --- a/src/gallium/drivers/nv20/nv20_clear.c +++ /dev/null @@ -1,14 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "util/u_clear.h" - -#include "nv20_context.h" - -void -nv20_clear(struct pipe_context *pipe, unsigned buffers, - const float *rgba, double depth, unsigned stencil) -{ - util_clear(pipe, nv20_context(pipe)->framebuffer, buffers, rgba, depth, - stencil); -} diff --git a/src/gallium/drivers/nv20/nv20_context.c b/src/gallium/drivers/nv20/nv20_context.c deleted file mode 100644 index 5b80af2d22..0000000000 --- a/src/gallium/drivers/nv20/nv20_context.c +++ /dev/null @@ -1,424 +0,0 @@ -#include "draw/draw_context.h" -#include "pipe/p_defines.h" -#include "pipe/internal/p_winsys_screen.h" - -#include "nv20_context.h" -#include "nv20_screen.h" - -static void -nv20_flush(struct pipe_context *pipe, unsigned flags, - struct pipe_fence_handle **fence) -{ - struct nv20_context *nv20 = nv20_context(pipe); - struct nv20_screen *screen = nv20->screen; - struct nouveau_channel *chan = screen->base.channel; - - draw_flush(nv20->draw); - - FIRE_RING(chan); - if (fence) - *fence = NULL; -} - -static void -nv20_destroy(struct pipe_context *pipe) -{ - struct nv20_context *nv20 = nv20_context(pipe); - - if (nv20->draw) - draw_destroy(nv20->draw); - - FREE(nv20); -} - -static void nv20_init_hwctx(struct nv20_context *nv20) -{ - struct nv20_screen *screen = nv20->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *kelvin = screen->kelvin; - int i; - float projectionmatrix[16]; - const boolean is_nv25tcl = (kelvin->grclass == NV25TCL); - - BEGIN_RING(chan, kelvin, NV20TCL_DMA_NOTIFY, 1); - OUT_RING (chan, screen->sync->handle); - BEGIN_RING(chan, kelvin, NV20TCL_DMA_TEXTURE0, 2); - OUT_RING (chan, chan->vram->handle); - OUT_RING (chan, chan->gart->handle); /* TEXTURE1 */ - BEGIN_RING(chan, kelvin, NV20TCL_DMA_COLOR, 2); - OUT_RING (chan, chan->vram->handle); - OUT_RING (chan, chan->vram->handle); /* ZETA */ - - BEGIN_RING(chan, kelvin, NV20TCL_DMA_QUERY, 1); - OUT_RING (chan, 0); /* renouveau: beef0351, unique */ - - BEGIN_RING(chan, kelvin, NV20TCL_RT_HORIZ, 2); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - - BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_CLIP_HORIZ(0), 1); - OUT_RING (chan, (0xfff << 16) | 0x0); - BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_CLIP_VERT(0), 1); - OUT_RING (chan, (0xfff << 16) | 0x0); - - for (i = 1; i < NV20TCL_VIEWPORT_CLIP_HORIZ__SIZE; i++) { - BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_CLIP_HORIZ(i), 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_CLIP_VERT(i), 1); - OUT_RING (chan, 0); - } - - BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_CLIP_MODE, 1); - OUT_RING (chan, 0); - - BEGIN_RING(chan, kelvin, 0x17e0, 3); - OUT_RINGf (chan, 0.0); - OUT_RINGf (chan, 0.0); - OUT_RINGf (chan, 1.0); - - if (is_nv25tcl) { - BEGIN_RING(chan, kelvin, NV20TCL_TX_RCOMP, 1); - OUT_RING (chan, NV20TCL_TX_RCOMP_LEQUAL | 0xdb0); - } else { - BEGIN_RING(chan, kelvin, 0x1e68, 1); - OUT_RING (chan, 0x4b800000); /* 16777216.000000 */ - BEGIN_RING(chan, kelvin, NV20TCL_TX_RCOMP, 1); - OUT_RING (chan, NV20TCL_TX_RCOMP_LEQUAL); - } - - BEGIN_RING(chan, kelvin, 0x290, 1); - OUT_RING (chan, (0x10 << 16) | 1); - BEGIN_RING(chan, kelvin, 0x9fc, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, 0x1d80, 1); - OUT_RING (chan, 1); - BEGIN_RING(chan, kelvin, 0x9f8, 1); - OUT_RING (chan, 4); - BEGIN_RING(chan, kelvin, 0x17ec, 3); - OUT_RINGf (chan, 0.0); - OUT_RINGf (chan, 1.0); - OUT_RINGf (chan, 0.0); - - if (is_nv25tcl) { - BEGIN_RING(chan, kelvin, 0x1d88, 1); - OUT_RING (chan, 3); - - BEGIN_RING(chan, kelvin, NV25TCL_DMA_IN_MEMORY9, 1); - OUT_RING (chan, chan->vram->handle); - BEGIN_RING(chan, kelvin, NV25TCL_DMA_IN_MEMORY8, 1); - OUT_RING (chan, chan->vram->handle); - } - BEGIN_RING(chan, kelvin, NV20TCL_DMA_FENCE, 1); - OUT_RING (chan, 0); /* renouveau: beef1e10 */ - - BEGIN_RING(chan, kelvin, 0x1e98, 1); - OUT_RING (chan, 0); -#if 0 - if (is_nv25tcl) { - BEGIN_RING(chan, NvSub3D, NV25TCL_DMA_IN_MEMORY4, 2); - OUT_RING (chan, NvDmaTT); /* renouveau: beef0202 */ - OUT_RING (chan, NvDmaFB); /* renouveau: beef0201 */ - - BEGIN_RING(chan, NvSub3D, NV20TCL_DMA_TEXTURE1, 1); - OUT_RING (chan, NvDmaTT); /* renouveau: beef0202 */ - } -#endif - BEGIN_RING(chan, kelvin, NV20TCL_NOTIFY, 1); - OUT_RING (chan, 0); - - BEGIN_RING(chan, kelvin, 0x120, 3); - OUT_RING (chan, 0); - OUT_RING (chan, 1); - OUT_RING (chan, 2); - -/* error: ILLEGAL_MTHD, PROTECTION_FAULT - BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_TRANSLATE_X, 4); - OUT_RINGf (chan, 0.0); - OUT_RINGf (chan, 512.0); - OUT_RINGf (chan, 0.0); - OUT_RINGf (chan, 0.0); -*/ - - if (is_nv25tcl) { - BEGIN_RING(chan, kelvin, 0x022c, 2); - OUT_RING (chan, 0x280); - OUT_RING (chan, 0x07d28000); - } - -/* * illegal method, protection fault - BEGIN_RING(chan, NvSub3D, 0x1c2c, 1); - OUT_RING (chan, 0); */ - - if (is_nv25tcl) { - BEGIN_RING(chan, kelvin, 0x1da4, 1); - OUT_RING (chan, 0); - } - -/* * crashes with illegal method, protection fault - BEGIN_RING(chan, NvSub3D, 0x1c18, 1); - OUT_RING (chan, 0x200); */ - - BEGIN_RING(chan, kelvin, NV20TCL_RT_HORIZ, 2); - OUT_RING (chan, (0 << 16) | 0); - OUT_RING (chan, (0 << 16) | 0); - - /* *** Set state *** */ - - BEGIN_RING(chan, kelvin, NV20TCL_ALPHA_FUNC_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_ALPHA_FUNC_FUNC, 2); - OUT_RING (chan, NV20TCL_ALPHA_FUNC_FUNC_ALWAYS); - OUT_RING (chan, 0); /* NV20TCL_ALPHA_FUNC_REF */ - - for (i = 0; i < NV20TCL_TX_ENABLE__SIZE; ++i) { - BEGIN_RING(chan, kelvin, NV20TCL_TX_ENABLE(i), 1); - OUT_RING (chan, 0); - } - BEGIN_RING(chan, kelvin, NV20TCL_TX_SHADER_OP, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_TX_SHADER_CULL_MODE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_RC_IN_ALPHA(0), 4); - OUT_RING (chan, 0x30d410d0); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_RC_OUT_RGB(0), 4); - OUT_RING (chan, 0x00000c00); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_RC_ENABLE, 1); - OUT_RING (chan, 0x00011101); - BEGIN_RING(chan, kelvin, NV20TCL_RC_FINAL0, 2); - OUT_RING (chan, 0x130e0300); - OUT_RING (chan, 0x0c091c80); - BEGIN_RING(chan, kelvin, NV20TCL_RC_OUT_ALPHA(0), 4); - OUT_RING (chan, 0x00000c00); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_RC_IN_RGB(0), 4); - OUT_RING (chan, 0x20c400c0); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_RC_COLOR0, 2); - OUT_RING (chan, 0); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_RC_CONSTANT_COLOR0(0), 4); - OUT_RING (chan, 0x035125a0); - OUT_RING (chan, 0); - OUT_RING (chan, 0x40002000); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_MULTISAMPLE_CONTROL, 1); - OUT_RING (chan, 0xffff0000); - - BEGIN_RING(chan, kelvin, NV20TCL_BLEND_FUNC_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_DITHER_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_STENCIL_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_BLEND_FUNC_SRC, 4); - OUT_RING (chan, NV20TCL_BLEND_FUNC_SRC_ONE); - OUT_RING (chan, NV20TCL_BLEND_FUNC_DST_ZERO); - OUT_RING (chan, 0); /* NV20TCL_BLEND_COLOR */ - OUT_RING (chan, NV20TCL_BLEND_EQUATION_FUNC_ADD); - BEGIN_RING(chan, kelvin, NV20TCL_STENCIL_MASK, 7); - OUT_RING (chan, 0xff); - OUT_RING (chan, NV20TCL_STENCIL_FUNC_FUNC_ALWAYS); - OUT_RING (chan, 0); /* NV20TCL_STENCIL_FUNC_REF */ - OUT_RING (chan, 0xff); /* NV20TCL_STENCIL_FUNC_MASK */ - OUT_RING (chan, NV20TCL_STENCIL_OP_FAIL_KEEP); - OUT_RING (chan, NV20TCL_STENCIL_OP_ZFAIL_KEEP); - OUT_RING (chan, NV20TCL_STENCIL_OP_ZPASS_KEEP); - - BEGIN_RING(chan, kelvin, NV20TCL_COLOR_LOGIC_OP_ENABLE, 2); - OUT_RING (chan, 0); - OUT_RING (chan, NV20TCL_COLOR_LOGIC_OP_OP_COPY); - BEGIN_RING(chan, kelvin, 0x17cc, 1); - OUT_RING (chan, 0); - if (is_nv25tcl) { - BEGIN_RING(chan, kelvin, 0x1d84, 1); - OUT_RING (chan, 1); - } - BEGIN_RING(chan, kelvin, NV20TCL_LIGHTING_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_LIGHT_CONTROL, 1); - OUT_RING (chan, 0x00020000); - BEGIN_RING(chan, kelvin, NV20TCL_SEPARATE_SPECULAR_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_LIGHT_MODEL_TWO_SIDE_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_ENABLED_LIGHTS, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_NORMALIZE_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_POLYGON_STIPPLE_PATTERN(0), - NV20TCL_POLYGON_STIPPLE_PATTERN__SIZE); - for (i = 0; i < NV20TCL_POLYGON_STIPPLE_PATTERN__SIZE; ++i) { - OUT_RING(chan, 0xffffffff); - } - - BEGIN_RING(chan, kelvin, NV20TCL_POLYGON_OFFSET_POINT_ENABLE, 3); - OUT_RING (chan, 0); - OUT_RING (chan, 0); /* NV20TCL.POLYGON_OFFSET_LINE_ENABLE */ - OUT_RING (chan, 0); /* NV20TCL.POLYGON_OFFSET_FILL_ENABLE */ - BEGIN_RING(chan, kelvin, NV20TCL_DEPTH_FUNC, 1); - OUT_RING (chan, NV20TCL_DEPTH_FUNC_LESS); - BEGIN_RING(chan, kelvin, NV20TCL_DEPTH_WRITE_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_DEPTH_TEST_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_POLYGON_OFFSET_FACTOR, 2); - OUT_RINGf (chan, 0.0); - OUT_RINGf (chan, 0.0); /* NV20TCL.POLYGON_OFFSET_UNITS */ - BEGIN_RING(chan, kelvin, NV20TCL_DEPTH_UNK17D8, 1); - OUT_RING (chan, 1); - if (!is_nv25tcl) { - BEGIN_RING(chan, kelvin, 0x1d84, 1); - OUT_RING (chan, 3); - } - BEGIN_RING(chan, kelvin, NV20TCL_POINT_SIZE, 1); - if (!is_nv25tcl) { - OUT_RING (chan, 8); - } else { - OUT_RINGf (chan, 1.0); - } - if (!is_nv25tcl) { - BEGIN_RING(chan, kelvin, NV20TCL_POINT_PARAMETERS_ENABLE, 2); - OUT_RING (chan, 0); - OUT_RING (chan, 0); /* NV20TCL.POINT_SMOOTH_ENABLE */ - } else { - BEGIN_RING(chan, kelvin, NV20TCL_POINT_PARAMETERS_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, 0x0a1c, 1); - OUT_RING (chan, 0x800); - } - BEGIN_RING(chan, kelvin, NV20TCL_LINE_WIDTH, 1); - OUT_RING (chan, 8); - BEGIN_RING(chan, kelvin, NV20TCL_LINE_SMOOTH_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_POLYGON_MODE_FRONT, 2); - OUT_RING (chan, NV20TCL_POLYGON_MODE_FRONT_FILL); - OUT_RING (chan, NV20TCL_POLYGON_MODE_BACK_FILL); - BEGIN_RING(chan, kelvin, NV20TCL_CULL_FACE, 2); - OUT_RING (chan, NV20TCL_CULL_FACE_BACK); - OUT_RING (chan, NV20TCL_FRONT_FACE_CCW); - BEGIN_RING(chan, kelvin, NV20TCL_POLYGON_SMOOTH_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_CULL_FACE_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_SHADE_MODEL, 1); - OUT_RING (chan, NV20TCL_SHADE_MODEL_SMOOTH); - BEGIN_RING(chan, kelvin, NV20TCL_POLYGON_STIPPLE_ENABLE, 1); - OUT_RING (chan, 0); - BEGIN_RING(chan, kelvin, NV20TCL_TX_GEN_S(0), 4 * NV20TCL_TX_GEN_S__SIZE); - for (i=0; i < 4 * NV20TCL_TX_GEN_S__SIZE; ++i) { - OUT_RING(chan, 0); - } - BEGIN_RING(chan, kelvin, NV20TCL_FOG_EQUATION_CONSTANT, 3); - OUT_RINGf (chan, 1.5); - OUT_RINGf (chan, -0.090168); /* NV20TCL.FOG_EQUATION_LINEAR */ - OUT_RINGf (chan, 0.0); /* NV20TCL.FOG_EQUATION_QUADRATIC */ - BEGIN_RING(chan, kelvin, NV20TCL_FOG_MODE, 2); - OUT_RING (chan, NV20TCL_FOG_MODE_EXP_SIGNED); - OUT_RING (chan, NV20TCL_FOG_COORD_FOG); - BEGIN_RING(chan, kelvin, NV20TCL_FOG_ENABLE, 2); - OUT_RING (chan, 0); - OUT_RING (chan, 0); /* NV20TCL.FOG_COLOR */ - BEGIN_RING(chan, kelvin, NV20TCL_ENGINE, 1); - OUT_RING (chan, NV20TCL_ENGINE_FIXED); - - for (i = 0; i < NV20TCL_TX_MATRIX_ENABLE__SIZE; ++i) { - BEGIN_RING(chan, kelvin, NV20TCL_TX_MATRIX_ENABLE(i), 1); - OUT_RING (chan, 0); - } - - BEGIN_RING(chan, kelvin, NV20TCL_VTX_ATTR_4F_X(1), 4 * 15); - OUT_RINGf(chan, 1.0); OUT_RINGf(chan, 0.0); OUT_RINGf(chan, 0.0); OUT_RINGf(chan, 1.0); - OUT_RINGf(chan, 0.0); OUT_RINGf(chan, 0.0); OUT_RINGf(chan, 1.0); OUT_RINGf(chan, 1.0); - OUT_RINGf(chan, 1.0); OUT_RINGf(chan, 1.0); OUT_RINGf(chan, 1.0); OUT_RINGf(chan, 1.0); - for (i = 4; i < 16; ++i) { - OUT_RINGf(chan, 0.0); - OUT_RINGf(chan, 0.0); - OUT_RINGf(chan, 0.0); - OUT_RINGf(chan, 1.0); - } - - BEGIN_RING(chan, kelvin, NV20TCL_EDGEFLAG_ENABLE, 1); - OUT_RING (chan, 1); - BEGIN_RING(chan, kelvin, NV20TCL_COLOR_MASK, 1); - OUT_RING (chan, 0x00010101); - BEGIN_RING(chan, kelvin, NV20TCL_CLEAR_VALUE, 1); - OUT_RING (chan, 0); - - memset(projectionmatrix, 0, sizeof(projectionmatrix)); - projectionmatrix[0*4+0] = 1.0; - projectionmatrix[1*4+1] = 1.0; - projectionmatrix[2*4+2] = 16777215.0; - projectionmatrix[3*4+3] = 1.0; - BEGIN_RING(chan, kelvin, NV20TCL_PROJECTION_MATRIX(0), 16); - for (i = 0; i < 16; i++) { - OUT_RINGf (chan, projectionmatrix[i]); - } - - BEGIN_RING(chan, kelvin, NV20TCL_DEPTH_RANGE_NEAR, 2); - OUT_RINGf (chan, 0.0); - OUT_RINGf (chan, 16777216.0); /* [0, 1] scaled approx to [0, 2^24] */ - - BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_TRANSLATE_X, 4); - OUT_RINGf (chan, 0.0); /* x-offset, w/2 + 1.031250 */ - OUT_RINGf (chan, 0.0); /* y-offset, h/2 + 0.030762 */ - OUT_RINGf (chan, 0.0); - OUT_RINGf (chan, 16777215.0); - - BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_SCALE_X, 4); - OUT_RINGf (chan, 0.0); /* no effect?, w/2 */ - OUT_RINGf (chan, 0.0); /* no effect?, h/2 */ - OUT_RINGf (chan, 16777215.0 * 0.5); - OUT_RINGf (chan, 65535.0); - - FIRE_RING (chan); -} - -struct pipe_context * -nv20_create(struct pipe_screen *pscreen, unsigned pctx_id) -{ - struct nv20_screen *screen = nv20_screen(pscreen); - struct pipe_winsys *ws = pscreen->winsys; - struct nv20_context *nv20; - struct nouveau_winsys *nvws = screen->nvws; - - nv20 = CALLOC(1, sizeof(struct nv20_context)); - if (!nv20) - return NULL; - nv20->screen = screen; - nv20->pctx_id = pctx_id; - - nv20->nvws = nvws; - - nv20->pipe.winsys = ws; - nv20->pipe.screen = pscreen; - nv20->pipe.destroy = nv20_destroy; - nv20->pipe.draw_arrays = nv20_draw_arrays; - nv20->pipe.draw_elements = nv20_draw_elements; - nv20->pipe.clear = nv20_clear; - nv20->pipe.flush = nv20_flush; - - nv20->pipe.is_texture_referenced = nouveau_is_texture_referenced; - nv20->pipe.is_buffer_referenced = nouveau_is_buffer_referenced; - - nv20_init_surface_functions(nv20); - nv20_init_state_functions(nv20); - - nv20->draw = draw_create(); - assert(nv20->draw); - draw_set_rasterize_stage(nv20->draw, nv20_draw_vbuf_stage(nv20)); - - nv20_init_hwctx(nv20); - - return &nv20->pipe; -} - diff --git a/src/gallium/drivers/nv20/nv20_context.h b/src/gallium/drivers/nv20/nv20_context.h deleted file mode 100644 index c7dfadaa31..0000000000 --- a/src/gallium/drivers/nv20/nv20_context.h +++ /dev/null @@ -1,150 +0,0 @@ -#ifndef __NV20_CONTEXT_H__ -#define __NV20_CONTEXT_H__ - -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" -#include "pipe/p_compiler.h" - -#include "util/u_memory.h" -#include "util/u_math.h" - -#include "draw/draw_vertex.h" - -#include "nouveau/nouveau_winsys.h" -#include "nouveau/nouveau_gldefs.h" -#include "nouveau/nouveau_context.h" - -#include "nv20_state.h" - -#define NOUVEAU_ERR(fmt, args...) \ - fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args); -#define NOUVEAU_MSG(fmt, args...) \ - fprintf(stderr, "nouveau: "fmt, ##args); - -#define NV20_NEW_VERTPROG (1 << 0) -#define NV20_NEW_FRAGPROG (1 << 1) -#define NV20_NEW_VTXARRAYS (1 << 2) -#define NV20_NEW_BLEND (1 << 3) -#define NV20_NEW_BLENDCOL (1 << 4) -#define NV20_NEW_RAST (1 << 5) -#define NV20_NEW_DSA (1 << 6) -#define NV20_NEW_VIEWPORT (1 << 7) -#define NV20_NEW_SCISSOR (1 << 8) -#define NV20_NEW_FRAMEBUFFER (1 << 9) - -#include "nv20_screen.h" - -struct nv20_context { - struct pipe_context pipe; - - struct nouveau_winsys *nvws; - struct nv20_screen *screen; - unsigned pctx_id; - - struct draw_context *draw; - - uint32_t dirty; - - struct nv20_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS]; - struct nv20_miptree *tex_miptree[PIPE_MAX_SAMPLERS]; - unsigned dirty_samplers; - unsigned fp_samplers; - unsigned vp_samplers; - - uint32_t rt_enable; - struct pipe_buffer *rt[4]; - struct pipe_buffer *zeta; - uint32_t lma_offset; - - struct nv20_blend_state *blend; - struct pipe_blend_color *blend_color; - struct nv20_rasterizer_state *rast; - struct nv20_depth_stencil_alpha_state *dsa; - struct pipe_viewport_state *viewport; - struct pipe_scissor_state *scissor; - struct pipe_framebuffer_state *framebuffer; - - //struct pipe_buffer *constbuf[PIPE_SHADER_TYPES]; - float *constbuf[PIPE_SHADER_TYPES][32][4]; - unsigned constbuf_nr[PIPE_SHADER_TYPES]; - - struct vertex_info vertex_info; - - struct { - struct pipe_buffer *buffer; - uint32_t format; - } tex[2]; - - unsigned vb_enable; - struct { - struct pipe_buffer *buffer; - unsigned delta; - } vb[16]; - -/* struct { - - struct nouveau_resource *exec_heap; - struct nouveau_resource *data_heap; - - struct nv20_vertex_program *active; - - struct nv20_vertex_program *current; - } vertprog; -*/ - struct { - struct nv20_fragment_program *active; - - struct nv20_fragment_program *current; - struct pipe_buffer *constant_buf; - } fragprog; - - struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; - struct pipe_vertex_element vtxelt[PIPE_MAX_ATTRIBS]; -}; - -static INLINE struct nv20_context * -nv20_context(struct pipe_context *pipe) -{ - return (struct nv20_context *)pipe; -} - -extern void nv20_init_state_functions(struct nv20_context *nv20); -extern void nv20_init_surface_functions(struct nv20_context *nv20); - -extern void nv20_screen_init_miptree_functions(struct pipe_screen *pscreen); - -/* nv20_clear.c */ -extern void nv20_clear(struct pipe_context *pipe, unsigned buffers, - const float *rgba, double depth, unsigned stencil); - -/* nv20_draw.c */ -extern struct draw_stage *nv20_draw_render_stage(struct nv20_context *nv20); - -/* nv20_fragprog.c */ -extern void nv20_fragprog_bind(struct nv20_context *, - struct nv20_fragment_program *); -extern void nv20_fragprog_destroy(struct nv20_context *, - struct nv20_fragment_program *); - -/* nv20_fragtex.c */ -extern void nv20_fragtex_bind(struct nv20_context *); - -/* nv20_prim_vbuf.c */ -struct draw_stage *nv20_draw_vbuf_stage( struct nv20_context *nv20 ); -extern void nv20_vtxbuf_bind(struct nv20_context* nv20); - -/* nv20_state.c and friends */ -extern void nv20_emit_hw_state(struct nv20_context *nv20); -extern void nv20_state_tex_update(struct nv20_context *nv20); - -/* nv20_vbo.c */ -extern void nv20_draw_arrays(struct pipe_context *, unsigned mode, - unsigned start, unsigned count); -extern void nv20_draw_elements( struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, - unsigned indexSize, - unsigned prim, unsigned start, unsigned count); - - -#endif diff --git a/src/gallium/drivers/nv20/nv20_fragprog.c b/src/gallium/drivers/nv20/nv20_fragprog.c deleted file mode 100644 index 4f496369dd..0000000000 --- a/src/gallium/drivers/nv20/nv20_fragprog.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/p_state.h" - -#include "pipe/p_shader_tokens.h" -#include "tgsi/tgsi_parse.h" -#include "tgsi/tgsi_util.h" - -#include "nv20_context.h" - -void -nv20_fragprog_bind(struct nv20_context *nv20, struct nv20_fragment_program *fp) -{ -} - -void -nv20_fragprog_destroy(struct nv20_context *nv20, - struct nv20_fragment_program *fp) -{ -} - diff --git a/src/gallium/drivers/nv20/nv20_fragtex.c b/src/gallium/drivers/nv20/nv20_fragtex.c deleted file mode 100644 index dedbec73f3..0000000000 --- a/src/gallium/drivers/nv20/nv20_fragtex.c +++ /dev/null @@ -1,130 +0,0 @@ -#include "nv20_context.h" -#include "nouveau/nouveau_util.h" - -#define _(m,tf) \ -{ \ - TRUE, \ - PIPE_FORMAT_##m, \ - NV20TCL_TX_FORMAT_FORMAT_##tf, \ -} - -struct nv20_texture_format { - boolean defined; - uint pipe; - int format; -}; - -static struct nv20_texture_format -nv20_texture_formats[] = { - _(A8R8G8B8_UNORM, A8R8G8B8), - _(A1R5G5B5_UNORM, A1R5G5B5), - _(A4R4G4B4_UNORM, A4R4G4B4), - _(L8_UNORM , L8 ), - _(A8_UNORM , A8 ), - _(A8L8_UNORM , A8L8 ), -/* _(RGB_DXT1 , DXT1, ), */ -/* _(RGBA_DXT1 , DXT1, ), */ -/* _(RGBA_DXT3 , DXT3, ), */ -/* _(RGBA_DXT5 , DXT5, ), */ - {}, -}; - -static struct nv20_texture_format * -nv20_fragtex_format(uint pipe_format) -{ - struct nv20_texture_format *tf = nv20_texture_formats; - - while (tf->defined) { - if (tf->pipe == pipe_format) - return tf; - tf++; - } - - return NULL; -} - - -static void -nv20_fragtex_build(struct nv20_context *nv20, int unit) -{ -#if 0 - struct nv20_sampler_state *ps = nv20->tex_sampler[unit]; - struct nv20_miptree *nv20mt = nv20->tex_miptree[unit]; - struct pipe_texture *pt = &nv20mt->base; - struct nv20_texture_format *tf; - struct nv20_screen *screen = nv20->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *kelvin = screen->kelvin; - uint32_t txf, txs, txp; - - tf = nv20_fragtex_format(pt->format); - if (!tf || !tf->defined) { - NOUVEAU_ERR("Unsupported texture format: 0x%x\n", pt->format); - return; - } - - txf = tf->format << 8; - txf |= (pt->last_level + 1) << 16; - txf |= log2i(pt->width0) << 20; - txf |= log2i(pt->height0) << 24; - txf |= log2i(pt->depth0) << 28; - txf |= 8; - - switch (pt->target) { - case PIPE_TEXTURE_CUBE: - txf |= NV10TCL_TX_FORMAT_CUBE_MAP; - /* fall-through */ - case PIPE_TEXTURE_2D: - txf |= (2<<4); - break; - case PIPE_TEXTURE_1D: - txf |= (1<<4); - break; - default: - NOUVEAU_ERR("Unknown target %d\n", pt->target); - return; - } - - BEGIN_RING(chan, kelvin, NV10TCL_TX_OFFSET(unit), 8); - OUT_RELOCl(chan, nouveau_bo(nv20mt->buffer), 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); - OUT_RELOCd(chan, nouveau_bo(nv20mt->buffer),txf,NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_OR | NOUVEAU_BO_RD, 1/*VRAM*/,2/*TT*/); - OUT_RING (chan, ps->wrap); - OUT_RING (chan, 0x40000000); /* enable */ - OUT_RING (chan, txs); - OUT_RING (chan, ps->filt | 0x2000 /* magic */); - OUT_RING (chan, (pt->width0 << 16) | pt->height0); - OUT_RING (chan, ps->bcol); -#endif -} - -void -nv20_fragtex_bind(struct nv20_context *nv20) -{ -#if 0 - struct nv20_fragment_program *fp = nv20->fragprog.active; - struct nv20_screen *screen = nv20->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *kelvin = screen->kelvin; - unsigned samplers, unit; - - samplers = nv20->fp_samplers & ~fp->samplers; - while (samplers) { - unit = ffs(samplers) - 1; - samplers &= ~(1 << unit); - - BEGIN_RING(chan, kelvin, NV10TCL_TX_ENABLE(unit), 1); - OUT_RING (chan, 0); - } - - samplers = nv20->dirty_samplers & fp->samplers; - while (samplers) { - unit = ffs(samplers) - 1; - samplers &= ~(1 << unit); - - nv20_fragtex_build(nv20, unit); - } - - nv20->fp_samplers = fp->samplers; -#endif -} - diff --git a/src/gallium/drivers/nv20/nv20_miptree.c b/src/gallium/drivers/nv20/nv20_miptree.c deleted file mode 100644 index 8f7538e7f5..0000000000 --- a/src/gallium/drivers/nv20/nv20_miptree.c +++ /dev/null @@ -1,226 +0,0 @@ -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "pipe/p_inlines.h" -#include "util/u_format.h" -#include "util/u_math.h" - -#include "nv20_context.h" -#include "nv20_screen.h" -#include "../nv04/nv04_surface_2d.h" - -static void -nv20_miptree_layout(struct nv20_miptree *nv20mt) -{ - struct pipe_texture *pt = &nv20mt->base; - uint width = pt->width0; - uint offset = 0; - int nr_faces, l, f; - uint wide_pitch = pt->tex_usage & (PIPE_TEXTURE_USAGE_SAMPLER | - PIPE_TEXTURE_USAGE_DEPTH_STENCIL | - PIPE_TEXTURE_USAGE_RENDER_TARGET | - PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_PRIMARY); - - if (pt->target == PIPE_TEXTURE_CUBE) { - nr_faces = 6; - } else { - nr_faces = 1; - } - - for (l = 0; l <= pt->last_level; l++) { - if (wide_pitch && (pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) - nv20mt->level[l].pitch = align(util_format_get_stride(pt->format, pt->width0), 64); - else - nv20mt->level[l].pitch = util_format_get_stride(pt->format, width); - - nv20mt->level[l].image_offset = - CALLOC(nr_faces, sizeof(unsigned)); - - width = u_minify(width, 1); - } - - for (f = 0; f < nr_faces; f++) { - for (l = 0; l < pt->last_level; l++) { - nv20mt->level[l].image_offset[f] = offset; - - if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) && - u_minify(pt->width0, l + 1) > 1 && u_minify(pt->height0, l + 1) > 1) - offset += align(nv20mt->level[l].pitch * u_minify(pt->height0, l), 64); - else - offset += nv20mt->level[l].pitch * u_minify(pt->height0, l); - } - - nv20mt->level[l].image_offset[f] = offset; - offset += nv20mt->level[l].pitch * u_minify(pt->height0, l); - } - - nv20mt->total_size = offset; -} - -static struct pipe_texture * -nv20_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt, - const unsigned *stride, struct pipe_buffer *pb) -{ - struct nv20_miptree *mt; - - /* Only supports 2D, non-mipmapped textures for the moment */ - if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 || - pt->depth0 != 1) - return NULL; - - mt = CALLOC_STRUCT(nv20_miptree); - if (!mt) - return NULL; - - mt->base = *pt; - pipe_reference_init(&mt->base.reference, 1); - mt->base.screen = pscreen; - mt->level[0].pitch = stride[0]; - mt->level[0].image_offset = CALLOC(1, sizeof(unsigned)); - - pipe_buffer_reference(&mt->buffer, pb); - mt->bo = nouveau_bo(mt->buffer); - return &mt->base; -} - -static struct pipe_texture * -nv20_miptree_create(struct pipe_screen *screen, const struct pipe_texture *pt) -{ - struct nv20_miptree *mt; - unsigned buf_usage = PIPE_BUFFER_USAGE_PIXEL | - NOUVEAU_BUFFER_USAGE_TEXTURE; - - mt = MALLOC(sizeof(struct nv20_miptree)); - if (!mt) - return NULL; - mt->base = *pt; - pipe_reference_init(&mt->base.reference, 1); - mt->base.screen = screen; - - /* Swizzled textures must be POT */ - if (pt->width0 & (pt->width0 - 1) || - pt->height0 & (pt->height0 - 1)) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - else - if (pt->tex_usage & (PIPE_TEXTURE_USAGE_PRIMARY | - PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_DEPTH_STENCIL)) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - else - if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - else { - switch (pt->format) { - /* TODO: Figure out which formats can be swizzled */ - case PIPE_FORMAT_A8R8G8B8_UNORM: - case PIPE_FORMAT_X8R8G8B8_UNORM: - case PIPE_FORMAT_R16_SNORM: - { - if (debug_get_bool_option("NOUVEAU_NO_SWIZZLE", FALSE)) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - break; - } - default: - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - } - } - - if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC) - buf_usage |= PIPE_BUFFER_USAGE_CPU_READ_WRITE; - - /* apparently we can't render to swizzled surfaces smaller than 64 bytes, so make them linear. - * If the user did not ask for a render target, they can still render to it, but it will cost them an extra copy. - * This also happens for small mipmaps of large textures. */ - if (pt->tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET && util_format_get_stride(pt->format, pt->width0) < 64) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - - nv20_miptree_layout(mt); - - mt->buffer = screen->buffer_create(screen, 256, buf_usage, mt->total_size); - if (!mt->buffer) { - FREE(mt); - return NULL; - } - mt->bo = nouveau_bo(mt->buffer); - - return &mt->base; -} - -static void -nv20_miptree_destroy(struct pipe_texture *pt) -{ - struct nv20_miptree *nv20mt = (struct nv20_miptree *)pt; - int l; - - pipe_buffer_reference(&nv20mt->buffer, NULL); - for (l = 0; l <= pt->last_level; l++) { - if (nv20mt->level[l].image_offset) - FREE(nv20mt->level[l].image_offset); - } -} - -static struct pipe_surface * -nv20_miptree_surface_get(struct pipe_screen *screen, struct pipe_texture *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned flags) -{ - struct nv20_miptree *nv20mt = (struct nv20_miptree *)pt; - struct nv04_surface *ns; - - ns = CALLOC_STRUCT(nv04_surface); - if (!ns) - return NULL; - pipe_texture_reference(&ns->base.texture, pt); - ns->base.format = pt->format; - ns->base.width = u_minify(pt->width0, level); - ns->base.height = u_minify(pt->height0, level); - ns->base.usage = flags; - pipe_reference_init(&ns->base.reference, 1); - ns->base.face = face; - ns->base.level = level; - ns->base.zslice = zslice; - ns->pitch = nv20mt->level[level].pitch; - - if (pt->target == PIPE_TEXTURE_CUBE) { - ns->base.offset = nv20mt->level[level].image_offset[face]; - } else - if (pt->target == PIPE_TEXTURE_3D) { - ns->base.offset = nv20mt->level[level].image_offset[zslice]; - } else { - ns->base.offset = nv20mt->level[level].image_offset[0]; - } - - /* create a linear temporary that we can render into if necessary. - * Note that ns->pitch is always a multiple of 64 for linear surfaces and swizzled surfaces are POT, so - * ns->pitch & 63 is equivalent to (ns->pitch < 64 && swizzled)*/ - if((ns->pitch & 63) && (ns->base.usage & (PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER)) == PIPE_BUFFER_USAGE_GPU_WRITE) - return &nv04_surface_wrap_for_render(screen, ((struct nv20_screen*)screen)->eng2d, ns)->base; - - return &ns->base; -} - -static void -nv20_miptree_surface_destroy(struct pipe_surface *ps) -{ - struct nv04_surface* ns = (struct nv04_surface*)ps; - if(ns->backing) - { - struct nv20_screen* screen = (struct nv20_screen*)ps->texture->screen; - if(ns->backing->base.usage & PIPE_BUFFER_USAGE_GPU_WRITE) - screen->eng2d->copy(screen->eng2d, &ns->backing->base, 0, 0, ps, 0, 0, ns->base.width, ns->base.height); - nv20_miptree_surface_destroy(&ns->backing->base); - } - - pipe_texture_reference(&ps->texture, NULL); - FREE(ps); -} - -void nv20_screen_init_miptree_functions(struct pipe_screen *pscreen) -{ - pscreen->texture_create = nv20_miptree_create; - pscreen->texture_blanket = nv20_miptree_blanket; - pscreen->texture_destroy = nv20_miptree_destroy; - pscreen->get_tex_surface = nv20_miptree_surface_get; - pscreen->tex_surface_destroy = nv20_miptree_surface_destroy; -} - diff --git a/src/gallium/drivers/nv20/nv20_prim_vbuf.c b/src/gallium/drivers/nv20/nv20_prim_vbuf.c deleted file mode 100644 index 2e145672da..0000000000 --- a/src/gallium/drivers/nv20/nv20_prim_vbuf.c +++ /dev/null @@ -1,440 +0,0 @@ -/************************************************************************** - * - * Copyright 2007 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. - * - **************************************************************************/ - -/** - * \file - * Build post-transformation, post-clipping vertex buffers and element - * lists by hooking into the end of the primitive pipeline and - * manipulating the vertex_id field in the vertex headers. - * - * XXX: work in progress - * - * \author José Fonseca <jrfonseca@tungstengraphics.com> - * \author Keith Whitwell <keith@tungstengraphics.com> - */ - - -#include "util/u_debug.h" -#include "pipe/p_inlines.h" -#include "pipe/internal/p_winsys_screen.h" - -#include "nv20_context.h" -#include "nv20_state.h" - -#include "draw/draw_vbuf.h" - -/** - * Primitive renderer for nv20. - */ -struct nv20_vbuf_render { - struct vbuf_render base; - - struct nv20_context *nv20; - - /** Vertex buffer in VRAM */ - struct pipe_buffer *pbuffer; - - /** Vertex buffer in normal memory */ - void *mbuffer; - - /** Vertex size in bytes */ - /*unsigned vertex_size;*/ - - /** Hardware primitive */ - unsigned hwprim; -}; - -/** - * Basically a cast wrapper. - */ -static INLINE struct nv20_vbuf_render * -nv20_vbuf_render(struct vbuf_render *render) -{ - assert(render); - return (struct nv20_vbuf_render *)render; -} - -void nv20_vtxbuf_bind( struct nv20_context* nv20 ) -{ -#if 0 - struct nv20_screen *screen = nv20->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *kelvin = screen->kelvin; - int i; - for(i = 0; i < NV20TCL_VTXBUF_ADDRESS__SIZE; i++) { - BEGIN_RING(chan, kelvin, NV20TCL_VTXBUF_ADDRESS(i), 1); - OUT_RING(chan, 0/*nv20->vtxbuf*/); - BEGIN_RING(chan, kelvin, NV20TCL_VTXFMT(i) ,1); - OUT_RING(chan, 0/*XXX*/); - } -#endif -} - -static const struct vertex_info * -nv20_vbuf_render_get_vertex_info( struct vbuf_render *render ) -{ - struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render); - struct nv20_context *nv20 = nv20_render->nv20; - - nv20_emit_hw_state(nv20); - - return &nv20->vertex_info; -} - -static void * -nv20__allocate_mbuffer(struct nv20_vbuf_render *nv20_render, size_t size) -{ - nv20_render->mbuffer = MALLOC(size); - return nv20_render->mbuffer; -} - -static void -nv20__allocate_pbuffer(struct nv20_vbuf_render *nv20_render, size_t size) -{ - struct pipe_screen *screen = nv20_render->nv20->pipe.screen; - nv20_render->pbuffer = screen->buffer_create(screen, 64, - PIPE_BUFFER_USAGE_VERTEX, size); -} - -static boolean -nv20_vbuf_render_allocate_vertices( struct vbuf_render *render, - ushort vertex_size, - ushort nr_vertices ) -{ - struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render); - size_t size = (size_t)vertex_size * (size_t)nr_vertices; - void *buf; - - assert(!nv20_render->pbuffer); - assert(!nv20_render->mbuffer); - - /* - * For small amount of vertices, don't bother with pipe vertex - * buffer, the data will be passed directly via the fifo. - */ - /* XXX: Pipe vertex buffers don't work. */ - if (0 && size > 16 * 1024) { - nv20__allocate_pbuffer(nv20_render, size); - /* umm yeah so this is ugly */ - buf = nv20_render->pbuffer; - } else { - buf = nv20__allocate_mbuffer(nv20_render, size); - } - - if (buf) - nv20_render->nv20->dirty |= NV20_NEW_VTXARRAYS; - - return buf ? TRUE : FALSE; -} - -static void * -nv20_vbuf_render_map_vertices( struct vbuf_render *render ) -{ - struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render); - struct pipe_screen *pscreen = nv20_render->nv20->pipe.screen; - - if (nv20_render->pbuffer) { - return pipe_buffer_map(pscreen, nv20_render->pbuffer, - PIPE_BUFFER_USAGE_CPU_WRITE); - } else if (nv20_render->mbuffer) { - return nv20_render->mbuffer; - } else - assert(0); - - /* warnings be gone */ - return NULL; -} - -static void -nv20_vbuf_render_unmap_vertices( struct vbuf_render *render, - ushort min_index, - ushort max_index ) -{ - struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render); - struct pipe_screen *pscreen = nv20_render->nv20->pipe.screen; - - if (nv20_render->pbuffer) - pipe_buffer_unmap(pscreen, nv20_render->pbuffer); -} - -static boolean -nv20_vbuf_render_set_primitive( struct vbuf_render *render, - unsigned prim ) -{ - struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render); - unsigned hwp = nvgl_primitive(prim); - if (hwp == 0) - return FALSE; - - nv20_render->hwprim = hwp; - return TRUE; -} - -static uint32_t -nv20__vtxhwformat(unsigned stride, unsigned fields, unsigned type) -{ - return (stride << NV20TCL_VTXFMT_STRIDE_SHIFT) | - (fields << NV20TCL_VTXFMT_SIZE_SHIFT) | - (type << NV20TCL_VTXFMT_TYPE_SHIFT); -} - -static unsigned -nv20__emit_format(struct nv20_context *nv20, enum attrib_emit type, int hwattr) -{ - struct nv20_screen *screen = nv20->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *kelvin = screen->kelvin; - uint32_t hwfmt = 0; - unsigned fields; - - switch (type) { - case EMIT_OMIT: - hwfmt = nv20__vtxhwformat(0, 0, 2); - fields = 0; - break; - case EMIT_1F: - hwfmt = nv20__vtxhwformat(4, 1, 2); - fields = 1; - break; - case EMIT_2F: - hwfmt = nv20__vtxhwformat(8, 2, 2); - fields = 2; - break; - case EMIT_3F: - hwfmt = nv20__vtxhwformat(12, 3, 2); - fields = 3; - break; - case EMIT_4F: - hwfmt = nv20__vtxhwformat(16, 4, 2); - fields = 4; - break; - default: - NOUVEAU_ERR("unhandled attrib_emit %d\n", type); - return 0; - } - - BEGIN_RING(chan, kelvin, NV20TCL_VTXFMT(hwattr), 1); - OUT_RING(chan, hwfmt); - return fields; -} - -static unsigned -nv20__emit_vertex_array_format(struct nv20_context *nv20) -{ - struct vertex_info *vinfo = &nv20->vertex_info; - int hwattr = NV20TCL_VTXFMT__SIZE; - int attr = 0; - unsigned nr_fields = 0; - - while (hwattr-- > 0) { - if (vinfo->hwfmt[0] & (1 << hwattr)) { - nr_fields += nv20__emit_format(nv20, - vinfo->attrib[attr].emit, hwattr); - attr++; - } else - nv20__emit_format(nv20, EMIT_OMIT, hwattr); - } - - return nr_fields; -} - -static void -nv20__draw_mbuffer(struct nv20_vbuf_render *nv20_render, - const ushort *indices, - uint nr_indices) -{ - struct nv20_context *nv20 = nv20_render->nv20; - struct nv20_screen *screen = nv20->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *kelvin = screen->kelvin; - struct vertex_info *vinfo = &nv20->vertex_info; - unsigned nr_fields; - int max_push; - ubyte *data = nv20_render->mbuffer; - int vsz = 4 * vinfo->size; - - nr_fields = nv20__emit_vertex_array_format(nv20); - - BEGIN_RING(chan, kelvin, NV20TCL_VERTEX_BEGIN_END, 1); - OUT_RING(chan, nv20_render->hwprim); - - max_push = 1200 / nr_fields; - while (nr_indices) { - int i; - int push = MIN2(nr_indices, max_push); - - BEGIN_RING_NI(chan, kelvin, NV20TCL_VERTEX_DATA, push * nr_fields); - for (i = 0; i < push; i++) { - /* XXX: fixme to handle other than floats? */ - int f = nr_fields; - float *attrv = (float*)&data[indices[i] * vsz]; - while (f-- > 0) - OUT_RINGf(chan, *attrv++); - } - - nr_indices -= push; - indices += push; - } - - BEGIN_RING(chan, kelvin, NV20TCL_VERTEX_BEGIN_END, 1); - OUT_RING(chan, NV20TCL_VERTEX_BEGIN_END_STOP); -} - -static void -nv20__draw_pbuffer(struct nv20_vbuf_render *nv20_render, - const ushort *indices, - uint nr_indices) -{ - struct nv20_context *nv20 = nv20_render->nv20; - struct nv20_screen *screen = nv20->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *kelvin = screen->kelvin; - int push, i; - - NOUVEAU_ERR("nv20__draw_pbuffer: this path is broken.\n"); - - BEGIN_RING(chan, kelvin, NV10TCL_VERTEX_ARRAY_OFFSET_POS, 1); - OUT_RELOCl(chan, nouveau_bo(nv20_render->pbuffer), 0, - NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); - - BEGIN_RING(chan, kelvin, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1); - OUT_RING(chan, nv20_render->hwprim); - - if (nr_indices & 1) { - BEGIN_RING(chan, kelvin, NV10TCL_VB_ELEMENT_U32, 1); - OUT_RING (chan, indices[0]); - indices++; nr_indices--; - } - - while (nr_indices) { - // XXX too big/small ? check the size - push = MIN2(nr_indices, 1200 * 2); - - BEGIN_RING_NI(chan, kelvin, NV10TCL_VB_ELEMENT_U16, push >> 1); - for (i = 0; i < push; i+=2) - OUT_RING(chan, (indices[i+1] << 16) | indices[i]); - - nr_indices -= push; - indices += push; - } - - BEGIN_RING(chan, kelvin, NV10TCL_VERTEX_BUFFER_BEGIN_END, 1); - OUT_RING (chan, 0); -} - -static void -nv20_vbuf_render_draw( struct vbuf_render *render, - const ushort *indices, - uint nr_indices) -{ - struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render); - - nv20_emit_hw_state(nv20_render->nv20); - - if (nv20_render->pbuffer) - nv20__draw_pbuffer(nv20_render, indices, nr_indices); - else if (nv20_render->mbuffer) - nv20__draw_mbuffer(nv20_render, indices, nr_indices); - else - assert(0); -} - - -static void -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; - - if (nv20_render->pbuffer) { - pipe_buffer_reference(&nv20_render->pbuffer, NULL); - } else if (nv20_render->mbuffer) { - FREE(nv20_render->mbuffer); - nv20_render->mbuffer = NULL; - } else - assert(0); -} - - -static void -nv20_vbuf_render_destroy( struct vbuf_render *render ) -{ - struct nv20_vbuf_render *nv20_render = nv20_vbuf_render(render); - - assert(!nv20_render->pbuffer); - assert(!nv20_render->mbuffer); - - FREE(nv20_render); -} - - -/** - * Create a new primitive render. - */ -static struct vbuf_render * -nv20_vbuf_render_create( struct nv20_context *nv20 ) -{ - struct nv20_vbuf_render *nv20_render = CALLOC_STRUCT(nv20_vbuf_render); - - nv20_render->nv20 = nv20; - - nv20_render->base.max_vertex_buffer_bytes = 16*1024; - nv20_render->base.max_indices = 1024; - nv20_render->base.get_vertex_info = nv20_vbuf_render_get_vertex_info; - nv20_render->base.allocate_vertices = - nv20_vbuf_render_allocate_vertices; - nv20_render->base.map_vertices = nv20_vbuf_render_map_vertices; - nv20_render->base.unmap_vertices = nv20_vbuf_render_unmap_vertices; - nv20_render->base.set_primitive = nv20_vbuf_render_set_primitive; - nv20_render->base.draw = nv20_vbuf_render_draw; - nv20_render->base.release_vertices = nv20_vbuf_render_release_vertices; - nv20_render->base.destroy = nv20_vbuf_render_destroy; - - return &nv20_render->base; -} - - -/** - * Create a new primitive vbuf/render stage. - */ -struct draw_stage *nv20_draw_vbuf_stage( struct nv20_context *nv20 ) -{ - struct vbuf_render *render; - struct draw_stage *stage; - - render = nv20_vbuf_render_create(nv20); - if(!render) - return NULL; - - stage = draw_vbuf_stage( nv20->draw, render ); - if(!stage) { - render->destroy(render); - return NULL; - } - - return stage; -} diff --git a/src/gallium/drivers/nv20/nv20_screen.c b/src/gallium/drivers/nv20/nv20_screen.c deleted file mode 100644 index d091335063..0000000000 --- a/src/gallium/drivers/nv20/nv20_screen.c +++ /dev/null @@ -1,194 +0,0 @@ -#include "pipe/p_screen.h" - -#include "nv20_context.h" -#include "nv20_screen.h" - -static int -nv20_screen_get_param(struct pipe_screen *screen, int param) -{ - switch (param) { - case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: - return 2; - case PIPE_CAP_NPOT_TEXTURES: - return 0; - case PIPE_CAP_TWO_SIDED_STENCIL: - return 0; - case PIPE_CAP_GLSL: - return 0; - case PIPE_CAP_ANISOTROPIC_FILTER: - return 1; - case PIPE_CAP_POINT_SPRITE: - return 0; - case PIPE_CAP_MAX_RENDER_TARGETS: - return 1; - case PIPE_CAP_OCCLUSION_QUERY: - return 0; - case PIPE_CAP_TEXTURE_SHADOW_MAP: - return 0; - case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: - return 12; - case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: - return 0; - case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS: - 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; - default: - NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); - return 0; - } -} - -static float -nv20_screen_get_paramf(struct pipe_screen *screen, int param) -{ - switch (param) { - case PIPE_CAP_MAX_LINE_WIDTH: - case PIPE_CAP_MAX_LINE_WIDTH_AA: - return 10.0; - case PIPE_CAP_MAX_POINT_WIDTH: - case PIPE_CAP_MAX_POINT_WIDTH_AA: - return 64.0; - case PIPE_CAP_MAX_TEXTURE_ANISOTROPY: - return 2.0; - case PIPE_CAP_MAX_TEXTURE_LOD_BIAS: - return 4.0; - default: - NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); - return 0.0; - } -} - -static boolean -nv20_screen_is_format_supported(struct pipe_screen *screen, - enum pipe_format format, - enum pipe_texture_target target, - unsigned tex_usage, unsigned geom_flags) -{ - if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) { - 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: - break; - } - } else { - switch (format) { - case PIPE_FORMAT_A8R8G8B8_UNORM: - case PIPE_FORMAT_A1R5G5B5_UNORM: - case PIPE_FORMAT_A4R4G4B4_UNORM: - case PIPE_FORMAT_R5G6B5_UNORM: - case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_A8_UNORM: - case PIPE_FORMAT_I8_UNORM: - return TRUE; - default: - break; - } - } - - return FALSE; -} - -static void -nv20_screen_destroy(struct pipe_screen *pscreen) -{ - struct nv20_screen *screen = nv20_screen(pscreen); - - nouveau_notifier_free(&screen->sync); - nouveau_grobj_free(&screen->kelvin); - nv04_surface_2d_takedown(&screen->eng2d); - - nouveau_screen_fini(&screen->base); - - FREE(pscreen); -} - -static struct pipe_buffer * -nv20_surface_buffer(struct pipe_surface *surf) -{ - struct nv20_miptree *mt = (struct nv20_miptree *)surf->texture; - - return mt->buffer; -} - -struct pipe_screen * -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; - int ret; - - if (!screen) - return NULL; - pscreen = &screen->base.base; - - 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 (dev->chipset >= 0x25) - kelvin_class = NV25TCL; - else if (dev->chipset >= 0x20) - kelvin_class = NV20TCL; - - if (!kelvin_class || dev->chipset >= 0x30) { - NOUVEAU_ERR("Unknown nv2x chipset: nv%02x\n", dev->chipset); - return NULL; - } - - ret = nouveau_grobj_alloc(chan, 0xbeef0097, kelvin_class, - &screen->kelvin); - if (ret) { - NOUVEAU_ERR("Error creating 3D object: %d\n", ret); - return FALSE; - } - - /* 2D engine setup */ - screen->eng2d = nv04_surface_2d_init(&screen->base); - screen->eng2d->buf = nv20_surface_buffer; - - /* Notifier for sync purposes */ - ret = nouveau_notifier_alloc(chan, 0xbeef0301, 1, &screen->sync); - if (ret) { - NOUVEAU_ERR("Error creating notifier object: %d\n", ret); - nv20_screen_destroy(pscreen); - return NULL; - } - - return pscreen; -} - diff --git a/src/gallium/drivers/nv20/nv20_screen.h b/src/gallium/drivers/nv20/nv20_screen.h deleted file mode 100644 index fc7bb05033..0000000000 --- a/src/gallium/drivers/nv20/nv20_screen.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __NV20_SCREEN_H__ -#define __NV20_SCREEN_H__ - -#include "nouveau/nouveau_screen.h" -#include "nv04/nv04_surface_2d.h" - -struct nv20_screen { - struct nouveau_screen base; - - struct nouveau_winsys *nvws; - - /* HW graphics objects */ - struct nv04_surface_2d *eng2d; - struct nouveau_grobj *kelvin; - struct nouveau_notifier *sync; -}; - -static INLINE struct nv20_screen * -nv20_screen(struct pipe_screen *screen) -{ - return (struct nv20_screen *)screen; -} - - -void -nv20_screen_init_transfer_functions(struct pipe_screen *pscreen); - -#endif diff --git a/src/gallium/drivers/nv20/nv20_state.h b/src/gallium/drivers/nv20/nv20_state.h deleted file mode 100644 index dde4106568..0000000000 --- a/src/gallium/drivers/nv20/nv20_state.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef __NV20_STATE_H__ -#define __NV20_STATE_H__ - -#include "pipe/p_state.h" -#include "tgsi/tgsi_scan.h" - -struct nv20_blend_state { - uint32_t b_enable; - uint32_t b_srcfunc; - uint32_t b_dstfunc; - - uint32_t c_mask; - - uint32_t d_enable; -}; - -struct nv20_sampler_state { - uint32_t wrap; - uint32_t en; - uint32_t filt; - uint32_t bcol; -}; - -struct nv20_rasterizer_state { - uint32_t shade_model; - - uint32_t line_width; - uint32_t line_smooth_en; - - uint32_t point_size; - - uint32_t poly_smooth_en; - - uint32_t poly_mode_front; - uint32_t poly_mode_back; - - uint32_t front_face; - uint32_t cull_face; - uint32_t cull_face_en; - - uint32_t point_sprite; - - const struct pipe_rasterizer_state *templ; -}; - -struct nv20_vertex_program_exec { - uint32_t data[4]; - boolean has_branch_offset; - int const_index; -}; - -struct nv20_vertex_program_data { - int index; /* immediates == -1 */ - float value[4]; -}; - -struct nv20_vertex_program { - const struct pipe_shader_state *pipe; - - boolean translated; - struct nv20_vertex_program_exec *insns; - unsigned nr_insns; - struct nv20_vertex_program_data *consts; - unsigned nr_consts; - - struct nouveau_resource *exec; - unsigned exec_start; - struct nouveau_resource *data; - unsigned data_start; - unsigned data_start_min; - - uint32_t ir; - uint32_t or; -}; - -struct nv20_fragment_program_data { - unsigned offset; - unsigned index; -}; - -struct nv20_fragment_program { - struct pipe_shader_state pipe; - struct tgsi_shader_info info; - - boolean translated; - boolean on_hw; - unsigned samplers; - - uint32_t *insn; - int insn_len; - - struct nv20_fragment_program_data *consts; - unsigned nr_consts; - - struct pipe_buffer *buffer; - - uint32_t fp_control; - uint32_t fp_reg_control; -}; - - -struct nv20_depth_stencil_alpha_state { - struct { - uint32_t func; - uint32_t write_enable; - uint32_t test_enable; - } depth; - - struct { - uint32_t enable; - uint32_t wmask; - uint32_t func; - uint32_t ref; - uint32_t vmask; - uint32_t fail; - uint32_t zfail; - uint32_t zpass; - } stencil; - - struct { - uint32_t enabled; - uint32_t func; - uint32_t ref; - } alpha; -}; - -struct nv20_miptree { - struct pipe_texture base; - struct nouveau_bo *bo; - - struct pipe_buffer *buffer; - uint total_size; - - struct { - uint pitch; - uint *image_offset; - } level[PIPE_MAX_TEXTURE_LEVELS]; -}; - -#endif diff --git a/src/gallium/drivers/nv20/nv20_state_emit.c b/src/gallium/drivers/nv20/nv20_state_emit.c deleted file mode 100644 index 6bbd1fdae9..0000000000 --- a/src/gallium/drivers/nv20/nv20_state_emit.c +++ /dev/null @@ -1,426 +0,0 @@ -#include "nv20_context.h" -#include "nv20_state.h" -#include "draw/draw_context.h" - -static void nv20_state_emit_blend(struct nv20_context* nv20) -{ - struct nv20_blend_state *b = nv20->blend; - struct nv20_screen *screen = nv20->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *kelvin = screen->kelvin; - - BEGIN_RING(chan, kelvin, NV20TCL_DITHER_ENABLE, 1); - OUT_RING (chan, b->d_enable); - - BEGIN_RING(chan, kelvin, NV20TCL_BLEND_FUNC_ENABLE, 1); - OUT_RING (chan, b->b_enable); - - BEGIN_RING(chan, kelvin, NV20TCL_BLEND_FUNC_SRC, 2); - OUT_RING (chan, b->b_srcfunc); - OUT_RING (chan, b->b_dstfunc); - - BEGIN_RING(chan, kelvin, NV20TCL_COLOR_MASK, 1); - OUT_RING (chan, b->c_mask); -} - -static void nv20_state_emit_blend_color(struct nv20_context* nv20) -{ - struct pipe_blend_color *c = nv20->blend_color; - struct nv20_screen *screen = nv20->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *kelvin = screen->kelvin; - - BEGIN_RING(chan, kelvin, NV20TCL_BLEND_COLOR, 1); - OUT_RING (chan, - (float_to_ubyte(c->color[3]) << 24)| - (float_to_ubyte(c->color[0]) << 16)| - (float_to_ubyte(c->color[1]) << 8) | - (float_to_ubyte(c->color[2]) << 0)); -} - -static void nv20_state_emit_rast(struct nv20_context* nv20) -{ - struct nv20_rasterizer_state *r = nv20->rast; - struct nv20_screen *screen = nv20->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *kelvin = screen->kelvin; - - BEGIN_RING(chan, kelvin, NV20TCL_SHADE_MODEL, 2); - OUT_RING (chan, r->shade_model); - OUT_RING (chan, r->line_width); - - - BEGIN_RING(chan, kelvin, NV20TCL_POINT_SIZE, 1); - OUT_RING (chan, r->point_size); - - BEGIN_RING(chan, kelvin, NV20TCL_POLYGON_MODE_FRONT, 2); - OUT_RING (chan, r->poly_mode_front); - OUT_RING (chan, r->poly_mode_back); - - - BEGIN_RING(chan, kelvin, NV20TCL_CULL_FACE, 2); - OUT_RING (chan, r->cull_face); - OUT_RING (chan, r->front_face); - - BEGIN_RING(chan, kelvin, NV20TCL_LINE_SMOOTH_ENABLE, 2); - OUT_RING (chan, r->line_smooth_en); - OUT_RING (chan, r->poly_smooth_en); - - BEGIN_RING(chan, kelvin, NV20TCL_CULL_FACE_ENABLE, 1); - OUT_RING (chan, r->cull_face_en); -} - -static void nv20_state_emit_dsa(struct nv20_context* nv20) -{ - struct nv20_depth_stencil_alpha_state *d = nv20->dsa; - struct nv20_screen *screen = nv20->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *kelvin = screen->kelvin; - - BEGIN_RING(chan, kelvin, NV20TCL_DEPTH_FUNC, 1); - OUT_RING (chan, d->depth.func); - - BEGIN_RING(chan, kelvin, NV20TCL_DEPTH_WRITE_ENABLE, 1); - OUT_RING (chan, d->depth.write_enable); - - BEGIN_RING(chan, kelvin, NV20TCL_DEPTH_TEST_ENABLE, 1); - OUT_RING (chan, d->depth.test_enable); - - BEGIN_RING(chan, kelvin, NV20TCL_DEPTH_UNK17D8, 1); - OUT_RING (chan, 1); - -#if 0 - BEGIN_RING(chan, kelvin, NV20TCL_STENCIL_ENABLE, 1); - OUT_RING (chan, d->stencil.enable); - BEGIN_RING(chan, kelvin, NV20TCL_STENCIL_MASK, 7); - OUT_RINGp (chan, (uint32_t *)&(d->stencil.wmask), 7); -#endif - - BEGIN_RING(chan, kelvin, NV20TCL_ALPHA_FUNC_ENABLE, 1); - OUT_RING (chan, d->alpha.enabled); - - BEGIN_RING(chan, kelvin, NV20TCL_ALPHA_FUNC_FUNC, 1); - OUT_RING (chan, d->alpha.func); - - BEGIN_RING(chan, kelvin, NV20TCL_ALPHA_FUNC_REF, 1); - OUT_RING (chan, d->alpha.ref); -} - -static void nv20_state_emit_viewport(struct nv20_context* nv20) -{ -} - -static void nv20_state_emit_scissor(struct nv20_context* nv20) -{ - /* NV20TCL_SCISSOR_* is probably a software method */ -/* struct pipe_scissor_state *s = nv20->scissor; - struct nv20_screen *screen = nv20->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *kelvin = screen->kelvin; - - BEGIN_RING(chan, kelvin, NV20TCL_SCISSOR_HORIZ, 2); - OUT_RING (chan, ((s->maxx - s->minx) << 16) | s->minx); - OUT_RING (chan, ((s->maxy - s->miny) << 16) | s->miny);*/ -} - -static void nv20_state_emit_framebuffer(struct nv20_context* nv20) -{ - struct pipe_framebuffer_state* fb = nv20->framebuffer; - struct nv04_surface *rt, *zeta = NULL; - uint32_t rt_format, w, h; - int colour_format = 0, zeta_format = 0; - struct nv20_miptree *nv20mt = 0; - struct nv20_screen *screen = nv20->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *kelvin = screen->kelvin; - - w = fb->cbufs[0]->width; - h = fb->cbufs[0]->height; - colour_format = fb->cbufs[0]->format; - rt = (struct nv04_surface *)fb->cbufs[0]; - - if (fb->zsbuf) { - if (colour_format) { - assert(w == fb->zsbuf->width); - assert(h == fb->zsbuf->height); - } else { - w = fb->zsbuf->width; - h = fb->zsbuf->height; - } - - zeta_format = fb->zsbuf->format; - zeta = (struct nv04_surface *)fb->zsbuf; - } - - rt_format = NV20TCL_RT_FORMAT_TYPE_LINEAR | 0x20; - - switch (colour_format) { - case PIPE_FORMAT_X8R8G8B8_UNORM: - rt_format |= NV20TCL_RT_FORMAT_COLOR_X8R8G8B8; - break; - case PIPE_FORMAT_A8R8G8B8_UNORM: - case 0: - rt_format |= NV20TCL_RT_FORMAT_COLOR_A8R8G8B8; - break; - case PIPE_FORMAT_R5G6B5_UNORM: - rt_format |= NV20TCL_RT_FORMAT_COLOR_R5G6B5; - break; - default: - assert(0); - } - - if (zeta) { - BEGIN_RING(chan, kelvin, NV20TCL_RT_PITCH, 1); - OUT_RING (chan, rt->pitch | (zeta->pitch << 16)); - } else { - BEGIN_RING(chan, kelvin, NV20TCL_RT_PITCH, 1); - OUT_RING (chan, rt->pitch | (rt->pitch << 16)); - } - - nv20mt = (struct nv20_miptree *)rt->base.texture; - nv20->rt[0] = nv20mt->buffer; - - if (zeta_format) - { - nv20mt = (struct nv20_miptree *)zeta->base.texture; - nv20->zeta = nv20mt->buffer; - } - - BEGIN_RING(chan, kelvin, NV20TCL_RT_HORIZ, 3); - OUT_RING (chan, (w << 16) | 0); - OUT_RING (chan, (h << 16) | 0); /*NV20TCL_RT_VERT */ - OUT_RING (chan, rt_format); /* NV20TCL_RT_FORMAT */ - BEGIN_RING(chan, kelvin, NV20TCL_VIEWPORT_CLIP_HORIZ(0), 2); - OUT_RING (chan, ((w - 1) << 16) | 0); - OUT_RING (chan, ((h - 1) << 16) | 0); -} - -static void nv20_vertex_layout(struct nv20_context *nv20) -{ - struct nv20_fragment_program *fp = nv20->fragprog.current; - struct draw_context *dc = nv20->draw; - int src; - int i; - struct vertex_info *vinfo = &nv20->vertex_info; - const enum interp_mode colorInterp = INTERP_LINEAR; - boolean colors[2] = { FALSE }; - boolean generics[12] = { FALSE }; - boolean fog = FALSE; - - memset(vinfo, 0, sizeof(*vinfo)); - - /* - * Assumed NV20 hardware vertex attribute order: - * 0 position, 1 ?, 2 ?, 3 col0, - * 4 col1?, 5 ?, 6 ?, 7 ?, - * 8 ?, 9 tex0, 10 tex1, 11 tex2, - * 12 tex3, 13 ?, 14 ?, 15 ? - * unaccounted: wgh, nor, fog - * There are total 16 attrs. - * vinfo->hwfmt[0] has a used-bit corresponding to each of these. - * relation to TGSI_SEMANTIC_*: - * - POSITION: position (always used) - * - COLOR: col1, col0 - * - GENERIC: tex3, tex2, tex1, tex0, normal, weight - * - FOG: fog - */ - - for (i = 0; i < fp->info.num_inputs; i++) { - int isn = fp->info.input_semantic_name[i]; - int isi = fp->info.input_semantic_index[i]; - switch (isn) { - case TGSI_SEMANTIC_POSITION: - break; - case TGSI_SEMANTIC_COLOR: - assert(isi < 2); - colors[isi] = TRUE; - break; - case TGSI_SEMANTIC_GENERIC: - assert(isi < 12); - generics[isi] = TRUE; - break; - case TGSI_SEMANTIC_FOG: - fog = TRUE; - break; - default: - assert(0 && "unknown input_semantic_name"); - } - } - - /* always do position */ { - src = draw_find_shader_output(dc, TGSI_SEMANTIC_POSITION, 0); - draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_LINEAR, src); - vinfo->hwfmt[0] |= (1 << 0); - } - - /* two unnamed generics */ - for (i = 4; i < 6; i++) { - if (!generics[i]) - continue; - src = draw_find_shader_output(dc, TGSI_SEMANTIC_GENERIC, i); - draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src); - vinfo->hwfmt[0] |= (1 << (i - 3)); - } - - if (colors[0]) { - src = draw_find_shader_output(dc, TGSI_SEMANTIC_COLOR, 0); - draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src); - vinfo->hwfmt[0] |= (1 << 3); - } - - if (colors[1]) { - src = draw_find_shader_output(dc, TGSI_SEMANTIC_COLOR, 1); - draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src); - vinfo->hwfmt[0] |= (1 << 4); - } - - /* four unnamed generics */ - for (i = 6; i < 10; i++) { - if (!generics[i]) - continue; - src = draw_find_shader_output(dc, TGSI_SEMANTIC_GENERIC, i); - draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src); - vinfo->hwfmt[0] |= (1 << (i - 1)); - } - - /* tex0, tex1, tex2, tex3 */ - for (i = 0; i < 4; i++) { - if (!generics[i]) - continue; - src = draw_find_shader_output(dc, TGSI_SEMANTIC_GENERIC, i); - draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src); - vinfo->hwfmt[0] |= (1 << (i + 9)); - } - - /* two unnamed generics */ - for (i = 10; i < 12; i++) { - if (!generics[i]) - continue; - src = draw_find_shader_output(dc, TGSI_SEMANTIC_GENERIC, i); - draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src); - vinfo->hwfmt[0] |= (1 << (i + 3)); - } - - if (fog) { - src = draw_find_shader_output(dc, TGSI_SEMANTIC_FOG, 0); - draw_emit_vertex_attr(vinfo, EMIT_1F, INTERP_PERSPECTIVE, src); - vinfo->hwfmt[0] |= (1 << 15); - } - - draw_compute_vertex_size(vinfo); -} - -void -nv20_emit_hw_state(struct nv20_context *nv20) -{ - struct nv20_screen *screen = nv20->screen; - struct nouveau_channel *chan = screen->base.channel; - struct nouveau_grobj *kelvin = screen->kelvin; - struct nouveau_bo *rt_bo; - int i; - - if (nv20->dirty & NV20_NEW_VERTPROG) { - //nv20_vertprog_bind(nv20, nv20->vertprog.current); - nv20->dirty &= ~NV20_NEW_VERTPROG; - } - - if (nv20->dirty & NV20_NEW_FRAGPROG) { - nv20_fragprog_bind(nv20, nv20->fragprog.current); - /*XXX: clear NV20_NEW_FRAGPROG if no new program uploaded */ - nv20->dirty_samplers |= (1<<10); - nv20->dirty_samplers = 0; - } - - if (nv20->dirty_samplers || (nv20->dirty & NV20_NEW_FRAGPROG)) { - nv20_fragtex_bind(nv20); - nv20->dirty &= ~NV20_NEW_FRAGPROG; - } - - if (nv20->dirty & NV20_NEW_VTXARRAYS) { - nv20->dirty &= ~NV20_NEW_VTXARRAYS; - nv20_vertex_layout(nv20); - nv20_vtxbuf_bind(nv20); - } - - if (nv20->dirty & NV20_NEW_BLEND) { - nv20->dirty &= ~NV20_NEW_BLEND; - nv20_state_emit_blend(nv20); - } - - if (nv20->dirty & NV20_NEW_BLENDCOL) { - nv20->dirty &= ~NV20_NEW_BLENDCOL; - nv20_state_emit_blend_color(nv20); - } - - if (nv20->dirty & NV20_NEW_RAST) { - nv20->dirty &= ~NV20_NEW_RAST; - nv20_state_emit_rast(nv20); - } - - if (nv20->dirty & NV20_NEW_DSA) { - nv20->dirty &= ~NV20_NEW_DSA; - nv20_state_emit_dsa(nv20); - } - - if (nv20->dirty & NV20_NEW_VIEWPORT) { - nv20->dirty &= ~NV20_NEW_VIEWPORT; - nv20_state_emit_viewport(nv20); - } - - if (nv20->dirty & NV20_NEW_SCISSOR) { - nv20->dirty &= ~NV20_NEW_SCISSOR; - nv20_state_emit_scissor(nv20); - } - - if (nv20->dirty & NV20_NEW_FRAMEBUFFER) { - nv20->dirty &= ~NV20_NEW_FRAMEBUFFER; - nv20_state_emit_framebuffer(nv20); - } - - /* Emit relocs for every referenced buffer. - * This is to ensure the bufmgr has an accurate idea of how - * the buffer is used. This isn't very efficient, but we don't - * seem to take a significant performance hit. Will be improved - * at some point. Vertex arrays are emitted by nv20_vbo.c - */ - - /* Render target */ - rt_bo = nouveau_bo(nv20->rt[0]); - BEGIN_RING(chan, kelvin, NV20TCL_DMA_COLOR, 1); - OUT_RELOCo(chan, rt_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - BEGIN_RING(chan, kelvin, NV20TCL_COLOR_OFFSET, 1); - OUT_RELOCl(chan, rt_bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - - if (nv20->zeta) { - struct nouveau_bo *zeta_bo = nouveau_bo(nv20->zeta); - BEGIN_RING(chan, kelvin, NV20TCL_DMA_ZETA, 1); - OUT_RELOCo(chan, zeta_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - BEGIN_RING(chan, kelvin, NV20TCL_ZETA_OFFSET, 1); - OUT_RELOCl(chan, zeta_bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - /* XXX for when we allocate LMA on nv17 */ -/* BEGIN_RING(chan, kelvin, NV10TCL_LMA_DEPTH_BUFFER_OFFSET, 1); - OUT_RELOCl(chan, nouveau_bo(nv20->zeta + lma_offset));*/ - } - - /* Vertex buffer */ - BEGIN_RING(chan, kelvin, NV20TCL_DMA_VTXBUF0, 1); - OUT_RELOCo(chan, rt_bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - BEGIN_RING(chan, kelvin, NV20TCL_COLOR_OFFSET, 1); - OUT_RELOCl(chan, rt_bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); - - /* Texture images */ - for (i = 0; i < 2; i++) { - if (!(nv20->fp_samplers & (1 << i))) - continue; - struct nouveau_bo *bo = nouveau_bo(nv20->tex[i].buffer); - BEGIN_RING(chan, kelvin, NV20TCL_TX_OFFSET(i), 1); - OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | - NOUVEAU_BO_GART | NOUVEAU_BO_RD); - BEGIN_RING(chan, kelvin, NV20TCL_TX_FORMAT(i), 1); - OUT_RELOCd(chan, bo, nv20->tex[i].format, - NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | - NOUVEAU_BO_OR, NV20TCL_TX_FORMAT_DMA0, - NV20TCL_TX_FORMAT_DMA1); - } -} - diff --git a/src/gallium/drivers/nv20/nv20_surface.c b/src/gallium/drivers/nv20/nv20_surface.c deleted file mode 100644 index 4224bdd6af..0000000000 --- a/src/gallium/drivers/nv20/nv20_surface.c +++ /dev/null @@ -1,63 +0,0 @@ - -/************************************************************************** - * - * Copyright 2003 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 "nv20_context.h" -#include "pipe/p_defines.h" -#include "pipe/internal/p_winsys_screen.h" -#include "pipe/p_inlines.h" -#include "util/u_tile.h" - -static void -nv20_surface_copy(struct pipe_context *pipe, - struct pipe_surface *dest, unsigned destx, unsigned desty, - struct pipe_surface *src, unsigned srcx, unsigned srcy, - unsigned width, unsigned height) -{ - struct nv20_context *nv20 = nv20_context(pipe); - struct nv04_surface_2d *eng2d = nv20->screen->eng2d; - - eng2d->copy(eng2d, dest, destx, desty, src, srcx, srcy, width, height); -} - -static void -nv20_surface_fill(struct pipe_context *pipe, struct pipe_surface *dest, - unsigned destx, unsigned desty, unsigned width, - unsigned height, unsigned value) -{ - struct nv20_context *nv20 = nv20_context(pipe); - struct nv04_surface_2d *eng2d = nv20->screen->eng2d; - - eng2d->fill(eng2d, dest, destx, desty, width, height, value); -} - -void -nv20_init_surface_functions(struct nv20_context *nv20) -{ - nv20->pipe.surface_copy = nv20_surface_copy; - nv20->pipe.surface_fill = nv20_surface_fill; -} diff --git a/src/gallium/drivers/nv20/nv20_transfer.c b/src/gallium/drivers/nv20/nv20_transfer.c deleted file mode 100644 index 699773e8e6..0000000000 --- a/src/gallium/drivers/nv20/nv20_transfer.c +++ /dev/null @@ -1,178 +0,0 @@ -#include <pipe/p_state.h> -#include <pipe/p_defines.h> -#include <pipe/p_inlines.h> -#include <util/u_format.h> -#include <util/u_memory.h> -#include <util/u_math.h> -#include <nouveau/nouveau_winsys.h> -#include "nv20_context.h" -#include "nv20_screen.h" -#include "nv20_state.h" - -struct nv20_transfer { - struct pipe_transfer base; - struct pipe_surface *surface; - boolean direct; -}; - -static void -nv20_compatible_transfer_tex(struct pipe_texture *pt, unsigned width, unsigned height, - struct pipe_texture *template) -{ - memset(template, 0, sizeof(struct pipe_texture)); - template->target = pt->target; - template->format = pt->format; - template->width0 = width; - template->height0 = height; - template->depth0 = 1; - template->last_level = 0; - template->nr_samples = pt->nr_samples; - - template->tex_usage = PIPE_TEXTURE_USAGE_DYNAMIC | - NOUVEAU_TEXTURE_USAGE_LINEAR; -} - -static struct pipe_transfer * -nv20_transfer_new(struct pipe_screen *pscreen, struct pipe_texture *pt, - unsigned face, unsigned level, unsigned zslice, - enum pipe_transfer_usage usage, - unsigned x, unsigned y, unsigned w, unsigned h) -{ - struct nv20_miptree *mt = (struct nv20_miptree *)pt; - struct nv20_transfer *tx; - struct pipe_texture tx_tex_template, *tx_tex; - - tx = CALLOC_STRUCT(nv20_transfer); - if (!tx) - return NULL; - - pipe_texture_reference(&tx->base.texture, pt); - tx->base.x = x; - tx->base.y = y; - tx->base.width = w; - tx->base.height = h; - tx->base.stride = mt->level[level].pitch; - tx->base.usage = usage; - tx->base.face = face; - tx->base.level = level; - tx->base.zslice = zslice; - - /* Direct access to texture */ - if ((pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC || - debug_get_bool_option("NOUVEAU_NO_TRANSFER", TRUE/*XXX:FALSE*/)) && - pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) - { - tx->direct = true; - tx->surface = pscreen->get_tex_surface(pscreen, pt, - 0, 0, 0, - pipe_transfer_buffer_flags(&tx->base)); - return &tx->base; - } - - tx->direct = false; - - nv20_compatible_transfer_tex(pt, w, h, &tx_tex_template); - - tx_tex = pscreen->texture_create(pscreen, &tx_tex_template); - if (!tx_tex) - { - FREE(tx); - return NULL; - } - - tx->base.stride = ((struct nv20_miptree*)tx_tex)->level[0].pitch; - - tx->surface = pscreen->get_tex_surface(pscreen, tx_tex, - face, level, zslice, - pipe_transfer_buffer_flags(&tx->base)); - - pipe_texture_reference(&tx_tex, NULL); - - if (!tx->surface) - { - pipe_surface_reference(&tx->surface, NULL); - FREE(tx); - return NULL; - } - - if (usage & PIPE_TRANSFER_READ) { - struct nv20_screen *nvscreen = nv20_screen(pscreen); - struct pipe_surface *src; - - src = pscreen->get_tex_surface(pscreen, pt, - face, level, zslice, - PIPE_BUFFER_USAGE_GPU_READ); - - /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ - /* TODO: Check if SIFM can un-swizzle */ - nvscreen->eng2d->copy(nvscreen->eng2d, - tx->surface, 0, 0, - src, x, y, - w, h); - - pipe_surface_reference(&src, NULL); - } - - return &tx->base; -} - -static void -nv20_transfer_del(struct pipe_transfer *ptx) -{ - struct nv20_transfer *tx = (struct nv20_transfer *)ptx; - - if (!tx->direct && (ptx->usage = PIPE_TRANSFER_WRITE)) { - struct pipe_screen *pscreen = ptx->texture->screen; - struct nv20_screen *nvscreen = nv20_screen(pscreen); - struct pipe_surface *dst; - - dst = pscreen->get_tex_surface(pscreen, ptx->texture, - ptx->face, ptx->level, ptx->zslice, - PIPE_BUFFER_USAGE_GPU_WRITE | NOUVEAU_BUFFER_USAGE_NO_RENDER); - - /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */ - nvscreen->eng2d->copy(nvscreen->eng2d, - dst, tx->base.x, tx->base.y, - tx->surface, 0, 0, - tx->base.width, tx->base.height); - - pipe_surface_reference(&dst, NULL); - } - - pipe_surface_reference(&tx->surface, NULL); - pipe_texture_reference(&ptx->texture, NULL); - FREE(ptx); -} - -static void * -nv20_transfer_map(struct pipe_screen *pscreen, struct pipe_transfer *ptx) -{ - struct nv20_transfer *tx = (struct nv20_transfer *)ptx; - struct nv04_surface *ns = (struct nv04_surface *)tx->surface; - struct nv20_miptree *mt = (struct nv20_miptree *)tx->surface->texture; - void *map = pipe_buffer_map(pscreen, mt->buffer, - pipe_transfer_buffer_flags(ptx)); - - if(!tx->direct) - return map + ns->base.offset; - else - return map + ns->base.offset + ptx->y * ns->pitch + ptx->x * util_format_get_blocksize(ptx->texture->format); -} - -static void -nv20_transfer_unmap(struct pipe_screen *pscreen, struct pipe_transfer *ptx) -{ - struct nv20_transfer *tx = (struct nv20_transfer *)ptx; - struct nv20_miptree *mt = (struct nv20_miptree *)tx->surface->texture; - - pipe_buffer_unmap(pscreen, mt->buffer); -} - -void -nv20_screen_init_transfer_functions(struct pipe_screen *pscreen) -{ - pscreen->get_tex_transfer = nv20_transfer_new; - pscreen->tex_transfer_destroy = nv20_transfer_del; - pscreen->transfer_map = nv20_transfer_map; - pscreen->transfer_unmap = nv20_transfer_unmap; -} diff --git a/src/gallium/drivers/nv20/nv20_vbo.c b/src/gallium/drivers/nv20/nv20_vbo.c deleted file mode 100644 index 52991a0d85..0000000000 --- a/src/gallium/drivers/nv20/nv20_vbo.c +++ /dev/null @@ -1,79 +0,0 @@ -#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" - -#include "nouveau/nouveau_channel.h" -#include "nouveau/nouveau_pushbuf.h" - -void nv20_draw_elements( struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, - 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; - - nv20_emit_hw_state(nv20); - - /* - * Map vertex buffers - */ - for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { - if (nv20->vtxbuf[i].buffer) { - void *buf - = 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_buffer_map(pscreen, indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); - draw_set_mapped_element_buffer(draw, indexSize, mapped_indexes); - } - else { - /* no index/element buffer */ - draw_set_mapped_element_buffer(draw, 0, NULL); - } - - draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, - nv20->constbuf[PIPE_SHADER_VERTEX], - nv20->constbuf_nr[PIPE_SHADER_VERTEX]); - - /* draw! */ - draw_arrays(nv20->draw, prim, start, count); - - /* - * unmap vertex/index buffers - */ - for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { - if (nv20->vtxbuf[i].buffer) { - pipe_buffer_unmap(pscreen, nv20->vtxbuf[i].buffer); - draw_set_mapped_vertex_buffer(draw, i, NULL); - } - } - if (indexBuffer) { - pipe_buffer_unmap(pscreen, indexBuffer); - draw_set_mapped_element_buffer(draw, 0, NULL); - } - - draw_flush(nv20->draw); -} - -void nv20_draw_arrays( struct pipe_context *pipe, - unsigned prim, unsigned start, unsigned count) -{ - nv20_draw_elements(pipe, NULL, 0, prim, start, count); -} - - - diff --git a/src/gallium/drivers/nv20/nv20_vertprog.c b/src/gallium/drivers/nv20/nv20_vertprog.c deleted file mode 100644 index 7886c2af7e..0000000000 --- a/src/gallium/drivers/nv20/nv20_vertprog.c +++ /dev/null @@ -1,841 +0,0 @@ -#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" -#include "tgsi/tgsi_dump.h" - -#include "nv20_context.h" -#include "nv20_state.h" - -/* TODO (at least...): - * 1. Indexed consts + ARL - * 2. Arb. swz/negation - * 3. NV_vp11, NV_vp2, NV_vp3 features - * - extra arith opcodes - * - branching - * - texture sampling - * - indexed attribs - * - indexed results - * 4. bugs - */ - -#define SWZ_X 0 -#define SWZ_Y 1 -#define SWZ_Z 2 -#define SWZ_W 3 -#define MASK_X 8 -#define MASK_Y 4 -#define MASK_Z 2 -#define MASK_W 1 -#define MASK_ALL (MASK_X|MASK_Y|MASK_Z|MASK_W) -#define DEF_SCALE 0 -#define DEF_CTEST 0 -#include "nv20_shader.h" - -#define swz(s,x,y,z,w) nv20_sr_swz((s), SWZ_##x, SWZ_##y, SWZ_##z, SWZ_##w) -#define neg(s) nv20_sr_neg((s)) -#define abs(s) nv20_sr_abs((s)) - -struct nv20_vpc { - struct nv20_vertex_program *vp; - - struct nv20_vertex_program_exec *vpi; - - unsigned output_map[PIPE_MAX_SHADER_OUTPUTS]; - - int high_temp; - int temp_temp_count; - - struct nv20_sreg *imm; - unsigned nr_imm; -}; - -static struct nv20_sreg -temp(struct nv20_vpc *vpc) -{ - int idx; - - idx = vpc->temp_temp_count++; - idx += vpc->high_temp + 1; - return nv20_sr(NV30SR_TEMP, idx); -} - -static struct nv20_sreg -constant(struct nv20_vpc *vpc, int pipe, float x, float y, float z, float w) -{ - struct nv20_vertex_program *vp = vpc->vp; - struct nv20_vertex_program_data *vpd; - int idx; - - if (pipe >= 0) { - for (idx = 0; idx < vp->nr_consts; idx++) { - if (vp->consts[idx].index == pipe) - return nv20_sr(NV30SR_CONST, idx); - } - } - - idx = vp->nr_consts++; - vp->consts = realloc(vp->consts, sizeof(*vpd) * vp->nr_consts); - vpd = &vp->consts[idx]; - - vpd->index = pipe; - vpd->value[0] = x; - vpd->value[1] = y; - vpd->value[2] = z; - vpd->value[3] = w; - return nv20_sr(NV30SR_CONST, idx); -} - -#define arith(cc,s,o,d,m,s0,s1,s2) \ - nv20_vp_arith((cc), (s), NV30_VP_INST_##o, (d), (m), (s0), (s1), (s2)) - -static void -emit_src(struct nv20_vpc *vpc, uint32_t *hw, int pos, struct nv20_sreg src) -{ - struct nv20_vertex_program *vp = vpc->vp; - uint32_t sr = 0; - - switch (src.type) { - case NV30SR_TEMP: - sr |= (NV30_VP_SRC_REG_TYPE_TEMP << NV30_VP_SRC_REG_TYPE_SHIFT); - sr |= (src.index << NV30_VP_SRC_TEMP_SRC_SHIFT); - break; - case NV30SR_INPUT: - sr |= (NV30_VP_SRC_REG_TYPE_INPUT << - NV30_VP_SRC_REG_TYPE_SHIFT); - vp->ir |= (1 << src.index); - hw[1] |= (src.index << NV30_VP_INST_INPUT_SRC_SHIFT); - break; - case NV30SR_CONST: - sr |= (NV30_VP_SRC_REG_TYPE_CONST << - NV30_VP_SRC_REG_TYPE_SHIFT); - assert(vpc->vpi->const_index == -1 || - vpc->vpi->const_index == src.index); - vpc->vpi->const_index = src.index; - break; - case NV30SR_NONE: - sr |= (NV30_VP_SRC_REG_TYPE_INPUT << - NV30_VP_SRC_REG_TYPE_SHIFT); - break; - default: - assert(0); - } - - if (src.negate) - sr |= NV30_VP_SRC_NEGATE; - - if (src.abs) - hw[0] |= (1 << (21 + pos)); - - sr |= ((src.swz[0] << NV30_VP_SRC_SWZ_X_SHIFT) | - (src.swz[1] << NV30_VP_SRC_SWZ_Y_SHIFT) | - (src.swz[2] << NV30_VP_SRC_SWZ_Z_SHIFT) | - (src.swz[3] << NV30_VP_SRC_SWZ_W_SHIFT)); - -/* - * |VVV| - * d�.�b - * \u/ - * - */ - - switch (pos) { - case 0: - hw[1] |= ((sr & NV30_VP_SRC0_HIGH_MASK) >> - NV30_VP_SRC0_HIGH_SHIFT) << NV30_VP_INST_SRC0H_SHIFT; - hw[2] |= (sr & NV30_VP_SRC0_LOW_MASK) << - NV30_VP_INST_SRC0L_SHIFT; - break; - case 1: - hw[2] |= sr << NV30_VP_INST_SRC1_SHIFT; - break; - case 2: - hw[2] |= ((sr & NV30_VP_SRC2_HIGH_MASK) >> - NV30_VP_SRC2_HIGH_SHIFT) << NV30_VP_INST_SRC2H_SHIFT; - hw[3] |= (sr & NV30_VP_SRC2_LOW_MASK) << - NV30_VP_INST_SRC2L_SHIFT; - break; - default: - assert(0); - } -} - -static void -emit_dst(struct nv20_vpc *vpc, uint32_t *hw, int slot, struct nv20_sreg dst) -{ - struct nv20_vertex_program *vp = vpc->vp; - - switch (dst.type) { - case NV30SR_TEMP: - hw[0] |= (dst.index << NV30_VP_INST_DEST_TEMP_ID_SHIFT); - break; - case NV30SR_OUTPUT: - switch (dst.index) { - case NV30_VP_INST_DEST_COL0 : vp->or |= (1 << 0); break; - case NV30_VP_INST_DEST_COL1 : vp->or |= (1 << 1); break; - case NV30_VP_INST_DEST_BFC0 : vp->or |= (1 << 2); break; - case NV30_VP_INST_DEST_BFC1 : vp->or |= (1 << 3); break; - case NV30_VP_INST_DEST_FOGC : vp->or |= (1 << 4); break; - case NV30_VP_INST_DEST_PSZ : vp->or |= (1 << 5); break; - case NV30_VP_INST_DEST_TC(0): vp->or |= (1 << 14); break; - case NV30_VP_INST_DEST_TC(1): vp->or |= (1 << 15); break; - case NV30_VP_INST_DEST_TC(2): vp->or |= (1 << 16); break; - case NV30_VP_INST_DEST_TC(3): vp->or |= (1 << 17); break; - case NV30_VP_INST_DEST_TC(4): vp->or |= (1 << 18); break; - case NV30_VP_INST_DEST_TC(5): vp->or |= (1 << 19); break; - case NV30_VP_INST_DEST_TC(6): vp->or |= (1 << 20); break; - case NV30_VP_INST_DEST_TC(7): vp->or |= (1 << 21); break; - default: - break; - } - - hw[3] |= (dst.index << NV30_VP_INST_DEST_SHIFT); - hw[0] |= NV30_VP_INST_VEC_DEST_TEMP_MASK | (1<<20); - - /*XXX: no way this is entirely correct, someone needs to - * figure out what exactly it is. - */ - hw[3] |= 0x800; - break; - default: - assert(0); - } -} - -static void -nv20_vp_arith(struct nv20_vpc *vpc, int slot, int op, - struct nv20_sreg dst, int mask, - struct nv20_sreg s0, struct nv20_sreg s1, - struct nv20_sreg s2) -{ - struct nv20_vertex_program *vp = vpc->vp; - uint32_t *hw; - - vp->insns = realloc(vp->insns, ++vp->nr_insns * sizeof(*vpc->vpi)); - vpc->vpi = &vp->insns[vp->nr_insns - 1]; - memset(vpc->vpi, 0, sizeof(*vpc->vpi)); - vpc->vpi->const_index = -1; - - hw = vpc->vpi->data; - - hw[0] |= (NV30_VP_INST_COND_TR << NV30_VP_INST_COND_SHIFT); - hw[0] |= ((0 << NV30_VP_INST_COND_SWZ_X_SHIFT) | - (1 << NV30_VP_INST_COND_SWZ_Y_SHIFT) | - (2 << NV30_VP_INST_COND_SWZ_Z_SHIFT) | - (3 << NV30_VP_INST_COND_SWZ_W_SHIFT)); - - hw[1] |= (op << NV30_VP_INST_VEC_OPCODE_SHIFT); -// hw[3] |= NV30_VP_INST_SCA_DEST_TEMP_MASK; -// hw[3] |= (mask << NV30_VP_INST_VEC_WRITEMASK_SHIFT); - - if (dst.type == NV30SR_OUTPUT) { - if (slot) - hw[3] |= (mask << NV30_VP_INST_SDEST_WRITEMASK_SHIFT); - else - hw[3] |= (mask << NV30_VP_INST_VDEST_WRITEMASK_SHIFT); - } else { - if (slot) - hw[3] |= (mask << NV30_VP_INST_STEMP_WRITEMASK_SHIFT); - else - hw[3] |= (mask << NV30_VP_INST_VTEMP_WRITEMASK_SHIFT); - } - - emit_dst(vpc, hw, slot, dst); - emit_src(vpc, hw, 0, s0); - emit_src(vpc, hw, 1, s1); - emit_src(vpc, hw, 2, s2); -} - -static INLINE struct nv20_sreg -tgsi_src(struct nv20_vpc *vpc, const struct tgsi_full_src_register *fsrc) { - struct nv20_sreg src; - - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: - src = nv20_sr(NV30SR_INPUT, fsrc->Register.Index); - break; - case TGSI_FILE_CONSTANT: - src = constant(vpc, fsrc->Register.Index, 0, 0, 0, 0); - break; - case TGSI_FILE_IMMEDIATE: - src = vpc->imm[fsrc->Register.Index]; - break; - case TGSI_FILE_TEMPORARY: - if (vpc->high_temp < fsrc->Register.Index) - vpc->high_temp = fsrc->Register.Index; - src = nv20_sr(NV30SR_TEMP, fsrc->Register.Index); - break; - default: - NOUVEAU_ERR("bad src file\n"); - break; - } - - src.abs = fsrc->Register.Absolute; - src.negate = fsrc->Register.Negate; - src.swz[0] = fsrc->Register.SwizzleX; - src.swz[1] = fsrc->Register.SwizzleY; - src.swz[2] = fsrc->Register.SwizzleZ; - src.swz[3] = fsrc->Register.SwizzleW; - return src; -} - -static INLINE struct nv20_sreg -tgsi_dst(struct nv20_vpc *vpc, const struct tgsi_full_dst_register *fdst) { - struct nv20_sreg dst; - - switch (fdst->Register.File) { - case TGSI_FILE_OUTPUT: - dst = nv20_sr(NV30SR_OUTPUT, - vpc->output_map[fdst->Register.Index]); - - break; - case TGSI_FILE_TEMPORARY: - dst = nv20_sr(NV30SR_TEMP, fdst->Register.Index); - if (vpc->high_temp < dst.index) - vpc->high_temp = dst.index; - break; - default: - NOUVEAU_ERR("bad dst file\n"); - break; - } - - return dst; -} - -static INLINE int -tgsi_mask(uint tgsi) -{ - int mask = 0; - - if (tgsi & TGSI_WRITEMASK_X) mask |= MASK_X; - if (tgsi & TGSI_WRITEMASK_Y) mask |= MASK_Y; - if (tgsi & TGSI_WRITEMASK_Z) mask |= MASK_Z; - if (tgsi & TGSI_WRITEMASK_W) mask |= MASK_W; - return mask; -} - -static boolean -nv20_vertprog_parse_instruction(struct nv20_vpc *vpc, - const struct tgsi_full_instruction *finst) -{ - struct nv20_sreg src[3], dst, tmp; - struct nv20_sreg none = nv20_sr(NV30SR_NONE, 0); - int mask; - int ai = -1, ci = -1; - int i; - - if (finst->Instruction.Opcode == TGSI_OPCODE_END) - return TRUE; - - vpc->temp_temp_count = 0; - for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { - const struct tgsi_full_src_register *fsrc; - - fsrc = &finst->Src[i]; - if (fsrc->Register.File == TGSI_FILE_TEMPORARY) { - src[i] = tgsi_src(vpc, fsrc); - } - } - - for (i = 0; i < finst->Instruction.NumSrcRegs; i++) { - const struct tgsi_full_src_register *fsrc; - - fsrc = &finst->Src[i]; - switch (fsrc->Register.File) { - case TGSI_FILE_INPUT: - if (ai == -1 || ai == fsrc->Register.Index) { - ai = fsrc->Register.Index; - src[i] = tgsi_src(vpc, fsrc); - } else { - src[i] = temp(vpc); - arith(vpc, 0, OP_MOV, src[i], MASK_ALL, - tgsi_src(vpc, fsrc), none, none); - } - break; - /*XXX: index comparison is broken now that consts come from - * two different register files. - */ - case TGSI_FILE_CONSTANT: - case TGSI_FILE_IMMEDIATE: - if (ci == -1 || ci == fsrc->Register.Index) { - ci = fsrc->Register.Index; - src[i] = tgsi_src(vpc, fsrc); - } else { - src[i] = temp(vpc); - arith(vpc, 0, OP_MOV, src[i], MASK_ALL, - tgsi_src(vpc, fsrc), none, none); - } - break; - case TGSI_FILE_TEMPORARY: - /* handled above */ - break; - default: - NOUVEAU_ERR("bad src file\n"); - return FALSE; - } - } - - dst = tgsi_dst(vpc, &finst->Dst[0]); - mask = tgsi_mask(finst->Dst[0].Register.WriteMask); - - switch (finst->Instruction.Opcode) { - case TGSI_OPCODE_ABS: - arith(vpc, 0, OP_MOV, dst, mask, abs(src[0]), none, none); - break; - case TGSI_OPCODE_ADD: - arith(vpc, 0, OP_ADD, dst, mask, src[0], none, src[1]); - break; - case TGSI_OPCODE_ARL: - arith(vpc, 0, OP_ARL, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_DP3: - arith(vpc, 0, OP_DP3, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_DP4: - arith(vpc, 0, OP_DP4, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_DPH: - arith(vpc, 0, OP_DPH, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_DST: - arith(vpc, 0, OP_DST, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_EX2: - arith(vpc, 1, OP_EX2, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_EXP: - arith(vpc, 1, OP_EXP, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_FLR: - arith(vpc, 0, OP_FLR, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_FRC: - arith(vpc, 0, OP_FRC, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_LG2: - arith(vpc, 1, OP_LG2, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_LIT: - arith(vpc, 1, OP_LIT, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_LOG: - arith(vpc, 1, OP_LOG, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_MAD: - arith(vpc, 0, OP_MAD, dst, mask, src[0], src[1], src[2]); - break; - case TGSI_OPCODE_MAX: - arith(vpc, 0, OP_MAX, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_MIN: - arith(vpc, 0, OP_MIN, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_MOV: - arith(vpc, 0, OP_MOV, dst, mask, src[0], none, none); - break; - case TGSI_OPCODE_MUL: - arith(vpc, 0, OP_MUL, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_POW: - tmp = temp(vpc); - arith(vpc, 1, OP_LG2, tmp, MASK_X, none, none, - swz(src[0], X, X, X, X)); - arith(vpc, 0, OP_MUL, tmp, MASK_X, swz(tmp, X, X, X, X), - swz(src[1], X, X, X, X), none); - arith(vpc, 1, OP_EX2, dst, mask, none, none, - swz(tmp, X, X, X, X)); - break; - case TGSI_OPCODE_RCP: - arith(vpc, 1, OP_RCP, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_RET: - break; - case TGSI_OPCODE_RSQ: - arith(vpc, 1, OP_RSQ, dst, mask, none, none, src[0]); - break; - case TGSI_OPCODE_SGE: - arith(vpc, 0, OP_SGE, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_SGT: - arith(vpc, 0, OP_SGT, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_SLT: - arith(vpc, 0, OP_SLT, dst, mask, src[0], src[1], none); - break; - case TGSI_OPCODE_SUB: - arith(vpc, 0, OP_ADD, dst, mask, src[0], none, neg(src[1])); - break; - case TGSI_OPCODE_XPD: - tmp = temp(vpc); - arith(vpc, 0, OP_MUL, tmp, mask, - swz(src[0], Z, X, Y, Y), swz(src[1], Y, Z, X, X), none); - arith(vpc, 0, OP_MAD, dst, (mask & ~MASK_W), - swz(src[0], Y, Z, X, X), swz(src[1], Z, X, Y, Y), - neg(tmp)); - break; - default: - NOUVEAU_ERR("invalid opcode %d\n", finst->Instruction.Opcode); - return FALSE; - } - - return TRUE; -} - -static boolean -nv20_vertprog_parse_decl_output(struct nv20_vpc *vpc, - const struct tgsi_full_declaration *fdec) -{ - int hw; - - switch (fdec->Semantic.Name) { - case TGSI_SEMANTIC_POSITION: - hw = NV30_VP_INST_DEST_POS; - break; - case TGSI_SEMANTIC_COLOR: - if (fdec->Semantic.Index == 0) { - hw = NV30_VP_INST_DEST_COL0; - } else - if (fdec->Semantic.Index == 1) { - hw = NV30_VP_INST_DEST_COL1; - } else { - NOUVEAU_ERR("bad colour semantic index\n"); - return FALSE; - } - break; - case TGSI_SEMANTIC_BCOLOR: - if (fdec->Semantic.Index == 0) { - hw = NV30_VP_INST_DEST_BFC0; - } else - if (fdec->Semantic.Index == 1) { - hw = NV30_VP_INST_DEST_BFC1; - } else { - NOUVEAU_ERR("bad bcolour semantic index\n"); - return FALSE; - } - break; - case TGSI_SEMANTIC_FOG: - hw = NV30_VP_INST_DEST_FOGC; - break; - case TGSI_SEMANTIC_PSIZE: - hw = NV30_VP_INST_DEST_PSZ; - break; - case TGSI_SEMANTIC_GENERIC: - if (fdec->Semantic.Index <= 7) { - hw = NV30_VP_INST_DEST_TC(fdec->Semantic.Index); - } else { - NOUVEAU_ERR("bad generic semantic index\n"); - return FALSE; - } - break; - case TGSI_SEMANTIC_EDGEFLAG: - NOUVEAU_ERR("cannot handle edgeflag output\n"); - return FALSE; - default: - NOUVEAU_ERR("bad output semantic\n"); - return FALSE; - } - - vpc->output_map[fdec->Range.First] = hw; - return TRUE; -} - -static boolean -nv20_vertprog_prepare(struct nv20_vpc *vpc) -{ - struct tgsi_parse_context p; - int nr_imm = 0; - - tgsi_parse_init(&p, vpc->vp->pipe.tokens); - while (!tgsi_parse_end_of_tokens(&p)) { - const union tgsi_full_token *tok = &p.FullToken; - - tgsi_parse_token(&p); - switch(tok->Token.Type) { - case TGSI_TOKEN_TYPE_IMMEDIATE: - nr_imm++; - break; - default: - break; - } - } - tgsi_parse_free(&p); - - if (nr_imm) { - vpc->imm = CALLOC(nr_imm, sizeof(struct nv20_sreg)); - assert(vpc->imm); - } - - return TRUE; -} - -static void -nv20_vertprog_translate(struct nv20_context *nv20, - struct nv20_vertex_program *vp) -{ - struct tgsi_parse_context parse; - struct nv20_vpc *vpc = NULL; - - tgsi_dump(vp->pipe.tokens,0); - - vpc = CALLOC(1, sizeof(struct nv20_vpc)); - if (!vpc) - return; - vpc->vp = vp; - vpc->high_temp = -1; - - if (!nv20_vertprog_prepare(vpc)) { - FREE(vpc); - return; - } - - tgsi_parse_init(&parse, vp->pipe.tokens); - - while (!tgsi_parse_end_of_tokens(&parse)) { - tgsi_parse_token(&parse); - - switch (parse.FullToken.Token.Type) { - case TGSI_TOKEN_TYPE_DECLARATION: - { - const struct tgsi_full_declaration *fdec; - fdec = &parse.FullToken.FullDeclaration; - switch (fdec->Declaration.File) { - case TGSI_FILE_OUTPUT: - if (!nv20_vertprog_parse_decl_output(vpc, fdec)) - goto out_err; - break; - default: - break; - } - } - break; - case TGSI_TOKEN_TYPE_IMMEDIATE: - { - const struct tgsi_full_immediate *imm; - - imm = &parse.FullToken.FullImmediate; - assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32); - assert(imm->Immediate.NrTokens == 4 + 1); - vpc->imm[vpc->nr_imm++] = - constant(vpc, -1, - imm->u[0].Float, - imm->u[1].Float, - imm->u[2].Float, - imm->u[3].Float); - } - break; - case TGSI_TOKEN_TYPE_INSTRUCTION: - { - const struct tgsi_full_instruction *finst; - finst = &parse.FullToken.FullInstruction; - if (!nv20_vertprog_parse_instruction(vpc, finst)) - goto out_err; - } - break; - default: - break; - } - } - - vp->insns[vp->nr_insns - 1].data[3] |= NV30_VP_INST_LAST; - vp->translated = TRUE; -out_err: - tgsi_parse_free(&parse); - FREE(vpc); -} - -static boolean -nv20_vertprog_validate(struct nv20_context *nv20) -{ - struct pipe_screen *pscreen = nv20->pipe.screen; - struct nouveau_winsys *nvws = nv20->nvws; - struct nouveau_grobj *rankine = nv20->screen->rankine; - struct nv20_vertex_program *vp; - struct pipe_buffer *constbuf; - boolean upload_code = FALSE, upload_data = FALSE; - int i; - - vp = nv20->vertprog; - constbuf = nv20->constbuf[PIPE_SHADER_VERTEX]; - - /* Translate TGSI shader into hw bytecode */ - if (!vp->translated) { - nv20_vertprog_translate(nv20, vp); - if (!vp->translated) - return FALSE; - } - - /* Allocate hw vtxprog exec slots */ - if (!vp->exec) { - struct nouveau_resource *heap = nv20->screen->vp_exec_heap; - struct nouveau_stateobj *so; - uint vplen = vp->nr_insns; - - if (nvws->res_alloc(heap, vplen, vp, &vp->exec)) { - while (heap->next && heap->size < vplen) { - struct nv20_vertex_program *evict; - - evict = heap->next->priv; - nvws->res_free(&evict->exec); - } - - if (nvws->res_alloc(heap, vplen, vp, &vp->exec)) - assert(0); - } - - so = so_new(2, 0); - so_method(so, rankine, NV34TCL_VP_START_FROM_ID, 1); - so_data (so, vp->exec->start); - so_ref(so, &vp->so); - - upload_code = TRUE; - } - - /* Allocate hw vtxprog const slots */ - if (vp->nr_consts && !vp->data) { - struct nouveau_resource *heap = nv20->screen->vp_data_heap; - - if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) { - while (heap->next && heap->size < vp->nr_consts) { - struct nv20_vertex_program *evict; - - evict = heap->next->priv; - nvws->res_free(&evict->data); - } - - if (nvws->res_alloc(heap, vp->nr_consts, vp, &vp->data)) - assert(0); - } - - /*XXX: handle this some day */ - assert(vp->data->start >= vp->data_start_min); - - upload_data = TRUE; - if (vp->data_start != vp->data->start) - upload_code = TRUE; - } - - /* If exec or data segments moved we need to patch the program to - * fixup offsets and register IDs. - */ - if (vp->exec_start != vp->exec->start) { - for (i = 0; i < vp->nr_insns; i++) { - struct nv20_vertex_program_exec *vpi = &vp->insns[i]; - - if (vpi->has_branch_offset) { - assert(0); - } - } - - vp->exec_start = vp->exec->start; - } - - if (vp->nr_consts && vp->data_start != vp->data->start) { - for (i = 0; i < vp->nr_insns; i++) { - struct nv20_vertex_program_exec *vpi = &vp->insns[i]; - - if (vpi->const_index >= 0) { - vpi->data[1] &= ~NV30_VP_INST_CONST_SRC_MASK; - vpi->data[1] |= - (vpi->const_index + vp->data->start) << - NV30_VP_INST_CONST_SRC_SHIFT; - - } - } - - vp->data_start = vp->data->start; - } - - /* Update + Upload constant values */ - if (vp->nr_consts) { - float *map = NULL; - - if (constbuf) { - map = pipe_buffer_map(pscreen, constbuf, - PIPE_BUFFER_USAGE_CPU_READ); - } - - for (i = 0; i < vp->nr_consts; i++) { - struct nv20_vertex_program_data *vpd = &vp->consts[i]; - - if (vpd->index >= 0) { - if (!upload_data && - !memcmp(vpd->value, &map[vpd->index * 4], - 4 * sizeof(float))) - continue; - memcpy(vpd->value, &map[vpd->index * 4], - 4 * sizeof(float)); - } - - BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_CONST_ID, 5); - OUT_RING (i + vp->data->start); - OUT_RINGp ((uint32_t *)vpd->value, 4); - } - - if (constbuf) - pipe_buffer_unmap(pscreen, constbuf); - } - - /* Upload vtxprog */ - if (upload_code) { -#if 0 - for (i = 0; i < vp->nr_insns; i++) { - NOUVEAU_MSG("VP inst %d: 0x%08x 0x%08x 0x%08x 0x%08x\n", - i, vp->insns[i].data[0], vp->insns[i].data[1], - vp->insns[i].data[2], vp->insns[i].data[3]); - } -#endif - BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_FROM_ID, 1); - OUT_RING (vp->exec->start); - for (i = 0; i < vp->nr_insns; i++) { - BEGIN_RING(rankine, NV34TCL_VP_UPLOAD_INST(0), 4); - OUT_RINGp (vp->insns[i].data, 4); - } - } - - if (vp->so != nv20->state.hw[NV30_STATE_VERTPROG]) { - so_ref(vp->so, &nv20->state.hw[NV30_STATE_VERTPROG]); - return TRUE; - } - - return FALSE; -} - -void -nv20_vertprog_destroy(struct nv20_context *nv20, struct nv20_vertex_program *vp) -{ - struct nouveau_winsys *nvws = nv20->screen->nvws; - - vp->translated = FALSE; - - if (vp->nr_insns) { - FREE(vp->insns); - vp->insns = NULL; - vp->nr_insns = 0; - } - - if (vp->nr_consts) { - FREE(vp->consts); - vp->consts = NULL; - vp->nr_consts = 0; - } - - nvws->res_free(&vp->exec); - vp->exec_start = 0; - nvws->res_free(&vp->data); - vp->data_start = 0; - vp->data_start_min = 0; - - vp->ir = vp->or = 0; - so_ref(NULL, &vp->so); -} - -struct nv20_state_entry nv20_state_vertprog = { - .validate = nv20_vertprog_validate, - .dirty = { - .pipe = NV30_NEW_VERTPROG /*| NV30_NEW_UCP*/, - .hw = NV30_STATE_VERTPROG, - } -}; diff --git a/src/gallium/drivers/nv30/nv30_context.c b/src/gallium/drivers/nv30/nv30_context.c index 54572e9ab3..8bfd7b2c90 100644 --- a/src/gallium/drivers/nv30/nv30_context.c +++ b/src/gallium/drivers/nv30/nv30_context.c @@ -1,6 +1,6 @@ #include "draw/draw_context.h" #include "pipe/p_defines.h" -#include "pipe/internal/p_winsys_screen.h" +#include "util/u_simple_screen.h" #include "nv30_context.h" #include "nv30_screen.h" @@ -43,7 +43,7 @@ nv30_destroy(struct pipe_context *pipe) } struct pipe_context * -nv30_create(struct pipe_screen *pscreen, unsigned pctx_id) +nv30_create(struct pipe_screen *pscreen, void *priv) { struct nv30_screen *screen = nv30_screen(pscreen); struct pipe_winsys *ws = pscreen->winsys; @@ -54,12 +54,12 @@ nv30_create(struct pipe_screen *pscreen, unsigned pctx_id) if (!nv30) return NULL; nv30->screen = screen; - nv30->pctx_id = pctx_id; nv30->nvws = nvws; nv30->pipe.winsys = ws; nv30->pipe.screen = pscreen; + nv30->pipe.priv = priv; nv30->pipe.destroy = nv30_destroy; nv30->pipe.draw_arrays = nv30_draw_arrays; nv30->pipe.draw_elements = nv30_draw_elements; diff --git a/src/gallium/drivers/nv30/nv30_context.h b/src/gallium/drivers/nv30/nv30_context.h index e59449287b..b3b26f7f94 100644 --- a/src/gallium/drivers/nv30/nv30_context.h +++ b/src/gallium/drivers/nv30/nv30_context.h @@ -1,6 +1,8 @@ #ifndef __NV30_CONTEXT_H__ #define __NV30_CONTEXT_H__ +#include <stdio.h> + #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" @@ -8,6 +10,7 @@ #include "util/u_memory.h" #include "util/u_math.h" +#include "util/u_inlines.h" #include "draw/draw_vertex.h" @@ -108,7 +111,6 @@ struct nv30_context { struct nouveau_winsys *nvws; struct nv30_screen *screen; - unsigned pctx_id; struct draw_context *draw; @@ -206,4 +208,8 @@ extern void nv30_draw_elements(struct pipe_context *pipe, extern void nv30_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba, double depth, unsigned stencil); +/* nv30_context.c */ +struct pipe_context * +nv30_create(struct pipe_screen *pscreen, void *priv); + #endif diff --git a/src/gallium/drivers/nv30/nv30_fragprog.c b/src/gallium/drivers/nv30/nv30_fragprog.c index 2d565cb631..2c432c6dfa 100644 --- a/src/gallium/drivers/nv30/nv30_fragprog.c +++ b/src/gallium/drivers/nv30/nv30_fragprog.c @@ -1,7 +1,7 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_shader_tokens.h" #include "tgsi/tgsi_dump.h" diff --git a/src/gallium/drivers/nv30/nv30_fragtex.c b/src/gallium/drivers/nv30/nv30_fragtex.c index 9893567891..0cc3172dcd 100644 --- a/src/gallium/drivers/nv30/nv30_fragtex.c +++ b/src/gallium/drivers/nv30/nv30_fragtex.c @@ -43,7 +43,6 @@ static struct nv30_texture_format * nv30_fragtex_format(uint pipe_format) { struct nv30_texture_format *tf = nv30_texture_formats; - char fs[128]; while (tf->defined) { if (tf->pipe == pipe_format) @@ -65,7 +64,7 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit) struct nouveau_bo *bo = nouveau_bo(nv30mt->buffer); struct nv30_texture_format *tf; struct nouveau_stateobj *so; - uint32_t txf, txs , txp; + uint32_t txf, txs; unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; tf = nv30_fragtex_format(pt->format); @@ -97,13 +96,6 @@ nv30_fragtex_build(struct nv30_context *nv30, int unit) return NULL; } - if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) { - txp = 0; - } else { - txp = nv30mt->level[0].pitch; - txf |= (1<<13) /*FIXME: NV34TCL_TX_FORMAT_LINEAR ? */; - } - txs = tf->swizzle; so = so_new(1, 8, 2); diff --git a/src/gallium/drivers/nv30/nv30_miptree.c b/src/gallium/drivers/nv30/nv30_miptree.c index 8fbba38e78..c29c36e20a 100644 --- a/src/gallium/drivers/nv30/nv30_miptree.c +++ b/src/gallium/drivers/nv30/nv30_miptree.c @@ -1,11 +1,11 @@ #include "pipe/p_state.h" #include "pipe/p_defines.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_format.h" #include "util/u_math.h" #include "nv30_context.h" -#include "../nv04/nv04_surface_2d.h" +#include "../nouveau/nv04_surface_2d.h" static void nv30_miptree_layout(struct nv30_miptree *nv30mt) diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c index 9ed48178dc..8f9b26ea56 100644 --- a/src/gallium/drivers/nv30/nv30_screen.c +++ b/src/gallium/drivers/nv30/nv30_screen.c @@ -20,9 +20,6 @@ struct nouveau_winsys { struct pipe_screen *pscreen; - unsigned nr_pctx; - struct pipe_context **pctx; - struct pipe_surface *front; }; @@ -67,6 +64,16 @@ nv30_screen_get_param(struct pipe_screen *pscreen, int param) case NOUVEAU_CAP_HW_VTXBUF: case NOUVEAU_CAP_HW_IDXBUF: return 1; + case PIPE_CAP_INDEP_BLEND_ENABLE: + return 0; + case PIPE_CAP_INDEP_BLEND_FUNC: + return 0; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 0; default: NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); return 0; @@ -163,9 +170,9 @@ nv30_screen_destroy(struct pipe_screen *pscreen) so_ref(NULL, &screen->state[i]); } - nouveau_resource_free(&screen->vp_exec_heap); - nouveau_resource_free(&screen->vp_data_heap); - nouveau_resource_free(&screen->query_heap); + nouveau_resource_destroy(&screen->vp_exec_heap); + nouveau_resource_destroy(&screen->vp_data_heap); + nouveau_resource_destroy(&screen->query_heap); nouveau_notifier_free(&screen->query); nouveau_notifier_free(&screen->sync); nouveau_grobj_free(&screen->rankine); @@ -202,6 +209,7 @@ nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) pscreen->get_param = nv30_screen_get_param; pscreen->get_paramf = nv30_screen_get_paramf; pscreen->is_format_supported = nv30_screen_surface_format_supported; + pscreen->context_create = nv30_create; nv30_screen_init_miptree_functions(pscreen); nv30_screen_init_transfer_functions(pscreen); diff --git a/src/gallium/drivers/nv30/nv30_screen.h b/src/gallium/drivers/nv30/nv30_screen.h index 5fbd998b53..8591cd31ca 100644 --- a/src/gallium/drivers/nv30/nv30_screen.h +++ b/src/gallium/drivers/nv30/nv30_screen.h @@ -3,14 +3,14 @@ #include "nouveau/nouveau_screen.h" -#include "nv04/nv04_surface_2d.h" +#include "nouveau/nv04_surface_2d.h" struct nv30_screen { struct nouveau_screen base; struct nouveau_winsys *nvws; - unsigned cur_pctx; + struct nv30_context *cur_ctx; /* HW graphics objects */ struct nv04_surface_2d *eng2d; diff --git a/src/gallium/drivers/nv30/nv30_state.c b/src/gallium/drivers/nv30/nv30_state.c index 66096de61e..f775938ba7 100644 --- a/src/gallium/drivers/nv30/nv30_state.c +++ b/src/gallium/drivers/nv30/nv30_state.c @@ -1,6 +1,6 @@ #include "pipe/p_state.h" #include "pipe/p_defines.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "tgsi/tgsi_parse.h" @@ -16,27 +16,27 @@ nv30_blend_state_create(struct pipe_context *pipe, struct nv30_blend_state *bso = CALLOC(1, sizeof(*bso)); struct nouveau_stateobj *so = so_new(5, 8, 0); - if (cso->blend_enable) { + if (cso->rt[0].blend_enable) { so_method(so, rankine, NV34TCL_BLEND_FUNC_ENABLE, 3); so_data (so, 1); - so_data (so, (nvgl_blend_func(cso->alpha_src_factor) << 16) | - nvgl_blend_func(cso->rgb_src_factor)); - so_data (so, nvgl_blend_func(cso->alpha_dst_factor) << 16 | - nvgl_blend_func(cso->rgb_dst_factor)); + so_data (so, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) | + nvgl_blend_func(cso->rt[0].rgb_src_factor)); + so_data (so, nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16 | + nvgl_blend_func(cso->rt[0].rgb_dst_factor)); /* FIXME: Gallium assumes GL_EXT_blend_func_separate. It is not the case for NV30 */ so_method(so, rankine, NV34TCL_BLEND_EQUATION, 1); - so_data (so, nvgl_blend_eqn(cso->rgb_func)); + so_data (so, nvgl_blend_eqn(cso->rt[0].rgb_func)); } else { so_method(so, rankine, NV34TCL_BLEND_FUNC_ENABLE, 1); so_data (so, 0); } so_method(so, rankine, NV34TCL_COLOR_MASK, 1); - so_data (so, (((cso->colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) | - ((cso->colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) | - ((cso->colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) | - ((cso->colormask & PIPE_MASK_B) ? (0x01 << 0) : 0))); + so_data (so, (((cso->rt[0].colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_B) ? (0x01 << 0) : 0))); if (cso->logicop_enable) { so_method(so, rankine, NV34TCL_COLOR_LOGIC_OP_ENABLE, 2); @@ -590,12 +590,12 @@ nv30_set_clip_state(struct pipe_context *pipe, static void nv30_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - const struct pipe_constant_buffer *buf ) + struct pipe_buffer *buf ) { struct nv30_context *nv30 = nv30_context(pipe); - nv30->constbuf[shader] = buf->buffer; - nv30->constbuf_nr[shader] = buf->buffer->size / (4 * sizeof(float)); + nv30->constbuf[shader] = buf; + nv30->constbuf_nr[shader] = buf->size / (4 * sizeof(float)); if (shader == PIPE_SHADER_VERTEX) { nv30->dirty |= NV30_NEW_VERTPROG; diff --git a/src/gallium/drivers/nv30/nv30_state_emit.c b/src/gallium/drivers/nv30/nv30_state_emit.c index ac52d946f0..d9650f63eb 100644 --- a/src/gallium/drivers/nv30/nv30_state_emit.c +++ b/src/gallium/drivers/nv30/nv30_state_emit.c @@ -44,13 +44,15 @@ nv30_state_emit(struct nv30_context *nv30) unsigned i; uint64_t states; - if (nv30->pctx_id != screen->cur_pctx) { + /* XXX: racy! + */ + if (nv30 != screen->cur_ctx) { for (i = 0; i < NV30_STATE_MAX; i++) { if (state->hw[i] && screen->state[i] != state->hw[i]) state->dirty |= (1ULL << i); } - screen->cur_pctx = nv30->pctx_id; + screen->cur_ctx = nv30; } for (i = 0, states = state->dirty; states; i++) { diff --git a/src/gallium/drivers/nv30/nv30_surface.c b/src/gallium/drivers/nv30/nv30_surface.c index 5e237e13eb..b48c5ab51a 100644 --- a/src/gallium/drivers/nv30/nv30_surface.c +++ b/src/gallium/drivers/nv30/nv30_surface.c @@ -28,8 +28,8 @@ #include "nv30_context.h" #include "pipe/p_defines.h" -#include "pipe/internal/p_winsys_screen.h" -#include "pipe/p_inlines.h" +#include "util/u_simple_screen.h" +#include "util/u_inlines.h" #include "util/u_tile.h" static void diff --git a/src/gallium/drivers/nv30/nv30_transfer.c b/src/gallium/drivers/nv30/nv30_transfer.c index 65598991c6..554bcbbdd0 100644 --- a/src/gallium/drivers/nv30/nv30_transfer.c +++ b/src/gallium/drivers/nv30/nv30_transfer.c @@ -1,6 +1,6 @@ #include <pipe/p_state.h> #include <pipe/p_defines.h> -#include <pipe/p_inlines.h> +#include <util/u_inlines.h> #include <util/u_format.h> #include <util/u_memory.h> #include <util/u_math.h> diff --git a/src/gallium/drivers/nv30/nv30_vbo.c b/src/gallium/drivers/nv30/nv30_vbo.c index 1c5db03ea2..a83ddf1154 100644 --- a/src/gallium/drivers/nv30/nv30_vbo.c +++ b/src/gallium/drivers/nv30/nv30_vbo.c @@ -1,6 +1,6 @@ #include "pipe/p_context.h" #include "pipe/p_state.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "nv30_context.h" #include "nv30_state.h" @@ -223,7 +223,6 @@ nv30_draw_arrays(struct pipe_context *pipe, } pipe->flush(pipe, 0, NULL); - return TRUE; } static INLINE void @@ -382,7 +381,7 @@ nv30_draw_elements_inline(struct pipe_context *pipe, map = pipe_buffer_map(pscreen, ib, PIPE_BUFFER_USAGE_CPU_READ); if (!ib) { NOUVEAU_ERR("failed mapping ib\n"); - return FALSE; + return; } switch (ib_size) { @@ -424,7 +423,7 @@ nv30_draw_elements_vbo(struct pipe_context *pipe, FIRE_RING(chan); continue; } - + BEGIN_RING(chan, rankine, NV34TCL_VERTEX_BEGIN_END, 1); OUT_RING (chan, nvgl_primitive(mode)); @@ -468,7 +467,7 @@ nv30_draw_elements(struct pipe_context *pipe, if (FORCE_SWTNL || !nv30_state_validate(nv30)) { /*return nv30_draw_elements_swtnl(pipe, NULL, 0, mode, start, count);*/ - return; + return; } if (idxbuf) { diff --git a/src/gallium/drivers/nv30/nv30_vertprog.c b/src/gallium/drivers/nv30/nv30_vertprog.c index e77a5be3f2..809be3712d 100644 --- a/src/gallium/drivers/nv30/nv30_vertprog.c +++ b/src/gallium/drivers/nv30/nv30_vertprog.c @@ -1,7 +1,7 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_shader_tokens.h" #include "tgsi/tgsi_parse.h" diff --git a/src/gallium/drivers/nv40/nv40_context.c b/src/gallium/drivers/nv40/nv40_context.c index f79ae4db84..b0b90032de 100644 --- a/src/gallium/drivers/nv40/nv40_context.c +++ b/src/gallium/drivers/nv40/nv40_context.c @@ -1,6 +1,6 @@ #include "draw/draw_context.h" #include "pipe/p_defines.h" -#include "pipe/internal/p_winsys_screen.h" +#include "util/u_simple_screen.h" #include "nv40_context.h" #include "nv40_screen.h" @@ -43,7 +43,7 @@ nv40_destroy(struct pipe_context *pipe) } struct pipe_context * -nv40_create(struct pipe_screen *pscreen, unsigned pctx_id) +nv40_create(struct pipe_screen *pscreen, void *priv) { struct nv40_screen *screen = nv40_screen(pscreen); struct pipe_winsys *ws = pscreen->winsys; @@ -54,11 +54,11 @@ nv40_create(struct pipe_screen *pscreen, unsigned pctx_id) if (!nv40) return NULL; nv40->screen = screen; - nv40->pctx_id = pctx_id; nv40->nvws = nvws; nv40->pipe.winsys = ws; + nv40->pipe.priv = priv; nv40->pipe.screen = pscreen; nv40->pipe.destroy = nv40_destroy; nv40->pipe.draw_arrays = nv40_draw_arrays; diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h index e219bb537a..958a48f2a4 100644 --- a/src/gallium/drivers/nv40/nv40_context.h +++ b/src/gallium/drivers/nv40/nv40_context.h @@ -1,6 +1,8 @@ #ifndef __NV40_CONTEXT_H__ #define __NV40_CONTEXT_H__ +#include <stdio.h> + #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" @@ -8,6 +10,7 @@ #include "util/u_memory.h" #include "util/u_math.h" +#include "util/u_inlines.h" #include "draw/draw_vertex.h" @@ -108,7 +111,6 @@ struct nv40_context { struct nouveau_winsys *nvws; struct nv40_screen *screen; - unsigned pctx_id; struct draw_context *draw; @@ -227,4 +229,8 @@ extern void nv40_draw_elements(struct pipe_context *pipe, extern void nv40_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba, double depth, unsigned stencil); +/* nv40_context.c */ +struct pipe_context * +nv40_create(struct pipe_screen *pscreen, void *priv); + #endif diff --git a/src/gallium/drivers/nv40/nv40_draw.c b/src/gallium/drivers/nv40/nv40_draw.c index d826f8c2f5..60ab49fad1 100644 --- a/src/gallium/drivers/nv40/nv40_draw.c +++ b/src/gallium/drivers/nv40/nv40_draw.c @@ -1,5 +1,5 @@ #include "pipe/p_shader_tokens.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_pack_color.h" @@ -271,7 +271,7 @@ nv40_draw_elements_swtnl(struct pipe_context *pipe, map = pipe_buffer_map(pscreen, nv40->constbuf[PIPE_SHADER_VERTEX], PIPE_BUFFER_USAGE_CPU_READ); - draw_set_mapped_constant_buffer(nv40->draw, PIPE_SHADER_VERTEX, + draw_set_mapped_constant_buffer(nv40->draw, PIPE_SHADER_VERTEX, 0, map, nr); } diff --git a/src/gallium/drivers/nv40/nv40_fragprog.c b/src/gallium/drivers/nv40/nv40_fragprog.c index 1237066c39..dc24f9b08a 100644 --- a/src/gallium/drivers/nv40/nv40_fragprog.c +++ b/src/gallium/drivers/nv40/nv40_fragprog.c @@ -1,7 +1,7 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_shader_tokens.h" #include "tgsi/tgsi_parse.h" diff --git a/src/gallium/drivers/nv40/nv40_miptree.c b/src/gallium/drivers/nv40/nv40_miptree.c index 89bd155ff4..ad1a9a5195 100644 --- a/src/gallium/drivers/nv40/nv40_miptree.c +++ b/src/gallium/drivers/nv40/nv40_miptree.c @@ -1,11 +1,11 @@ #include "pipe/p_state.h" #include "pipe/p_defines.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_format.h" #include "util/u_math.h" #include "nv40_context.h" -#include "../nv04/nv04_surface_2d.h" +#include "../nouveau/nv04_surface_2d.h" diff --git a/src/gallium/drivers/nv40/nv40_screen.c b/src/gallium/drivers/nv40/nv40_screen.c index 9e55e5a089..001147e752 100644 --- a/src/gallium/drivers/nv40/nv40_screen.c +++ b/src/gallium/drivers/nv40/nv40_screen.c @@ -52,6 +52,16 @@ nv40_screen_get_param(struct pipe_screen *pscreen, int param) if (screen->curie->grclass == NV40TCL) return 1; return 0; + case PIPE_CAP_INDEP_BLEND_ENABLE: + return 0; + case PIPE_CAP_INDEP_BLEND_FUNC: + return 0; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 0; default: NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); return 0; @@ -147,9 +157,9 @@ nv40_screen_destroy(struct pipe_screen *pscreen) so_ref(NULL, &screen->state[i]); } - nouveau_resource_free(&screen->vp_exec_heap); - nouveau_resource_free(&screen->vp_data_heap); - nouveau_resource_free(&screen->query_heap); + nouveau_resource_destroy(&screen->vp_exec_heap); + nouveau_resource_destroy(&screen->vp_data_heap); + nouveau_resource_destroy(&screen->query_heap); nouveau_notifier_free(&screen->query); nouveau_notifier_free(&screen->sync); nouveau_grobj_free(&screen->curie); @@ -186,6 +196,7 @@ nv40_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) pscreen->get_param = nv40_screen_get_param; pscreen->get_paramf = nv40_screen_get_paramf; pscreen->is_format_supported = nv40_screen_surface_format_supported; + pscreen->context_create = nv40_create; nv40_screen_init_miptree_functions(pscreen); nv40_screen_init_transfer_functions(pscreen); diff --git a/src/gallium/drivers/nv40/nv40_screen.h b/src/gallium/drivers/nv40/nv40_screen.h index 57b4c8fc46..9437aa050d 100644 --- a/src/gallium/drivers/nv40/nv40_screen.h +++ b/src/gallium/drivers/nv40/nv40_screen.h @@ -2,14 +2,14 @@ #define __NV40_SCREEN_H__ #include "nouveau/nouveau_screen.h" -#include "nv04/nv04_surface_2d.h" +#include "nouveau/nv04_surface_2d.h" struct nv40_screen { struct nouveau_screen base; struct nouveau_winsys *nvws; - unsigned cur_pctx; + struct nv40_context *cur_ctx; /* HW graphics objects */ struct nv04_surface_2d *eng2d; diff --git a/src/gallium/drivers/nv40/nv40_state.c b/src/gallium/drivers/nv40/nv40_state.c index 5084c48eeb..51b40e51e4 100644 --- a/src/gallium/drivers/nv40/nv40_state.c +++ b/src/gallium/drivers/nv40/nv40_state.c @@ -1,6 +1,6 @@ #include "pipe/p_state.h" #include "pipe/p_defines.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "draw/draw_context.h" @@ -18,26 +18,26 @@ nv40_blend_state_create(struct pipe_context *pipe, struct nv40_blend_state *bso = CALLOC(1, sizeof(*bso)); struct nouveau_stateobj *so = so_new(5, 8, 0); - if (cso->blend_enable) { + if (cso->rt[0].blend_enable) { so_method(so, curie, NV40TCL_BLEND_ENABLE, 3); so_data (so, 1); - so_data (so, (nvgl_blend_func(cso->alpha_src_factor) << 16) | - nvgl_blend_func(cso->rgb_src_factor)); - so_data (so, nvgl_blend_func(cso->alpha_dst_factor) << 16 | - nvgl_blend_func(cso->rgb_dst_factor)); + so_data (so, (nvgl_blend_func(cso->rt[0].alpha_src_factor) << 16) | + nvgl_blend_func(cso->rt[0].rgb_src_factor)); + so_data (so, nvgl_blend_func(cso->rt[0].alpha_dst_factor) << 16 | + nvgl_blend_func(cso->rt[0].rgb_dst_factor)); so_method(so, curie, NV40TCL_BLEND_EQUATION, 1); - so_data (so, nvgl_blend_eqn(cso->alpha_func) << 16 | - nvgl_blend_eqn(cso->rgb_func)); + so_data (so, nvgl_blend_eqn(cso->rt[0].alpha_func) << 16 | + nvgl_blend_eqn(cso->rt[0].rgb_func)); } else { so_method(so, curie, NV40TCL_BLEND_ENABLE, 1); so_data (so, 0); } so_method(so, curie, NV40TCL_COLOR_MASK, 1); - so_data (so, (((cso->colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) | - ((cso->colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) | - ((cso->colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) | - ((cso->colormask & PIPE_MASK_B) ? (0x01 << 0) : 0))); + so_data (so, (((cso->rt[0].colormask & PIPE_MASK_A) ? (0x01 << 24) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_R) ? (0x01 << 16) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_G) ? (0x01 << 8) : 0) | + ((cso->rt[0].colormask & PIPE_MASK_B) ? (0x01 << 0) : 0))); if (cso->logicop_enable) { so_method(so, curie, NV40TCL_COLOR_LOGIC_OP_ENABLE, 2); @@ -605,12 +605,12 @@ nv40_set_clip_state(struct pipe_context *pipe, static void nv40_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - const struct pipe_constant_buffer *buf ) + struct pipe_buffer *buf ) { struct nv40_context *nv40 = nv40_context(pipe); - nv40->constbuf[shader] = buf->buffer; - nv40->constbuf_nr[shader] = buf->buffer->size / (4 * sizeof(float)); + nv40->constbuf[shader] = buf; + nv40->constbuf_nr[shader] = buf->size / (4 * sizeof(float)); if (shader == PIPE_SHADER_VERTEX) { nv40->dirty |= NV40_NEW_VERTPROG; diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c index 13fe854915..1c4007a129 100644 --- a/src/gallium/drivers/nv40/nv40_state_emit.c +++ b/src/gallium/drivers/nv40/nv40_state_emit.c @@ -61,13 +61,15 @@ nv40_state_emit(struct nv40_context *nv40) unsigned i; uint64_t states; - if (nv40->pctx_id != screen->cur_pctx) { + /* XXX: race conditions + */ + if (nv40 != screen->cur_ctx) { for (i = 0; i < NV40_STATE_MAX; i++) { if (state->hw[i] && screen->state[i] != state->hw[i]) state->dirty |= (1ULL << i); } - screen->cur_pctx = nv40->pctx_id; + screen->cur_ctx = nv40; } for (i = 0, states = state->dirty; states; i++) { diff --git a/src/gallium/drivers/nv40/nv40_surface.c b/src/gallium/drivers/nv40/nv40_surface.c index a596547974..02ecfd7bbb 100644 --- a/src/gallium/drivers/nv40/nv40_surface.c +++ b/src/gallium/drivers/nv40/nv40_surface.c @@ -27,7 +27,7 @@ **************************************************************************/ #include "pipe/p_defines.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_tile.h" diff --git a/src/gallium/drivers/nv40/nv40_transfer.c b/src/gallium/drivers/nv40/nv40_transfer.c index 791ee6823d..ee266c6cfb 100644 --- a/src/gallium/drivers/nv40/nv40_transfer.c +++ b/src/gallium/drivers/nv40/nv40_transfer.c @@ -1,6 +1,6 @@ #include <pipe/p_state.h> #include <pipe/p_defines.h> -#include <pipe/p_inlines.h> +#include <util/u_inlines.h> #include <util/u_format.h> #include <util/u_memory.h> #include <util/u_math.h> diff --git a/src/gallium/drivers/nv40/nv40_vbo.c b/src/gallium/drivers/nv40/nv40_vbo.c index a777898f68..1e14edc56a 100644 --- a/src/gallium/drivers/nv40/nv40_vbo.c +++ b/src/gallium/drivers/nv40/nv40_vbo.c @@ -1,6 +1,6 @@ #include "pipe/p_context.h" #include "pipe/p_state.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "nv40_context.h" #include "nv40_state.h" @@ -382,7 +382,7 @@ nv40_draw_elements_inline(struct pipe_context *pipe, map = pipe_buffer_map(pscreen, ib, PIPE_BUFFER_USAGE_CPU_READ); if (!ib) { NOUVEAU_ERR("failed mapping ib\n"); - return FALSE; + return; } switch (ib_size) { @@ -424,7 +424,7 @@ nv40_draw_elements_vbo(struct pipe_context *pipe, FIRE_RING(chan); continue; } - + BEGIN_RING(chan, curie, NV40TCL_BEGIN_END, 1); OUT_RING (chan, nvgl_primitive(mode)); diff --git a/src/gallium/drivers/nv40/nv40_vertprog.c b/src/gallium/drivers/nv40/nv40_vertprog.c index 8d80fcad38..b289eef0fc 100644 --- a/src/gallium/drivers/nv40/nv40_vertprog.c +++ b/src/gallium/drivers/nv40/nv40_vertprog.c @@ -1,7 +1,7 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_shader_tokens.h" #include "tgsi/tgsi_parse.h" diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index 5997456e4c..867bd03e69 100644 --- a/src/gallium/drivers/nv50/nv50_context.c +++ b/src/gallium/drivers/nv50/nv50_context.c @@ -22,7 +22,7 @@ #include "draw/draw_context.h" #include "pipe/p_defines.h" -#include "pipe/internal/p_winsys_screen.h" +#include "util/u_simple_screen.h" #include "nv50_context.h" #include "nv50_screen.h" @@ -34,6 +34,11 @@ nv50_flush(struct pipe_context *pipe, unsigned flags, struct nv50_context *nv50 = nv50_context(pipe); struct nouveau_channel *chan = nv50->screen->base.channel; + if (flags & PIPE_FLUSH_TEXTURE_CACHE) { + BEGIN_RING(chan, nv50->screen->tesla, 0x1338, 1); + OUT_RING (chan, 0x20); + } + if (flags & PIPE_FLUSH_FRAME) FIRE_RING(chan); } @@ -67,8 +72,12 @@ nv50_destroy(struct pipe_context *pipe) so_ref(NULL, &nv50->state.vertprog); if (nv50->state.fragprog) so_ref(NULL, &nv50->state.fragprog); - if (nv50->state.programs) - so_ref(NULL, &nv50->state.programs); + if (nv50->state.geomprog) + so_ref(NULL, &nv50->state.geomprog); + if (nv50->state.fp_linkage) + so_ref(NULL, &nv50->state.fp_linkage); + if (nv50->state.gp_linkage) + so_ref(NULL, &nv50->state.gp_linkage); if (nv50->state.vtxfmt) so_ref(NULL, &nv50->state.vtxfmt); if (nv50->state.vtxbuf) @@ -77,12 +86,16 @@ nv50_destroy(struct pipe_context *pipe) so_ref(NULL, &nv50->state.vtxattr); draw_destroy(nv50->draw); + + if (nv50->screen->cur_ctx == nv50) + nv50->screen->cur_ctx = NULL; + FREE(nv50); } struct pipe_context * -nv50_create(struct pipe_screen *pscreen, unsigned pctx_id) +nv50_create(struct pipe_screen *pscreen, void *priv) { struct pipe_winsys *pipe_winsys = pscreen->winsys; struct nv50_screen *screen = nv50_screen(pscreen); @@ -92,15 +105,17 @@ nv50_create(struct pipe_screen *pscreen, unsigned pctx_id) if (!nv50) return NULL; nv50->screen = screen; - nv50->pctx_id = pctx_id; nv50->pipe.winsys = pipe_winsys; nv50->pipe.screen = pscreen; + nv50->pipe.priv = priv; nv50->pipe.destroy = nv50_destroy; nv50->pipe.draw_arrays = nv50_draw_arrays; + nv50->pipe.draw_arrays_instanced = nv50_draw_arrays_instanced; nv50->pipe.draw_elements = nv50_draw_elements; + nv50->pipe.draw_elements_instanced = nv50_draw_elements_instanced; nv50->pipe.clear = nv50_clear; nv50->pipe.flush = nv50_flush; diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index cbd4c3ff86..14cef4c0bf 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -1,6 +1,7 @@ #ifndef __NV50_CONTEXT_H__ #define __NV50_CONTEXT_H__ +#include <stdio.h> #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" @@ -8,6 +9,7 @@ #include "util/u_memory.h" #include "util/u_math.h" +#include "util/u_inlines.h" #include "draw/draw_vertex.h" @@ -29,9 +31,7 @@ #define NV50_CB_PVP 1 #define NV50_CB_PFP 2 #define NV50_CB_PGP 3 -#define NV50_CB_TIC 4 -#define NV50_CB_TSC 5 -#define NV50_CB_PUPLOAD 6 +#define NV50_CB_AUX 4 #define NV50_NEW_BLEND (1 << 0) #define NV50_NEW_ZSA (1 << 1) @@ -45,9 +45,11 @@ #define NV50_NEW_VERTPROG_CB (1 << 9) #define NV50_NEW_FRAGPROG (1 << 10) #define NV50_NEW_FRAGPROG_CB (1 << 11) -#define NV50_NEW_ARRAYS (1 << 12) -#define NV50_NEW_SAMPLER (1 << 13) -#define NV50_NEW_TEXTURE (1 << 14) +#define NV50_NEW_GEOMPROG (1 << 12) +#define NV50_NEW_GEOMPROG_CB (1 << 13) +#define NV50_NEW_ARRAYS (1 << 14) +#define NV50_NEW_SAMPLER (1 << 15) +#define NV50_NEW_TEXTURE (1 << 16) struct nv50_blend_stateobj { struct pipe_blend_state pipe; @@ -129,10 +131,13 @@ struct nv50_state { unsigned miptree_nr[PIPE_SHADER_TYPES]; struct nouveau_stateobj *vertprog; struct nouveau_stateobj *fragprog; - struct nouveau_stateobj *programs; + struct nouveau_stateobj *geomprog; + struct nouveau_stateobj *fp_linkage; + struct nouveau_stateobj *gp_linkage; struct nouveau_stateobj *vtxfmt; struct nouveau_stateobj *vtxbuf; struct nouveau_stateobj *vtxattr; + struct nouveau_stateobj *instbuf; unsigned vtxelt_nr; }; @@ -140,7 +145,6 @@ struct nv50_context { struct pipe_context pipe; struct nv50_screen *screen; - unsigned pctx_id; struct draw_context *draw; @@ -157,6 +161,7 @@ struct nv50_context { struct pipe_framebuffer_state framebuffer; struct nv50_program *vertprog; struct nv50_program *fragprog; + struct nv50_program *geomprog; struct pipe_buffer *constbuf[PIPE_SHADER_TYPES]; struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; unsigned vtxbuf_nr; @@ -193,11 +198,22 @@ extern struct draw_stage *nv50_draw_render_stage(struct nv50_context *nv50); /* nv50_vbo.c */ extern void nv50_draw_arrays(struct pipe_context *, unsigned mode, unsigned start, unsigned count); +extern void nv50_draw_arrays_instanced(struct pipe_context *, unsigned mode, + unsigned start, unsigned count, + unsigned startInstance, + unsigned instanceCount); extern void nv50_draw_elements(struct pipe_context *pipe, struct pipe_buffer *indexBuffer, unsigned indexSize, unsigned mode, unsigned start, unsigned count); +extern void nv50_draw_elements_instanced(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned mode, unsigned start, + unsigned count, + unsigned startInstance, + unsigned instanceCount); extern void nv50_vbo_validate(struct nv50_context *nv50); /* nv50_clear.c */ @@ -207,7 +223,9 @@ extern void nv50_clear(struct pipe_context *pipe, unsigned buffers, /* nv50_program.c */ extern void nv50_vertprog_validate(struct nv50_context *nv50); extern void nv50_fragprog_validate(struct nv50_context *nv50); -extern void nv50_linkage_validate(struct nv50_context *nv50); +extern void nv50_geomprog_validate(struct nv50_context *nv50); +extern void nv50_fp_linkage_validate(struct nv50_context *nv50); +extern void nv50_gp_linkage_validate(struct nv50_context *nv50); extern void nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p); @@ -231,4 +249,8 @@ nv50_upload_sifc(struct nv50_context *nv50, void *src, unsigned src_format, int src_pitch, int x, int y, int w, int h, int cpp); +/* nv50_context.c */ +struct pipe_context * +nv50_create(struct pipe_screen *pscreen, void *priv); + #endif diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c index 3f1edf0a13..7297c74a83 100644 --- a/src/gallium/drivers/nv50/nv50_miptree.c +++ b/src/gallium/drivers/nv50/nv50_miptree.c @@ -22,7 +22,7 @@ #include "pipe/p_state.h" #include "pipe/p_defines.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_format.h" #include "nv50_context.h" @@ -92,12 +92,23 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp) case PIPE_FORMAT_Z24S8_UNORM: tile_flags = 0x1800; break; + case PIPE_FORMAT_Z16_UNORM: + tile_flags = 0x6c00; + break; case PIPE_FORMAT_X8Z24_UNORM: case PIPE_FORMAT_S8Z24_UNORM: tile_flags = 0x2800; break; + case PIPE_FORMAT_R32G32B32A32_FLOAT: + case PIPE_FORMAT_R32G32B32_FLOAT: + tile_flags = 0x7400; + break; default: - tile_flags = 0x7000; + if ((pt->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) && + util_format_get_blocksizebits(pt->format) == 32) + tile_flags = 0x7a00; + else + tile_flags = 0x7000; break; } @@ -145,7 +156,7 @@ nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp) mt->level[0].tile_mode, tile_flags, &mt->base.bo); if (ret) { - for (l = 0; l < pt->last_level; ++l) + for (l = 0; l <= pt->last_level; ++l) FREE(mt->level[l].image_offset); FREE(mt); return NULL; @@ -188,7 +199,7 @@ nv50_miptree_destroy(struct pipe_texture *pt) struct nv50_miptree *mt = nv50_miptree(pt); unsigned l; - for (l = 0; l < pt->last_level; ++l) + for (l = 0; l <= pt->last_level; ++l) FREE(mt->level[l].image_offset); nouveau_bo_ref(NULL, &mt->base.bo); diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c index 593d743603..2372cbbef6 100644 --- a/src/gallium/drivers/nv50/nv50_program.c +++ b/src/gallium/drivers/nv50/nv50_program.c @@ -23,7 +23,7 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_shader_tokens.h" #include "tgsi/tgsi_parse.h" @@ -92,6 +92,11 @@ struct nv50_reg { int rhw; /* result hw for FP outputs, or interpolant index */ int acc; /* instruction where this reg is last read (first insn == 1) */ + + int vtx; /* vertex index, for GP inputs (TGSI Dimension.Index) */ + int indirect[2]; /* index into pc->addr, or -1 */ + + ubyte buf_index; /* c{0 .. 15}[] or g{0 .. 15}[] */ }; #define NV50_MOD_NEG 1 @@ -135,7 +140,8 @@ struct nv50_pc { int immd_nr; struct nv50_reg **addr; int addr_nr; - uint8_t addr_alloc; /* set bit indicates used for TGSI_FILE_ADDRESS */ + struct nv50_reg *sysval; + int sysval_nr; struct nv50_reg *temp_temp[16]; struct nv50_program_exec *temp_temp_exec[16]; @@ -171,6 +177,8 @@ struct nv50_pc { uint8_t edgeflag_out; }; +static struct nv50_reg *get_address_reg(struct nv50_pc *, struct nv50_reg *); + static INLINE void ctor_reg(struct nv50_reg *reg, unsigned type, int index, int hw) { @@ -179,7 +187,10 @@ ctor_reg(struct nv50_reg *reg, unsigned type, int index, int hw) reg->hw = hw; reg->mod = 0; reg->rhw = -1; + reg->vtx = -1; reg->acc = 0; + reg->indirect[0] = reg->indirect[1] = -1; + reg->buf_index = (type == P_CONST) ? 1 : 0; } static INLINE unsigned @@ -197,7 +208,8 @@ terminate_mbb(struct nv50_pc *pc) /* remove records of temporary address register values */ for (i = 0; i < NV50_SU_MAX_ADDR; ++i) - pc->r_addr[i].rhw = -1; + if (pc->r_addr[i].index < 0) + pc->r_addr[i].acc = 0; } static void @@ -260,6 +272,7 @@ reg_instance(struct nv50_pc *pc, struct nv50_reg *reg) if (reg) { alloc_reg(pc, reg); *ri = *reg; + reg->indirect[0] = reg->indirect[1] = -1; reg->mod = 0; } return ri; @@ -464,6 +477,12 @@ is_join(struct nv50_program_exec *e) return FALSE; } +static INLINE boolean +is_control_flow(struct nv50_program_exec *e) +{ + return (e->inst[0] & 2); +} + static INLINE void set_pred(struct nv50_pc *pc, unsigned pred, unsigned idx, struct nv50_program_exec *e) @@ -525,11 +544,33 @@ set_immd(struct nv50_pc *pc, struct nv50_reg *imm, struct nv50_program_exec *e) static INLINE void set_addr(struct nv50_program_exec *e, struct nv50_reg *a) { + assert(a->type == P_ADDR); + assert(!(e->inst[0] & 0x0c000000)); assert(!(e->inst[1] & 0x00000004)); e->inst[0] |= (a->hw & 3) << 26; - e->inst[1] |= (a->hw >> 2) << 2; + e->inst[1] |= a->hw & 4; +} + +static void +emit_arl(struct nv50_pc *, struct nv50_reg *, struct nv50_reg *, uint8_t); + +static void +emit_shl_imm(struct nv50_pc *, struct nv50_reg *, struct nv50_reg *, int); + +static void +emit_mov_from_addr(struct nv50_pc *pc, struct nv50_reg *dst, + struct nv50_reg *src) +{ + struct nv50_program_exec *e = exec(pc); + + e->inst[1] = 0x40000000; + set_long(pc, e); + set_dst(pc, dst, e); + set_addr(e, src); + + emit(pc, e); } static void @@ -548,72 +589,6 @@ emit_add_addr_imm(struct nv50_pc *pc, struct nv50_reg *dst, emit(pc, e); } -static struct nv50_reg * -alloc_addr(struct nv50_pc *pc, struct nv50_reg *ref) -{ - struct nv50_reg *a_tgsi = NULL, *a = NULL; - int i; - uint8_t avail = ~pc->addr_alloc; - - if (!ref) { - /* allocate for TGSI_FILE_ADDRESS */ - while (avail) { - i = ffs(avail) - 1; - - if (pc->r_addr[i].rhw < 0 || - pc->r_addr[i].acc != pc->insn_cur) { - pc->addr_alloc |= (1 << i); - - pc->r_addr[i].rhw = -1; - pc->r_addr[i].index = i; - return &pc->r_addr[i]; - } - avail &= ~(1 << i); - } - assert(0); - return NULL; - } - - /* Allocate and set an address reg so we can access 'ref'. - * - * If and r_addr->index will be -1 or the hw index the value - * value in rhw is relative to. If rhw < 0, the reg has not - * been initialized or is in use for TGSI_FILE_ADDRESS. - */ - while (avail) { /* only consider regs that are not TGSI */ - i = ffs(avail) - 1; - avail &= ~(1 << i); - - if ((!a || a->rhw >= 0) && pc->r_addr[i].rhw < 0) { - /* prefer an usused reg with low hw index */ - a = &pc->r_addr[i]; - continue; - } - if (!a && pc->r_addr[i].acc != pc->insn_cur) - a = &pc->r_addr[i]; - - if (ref->hw - pc->r_addr[i].rhw >= 128) - continue; - - if ((ref->acc >= 0 && pc->r_addr[i].index < 0) || - (ref->acc < 0 && pc->r_addr[i].index == ref->index)) { - pc->r_addr[i].acc = pc->insn_cur; - return &pc->r_addr[i]; - } - } - assert(a); - - if (ref->acc < 0) - a_tgsi = pc->addr[ref->index]; - - emit_add_addr_imm(pc, a, a_tgsi, (ref->hw & ~0x7f) * 4); - - a->rhw = ref->hw & ~0x7f; - a->acc = pc->insn_cur; - a->index = a_tgsi ? ref->index : -1; - return a; -} - #define INTERP_LINEAR 0 #define INTERP_FLAT 1 #define INTERP_PERSPECTIVE 2 @@ -657,15 +632,15 @@ set_data(struct nv50_pc *pc, struct nv50_reg *src, unsigned m, unsigned s, e->param.shift = s; e->param.mask = m << (s % 32); - if (src->hw > 127) - set_addr(e, alloc_addr(pc, src)); + if (src->hw < 0 || src->hw > 127) /* need (additional) address reg */ + set_addr(e, get_address_reg(pc, src)); else if (src->acc < 0) { assert(src->type == P_CONST); - set_addr(e, pc->addr[src->index]); + set_addr(e, pc->addr[src->indirect[0]]); } - e->inst[1] |= (((src->type == P_IMMD) ? 0 : 1) << 22); + e->inst[1] |= (src->buf_index << 22); } /* Never apply nv50_reg::mod in emit_mov, or carefully check the code !!! */ @@ -694,6 +669,12 @@ emit_mov(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src) if (src->type == P_ATTR) { set_long(pc, e); e->inst[1] |= 0x00200000; + + if (src->vtx >= 0) { + /* indirect (vertex base + c) load from p[] */ + e->inst[0] |= 0x01800000; + set_addr(e, get_address_reg(pc, src)); + } } alloc_reg(pc, src); @@ -808,6 +789,11 @@ set_src_0(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e) if (src->type == P_ATTR) { set_long(pc, e); e->inst[1] |= 0x00200000; + + if (src->vtx >= 0) { + e->inst[0] |= 0x01800000; /* src from p[] */ + set_addr(e, get_address_reg(pc, src)); + } } else if (src->type == P_CONST || src->type == P_IMMD) { struct nv50_reg *temp = temp_temp(pc, e); @@ -832,13 +818,13 @@ set_src_1(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e) src = temp; } else if (src->type == P_CONST || src->type == P_IMMD) { - assert(!(e->inst[0] & 0x00800000)); - if (e->inst[0] & 0x01000000) { + if (e->inst[0] & 0x01800000) { struct nv50_reg *temp = temp_temp(pc, e); emit_mov(pc, temp, src); src = temp; } else { + assert(!(e->inst[0] & 0x00800000)); set_data(pc, src, 0x7f, 16, e); e->inst[0] |= 0x00800000; } @@ -862,13 +848,13 @@ set_src_2(struct nv50_pc *pc, struct nv50_reg *src, struct nv50_program_exec *e) src = temp; } else if (src->type == P_CONST || src->type == P_IMMD) { - assert(!(e->inst[0] & 0x01000000)); - if (e->inst[0] & 0x00800000) { + if (e->inst[0] & 0x01800000) { struct nv50_reg *temp = temp_temp(pc, e); emit_mov(pc, temp, src); src = temp; } else { + assert(!(e->inst[0] & 0x01000000)); set_data(pc, src, 0x7f, 32+14, e); e->inst[0] |= 0x01000000; } @@ -997,11 +983,125 @@ emit_arl(struct nv50_pc *pc, struct nv50_reg *dst, struct nv50_reg *src, e->inst[0] |= dst->hw << 2; e->inst[0] |= s << 16; /* shift left */ - set_src_0_restricted(pc, src, e); + set_src_0(pc, src, e); emit(pc, e); } +static boolean +address_reg_suitable(struct nv50_reg *a, struct nv50_reg *r) +{ + if (!r) + return FALSE; + + if (r->vtx != a->vtx) + return FALSE; + if (r->vtx >= 0) + return (r->indirect[1] == a->indirect[1]); + + if (r->hw < a->rhw || (r->hw - a->rhw) >= 128) + return FALSE; + + if (a->index >= 0) + return (a->index == r->indirect[0]); + return (a->indirect[0] == r->indirect[0]); +} + +static void +load_vertex_base(struct nv50_pc *pc, struct nv50_reg *dst, + struct nv50_reg *a, int shift) +{ + struct nv50_reg mem, *temp; + + ctor_reg(&mem, P_ATTR, -1, dst->vtx); + + assert(dst->type == P_ADDR); + if (!a) { + emit_arl(pc, dst, &mem, 0); + return; + } + temp = alloc_temp(pc, NULL); + + if (shift) { + emit_mov_from_addr(pc, temp, a); + if (shift < 0) + emit_shl_imm(pc, temp, temp, shift); + emit_arl(pc, dst, temp, MAX2(shift, 0)); + } + emit_mov(pc, temp, &mem); + set_addr(pc->p->exec_tail, dst); + + emit_arl(pc, dst, temp, 0); + free_temp(pc, temp); +} + +/* case (ref == NULL): allocate address register for TGSI_FILE_ADDRESS + * case (vtx >= 0, acc >= 0): load vertex base from a[vtx * 4] to $aX + * case (vtx >= 0, acc < 0): load vertex base from s[$aY + vtx * 4] to $aX + * case (vtx < 0, acc >= 0): memory address too high to encode + * case (vtx < 0, acc < 0): get source register for TGSI_FILE_ADDRESS + */ +static struct nv50_reg * +get_address_reg(struct nv50_pc *pc, struct nv50_reg *ref) +{ + int i; + struct nv50_reg *a_ref, *a = NULL; + + for (i = 0; i < NV50_SU_MAX_ADDR; ++i) { + if (pc->r_addr[i].acc == 0) + a = &pc->r_addr[i]; /* an unused address reg */ + else + if (address_reg_suitable(&pc->r_addr[i], ref)) { + pc->r_addr[i].acc = pc->insn_cur; + return &pc->r_addr[i]; + } else + if (!a && pc->r_addr[i].index < 0 && + pc->r_addr[i].acc < pc->insn_cur) + a = &pc->r_addr[i]; + } + if (!a) { + /* We'll be able to spill address regs when this + * mess is replaced with a proper compiler ... + */ + NOUVEAU_ERR("out of address regs\n"); + abort(); + return NULL; + } + + /* initialize and reserve for this TGSI instruction */ + a->rhw = 0; + a->index = a->indirect[0] = a->indirect[1] = -1; + a->acc = pc->insn_cur; + + if (!ref) { + a->vtx = -1; + return a; + } + a->vtx = ref->vtx; + + /* now put in the correct value ... */ + + if (ref->vtx >= 0) { + a->indirect[1] = ref->indirect[1]; + + /* For an indirect vertex index, we need to shift address right + * by 2, the address register will contain vtx * 16, we need to + * load from a[vtx * 4]. + */ + load_vertex_base(pc, a, (ref->acc < 0) ? + pc->addr[ref->indirect[1]] : NULL, -2); + } else { + assert(ref->acc < 0 || ref->indirect[0] < 0); + + a->rhw = ref->hw & ~0x7f; + a->indirect[0] = ref->indirect[0]; + a_ref = (ref->acc < 0) ? pc->addr[ref->indirect[0]] : NULL; + + emit_add_addr_imm(pc, a, a_ref, a->rhw * 4); + } + return a; +} + #define NV50_MAX_F32 0x880 #define NV50_MAX_S32 0x08c #define NV50_MAX_U32 0x084 @@ -1629,6 +1729,18 @@ emit_ret(struct nv50_pc *pc, int pred, unsigned cc) emit_control_flow(pc, 0x3, pred, cc); } +static void +emit_prim_cmd(struct nv50_pc *pc, unsigned cmd) +{ + struct nv50_program_exec *e = exec(pc); + + e->inst[0] = 0xf0000000 | (cmd << 9); + e->inst[1] = 0xc0000000; + set_long(pc, e); + + emit(pc, e); +} + #define QOP_ADD 0 #define QOP_SUBR 1 #define QOP_SUB 2 @@ -2171,14 +2283,19 @@ tgsi_dst(struct nv50_pc *pc, int c, const struct tgsi_full_dst_register *dst) { struct nv50_reg *r = pc->addr[dst->Register.Index * 4 + c]; if (!r) { - r = alloc_addr(pc, NULL); - pc->addr[dst->Register.Index * 4 + c] = r; + r = get_address_reg(pc, NULL); + r->index = dst->Register.Index * 4 + c; + pc->addr[r->index] = r; } assert(r); return r; } case TGSI_FILE_NULL: return NULL; + case TGSI_FILE_SYSTEM_VALUE: + assert(pc->sysval[dst->Register.Index].type == P_RESULT); + assert(c == 0); + return &pc->sysval[dst->Register.Index]; default: break; } @@ -2208,6 +2325,18 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src, switch (src->Register.File) { case TGSI_FILE_INPUT: r = &pc->attr[src->Register.Index * 4 + c]; + + if (!src->Dimension.Dimension) + break; + r = reg_instance(pc, r); + r->vtx = src->Dimension.Index; + + if (!src->Dimension.Indirect) + break; + swz = tgsi_util_get_src_register_swizzle( + &src->DimIndirect, 0); + r->acc = -1; + r->indirect[1] = src->DimIndirect.Index * 4 + swz; break; case TGSI_FILE_TEMPORARY: r = &pc->temp[src->Register.Index * 4 + c]; @@ -2221,12 +2350,12 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src, * use the index field to select the address reg. */ r = reg_instance(pc, NULL); + ctor_reg(r, P_CONST, -1, src->Register.Index * 4 + c); + swz = tgsi_util_get_src_register_swizzle( - &src->Indirect, 0); - ctor_reg(r, P_CONST, - src->Indirect.Index * 4 + swz, - src->Register.Index * 4 + c); + &src->Indirect, 0); r->acc = -1; + r->indirect[0] = src->Indirect.Index * 4 + swz; break; case TGSI_FILE_IMMEDIATE: r = &pc->immd[src->Register.Index * 4 + c]; @@ -2237,6 +2366,10 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src, r = pc->addr[src->Register.Index * 4 + c]; assert(r); break; + case TGSI_FILE_SYSTEM_VALUE: + assert(c == 0); + r = &pc->sysval[src->Register.Index]; + break; default: assert(0); break; @@ -2273,7 +2406,7 @@ tgsi_src(struct nv50_pc *pc, int chan, const struct tgsi_full_src_register *src, r->mod |= mod & NV50_MOD_I32; assert(r); - if (r->acc >= 0 && r != temp) + if (r->acc >= 0 && r->vtx < 0 && r != temp) return reg_instance(pc, r); /* will clear r->mod */ return r; } @@ -2495,10 +2628,14 @@ nv50_program_tx_insn(struct nv50_pc *pc, } break; case TGSI_OPCODE_ARL: - assert(src[0][0]); temp = temp_temp(pc, NULL); - emit_cvt(pc, temp, src[0][0], -1, CVT_FLOOR | CVT_S32_F32); - emit_arl(pc, dst[0], temp, 4); + for (c = 0; c < 4; c++) { + if (!(mask & (1 << c))) + continue; + emit_cvt(pc, temp, src[0][c], -1, + CVT_FLOOR | CVT_S32_F32); + emit_arl(pc, dst[c], temp, 4); + } break; case TGSI_OPCODE_BGNLOOP: pc->loop_brka[pc->loop_lvl] = emit_breakaddr(pc); @@ -2605,6 +2742,9 @@ nv50_program_tx_insn(struct nv50_pc *pc, pc->if_insn[pc->if_lvl++] = pc->p->exec_tail; terminate_mbb(pc); break; + case TGSI_OPCODE_EMIT: + emit_prim_cmd(pc, 1); + break; case TGSI_OPCODE_ENDIF: pc->if_insn[--pc->if_lvl]->param.index = pc->p->exec_size; @@ -2628,8 +2768,12 @@ nv50_program_tx_insn(struct nv50_pc *pc, pc->loop_brka[pc->loop_lvl]->param.index = pc->p->exec_size; terminate_mbb(pc); break; + case TGSI_OPCODE_ENDPRIM: + emit_prim_cmd(pc, 2); + break; case TGSI_OPCODE_ENDSUB: assert(pc->in_subroutine); + terminate_mbb(pc); pc->in_subroutine = FALSE; break; case TGSI_OPCODE_EX2: @@ -3028,10 +3172,14 @@ nv50_program_tx_insn(struct nv50_pc *pc, if (!is_long(pc->p->exec_tail)) convert_to_long(pc, pc->p->exec_tail); else - if (is_immd(pc->p->exec_tail) || is_join(pc->p->exec_tail)) + if (is_immd(pc->p->exec_tail) || + is_join(pc->p->exec_tail) || + is_control_flow(pc->p->exec_tail)) emit_nop(pc); pc->p->exec_tail->inst[1] |= 1; /* set exit bit */ + + terminate_mbb(pc); break; default: NOUVEAU_ERR("invalid opcode %d\n", inst->Instruction.Opcode); @@ -3135,7 +3283,7 @@ prep_inspect_insn(struct nv50_pc *pc, const struct tgsi_full_instruction *insn) static unsigned nv50_revdep_reorder(unsigned m[4], unsigned rdep[4]) { - unsigned i, c, x, unsafe; + unsigned i, c, x, unsafe = 0; for (c = 0; c < 4; c++) m[c] = c; @@ -3327,17 +3475,53 @@ load_interpolant(struct nv50_pc *pc, struct nv50_reg *reg) * value of 0 for back-facing, and 0xffffffff for front-facing. */ static void -load_frontfacing(struct nv50_pc *pc, struct nv50_reg *a) +load_frontfacing(struct nv50_pc *pc, struct nv50_reg *sv) { - struct nv50_reg *one = alloc_immd(pc, 1.0f); + struct nv50_reg *temp = alloc_temp(pc, NULL); + int r_pred = 0; - assert(a->rhw == -1); - alloc_reg(pc, a); /* do this before rhw is set */ - a->rhw = 255; - load_interpolant(pc, a); - emit_bitop2(pc, a, a, one, TGSI_OPCODE_AND); + temp->rhw = 255; + emit_interp(pc, temp, NULL, INTERP_FLAT); - FREE(one); + emit_cvt(pc, sv, temp, r_pred, CVT_ABS | CVT_F32_S32); + + emit_not(pc, temp, temp); + set_pred(pc, 0x2, r_pred, pc->p->exec_tail); + emit_cvt(pc, sv, temp, -1, CVT_F32_S32); + set_pred(pc, 0x2, r_pred, pc->p->exec_tail); + + free_temp(pc, temp); +} + +static void +load_instance_id(struct nv50_pc *pc, unsigned index) +{ + struct nv50_reg reg, mem; + + ctor_reg(®, P_TEMP, -1, -1); + ctor_reg(&mem, P_CONST, -1, 24); /* startInstance */ + mem.buf_index = 2; + + emit_add_b32(pc, ®, &pc->sysval[index], &mem); + pc->sysval[index] = reg; +} + +static void +copy_semantic_info(struct nv50_program *p) +{ + unsigned i, id; + + for (i = 0; i < p->cfg.in_nr; ++i) { + id = p->cfg.in[i].id; + p->cfg.in[i].sn = p->info.input_semantic_name[id]; + p->cfg.in[i].si = p->info.input_semantic_index[id]; + } + + for (i = 0; i < p->cfg.out_nr; ++i) { + id = p->cfg.out[i].id; + p->cfg.out[i].sn = p->info.output_semantic_name[id]; + p->cfg.out[i].si = p->info.output_semantic_index[id]; + } } static boolean @@ -3346,7 +3530,7 @@ nv50_program_tx_prep(struct nv50_pc *pc) struct tgsi_parse_context tp; struct nv50_program *p = pc->p; boolean ret = FALSE; - unsigned i, c, flat_nr = 0; + unsigned i, c, instance_id, vertex_id, flat_nr = 0; tgsi_parse_init(&tp, pc->p->pipe.tokens); while (!tgsi_parse_end_of_tokens(&tp)) { @@ -3386,13 +3570,13 @@ nv50_program_tx_prep(struct nv50_pc *pc) switch (d->Semantic.Name) { case TGSI_SEMANTIC_BCOLOR: p->cfg.two_side[si].hw = first; - if (p->cfg.io_nr > first) - p->cfg.io_nr = first; + if (p->cfg.out_nr > first) + p->cfg.out_nr = first; break; case TGSI_SEMANTIC_PSIZE: p->cfg.psiz = first; - if (p->cfg.io_nr > first) - p->cfg.io_nr = first; + if (p->cfg.out_nr > first) + p->cfg.out_nr = first; break; case TGSI_SEMANTIC_EDGEFLAG: pc->edgeflag_out = first; @@ -3432,6 +3616,37 @@ nv50_program_tx_prep(struct nv50_pc *pc) pc->interp_mode[i] = mode; } break; + case TGSI_FILE_SYSTEM_VALUE: + assert(d->Declaration.Semantic); + switch (d->Semantic.Name) { + case TGSI_SEMANTIC_FACE: + assert(p->type == PIPE_SHADER_FRAGMENT); + load_frontfacing(pc, + &pc->sysval[first]); + break; + case TGSI_SEMANTIC_INSTANCEID: + assert(p->type == PIPE_SHADER_VERTEX); + instance_id = first; + p->cfg.regs[0] |= (1 << 4); + break; + case TGSI_SEMANTIC_PRIMID: + assert(p->type != PIPE_SHADER_VERTEX); + p->cfg.prim_id = first; + break; + /* + case TGSI_SEMANTIC_PRIMIDIN: + assert(p->type == PIPE_SHADER_GEOMETRY); + pc->sysval[first].hw = 6; + p->cfg.regs[0] |= (1 << 8); + break; + case TGSI_SEMANTIC_VERTEXID: + assert(p->type == PIPE_SHADER_VERTEX); + vertex_id = first; + p->cfg.regs[0] |= (1 << 12) | (1 << 0); + break; + */ + } + break; case TGSI_FILE_ADDRESS: case TGSI_FILE_CONSTANT: case TGSI_FILE_SAMPLER: @@ -3452,36 +3667,65 @@ nv50_program_tx_prep(struct nv50_pc *pc) } } - if (p->type == PIPE_SHADER_VERTEX) { + if (p->type == PIPE_SHADER_VERTEX || p->type == PIPE_SHADER_GEOMETRY) { int rid = 0; - for (i = 0; i < pc->attr_nr * 4; ++i) { - if (pc->attr[i].acc) { - pc->attr[i].hw = rid++; - p->cfg.attr[i / 32] |= 1 << (i % 32); + if (p->type == PIPE_SHADER_GEOMETRY) { + for (i = 0; i < pc->attr_nr; ++i) { + p->cfg.in[i].hw = rid; + p->cfg.in[i].id = i; + + for (c = 0; c < 4; ++c) { + int n = i * 4 + c; + if (!pc->attr[n].acc) + continue; + pc->attr[n].hw = rid++; + p->cfg.in[i].mask |= 1 << c; + } + } + } else { + for (i = 0; i < pc->attr_nr * 4; ++i) { + if (pc->attr[i].acc) { + pc->attr[i].hw = rid++; + p->cfg.attr[i / 32] |= 1 << (i % 32); + } + } + if (p->cfg.regs[0] & (1 << 0)) + pc->sysval[vertex_id].hw = rid++; + if (p->cfg.regs[0] & (1 << 4)) { + pc->sysval[instance_id].hw = rid++; + load_instance_id(pc, instance_id); } } for (i = 0, rid = 0; i < pc->result_nr; ++i) { - p->cfg.io[i].hw = rid; - p->cfg.io[i].id = i; + p->cfg.out[i].hw = rid; + p->cfg.out[i].id = i; for (c = 0; c < 4; ++c) { int n = i * 4 + c; if (!pc->result[n].acc) continue; pc->result[n].hw = rid++; - p->cfg.io[i].mask |= 1 << c; + p->cfg.out[i].mask |= 1 << c; } } + if (p->cfg.prim_id < 0x40) { + /* GP has to write to PrimitiveID */ + ctor_reg(&pc->sysval[p->cfg.prim_id], + P_RESULT, p->cfg.prim_id, rid); + p->cfg.prim_id = rid++; + } for (c = 0; c < 2; ++c) if (p->cfg.two_side[c].hw < 0x40) - p->cfg.two_side[c] = p->cfg.io[ + p->cfg.two_side[c] = p->cfg.out[ p->cfg.two_side[c].hw]; if (p->cfg.psiz < 0x40) - p->cfg.psiz = p->cfg.io[p->cfg.psiz].hw; + p->cfg.psiz = p->cfg.out[p->cfg.psiz].hw; + + copy_semantic_info(p); } else if (p->type == PIPE_SHADER_FRAGMENT) { int rid, aid; @@ -3489,31 +3733,34 @@ nv50_program_tx_prep(struct nv50_pc *pc) pc->allow32 = TRUE; - int base = (TGSI_SEMANTIC_POSITION == - p->info.input_semantic_name[0]) ? 0 : 1; + /* do we read FragCoord ? */ + if (pc->attr_nr && + p->info.input_semantic_name[0] == TGSI_SEMANTIC_POSITION) { + /* select FCRD components we want accessible */ + for (c = 0; c < 4; ++c) + if (pc->attr[c].acc) + p->cfg.regs[1] |= 1 << (24 + c); + aid = 0; + } else /* offset by 1 if FCRD.w is needed for pinterp */ + aid = popcnt4(p->cfg.regs[1] >> 24); /* non-flat interpolants have to be mapped to * the lower hardware IDs, so sort them: */ for (i = 0; i < pc->attr_nr; i++) { if (pc->interp_mode[i] == INTERP_FLAT) - p->cfg.io[m++].id = i; + p->cfg.in[m++].id = i; else { if (!(pc->interp_mode[i] & INTERP_PERSPECTIVE)) - p->cfg.io[n].linear = TRUE; - p->cfg.io[n++].id = i; + p->cfg.in[n].linear = TRUE; + p->cfg.in[n++].id = i; } } - - if (!base) /* set w-coordinate mask from perspective interp */ - p->cfg.io[0].mask |= p->cfg.regs[1] >> 24; - - aid = popcnt4( /* if fcrd isn't contained in cfg.io */ - base ? (p->cfg.regs[1] >> 24) : p->cfg.io[0].mask); + copy_semantic_info(p); for (n = 0; n < pc->attr_nr; ++n) { - p->cfg.io[n].hw = rid = aid; - i = p->cfg.io[n].id; + p->cfg.in[n].hw = rid = aid; + i = p->cfg.in[n].id; if (p->info.input_semantic_name[n] == TGSI_SEMANTIC_FACE) { @@ -3525,16 +3772,13 @@ nv50_program_tx_prep(struct nv50_pc *pc) if (!pc->attr[i * 4 + c].acc) continue; pc->attr[i * 4 + c].rhw = rid++; - p->cfg.io[n].mask |= 1 << c; + p->cfg.in[n].mask |= 1 << c; load_interpolant(pc, &pc->attr[i * 4 + c]); } - aid += popcnt4(p->cfg.io[n].mask); + aid += popcnt4(p->cfg.in[n].mask); } - if (!base) - p->cfg.regs[1] |= p->cfg.io[0].mask << 24; - m = popcnt4(p->cfg.regs[1] >> 24); /* set count of non-position inputs and of non-flat @@ -3543,32 +3787,33 @@ nv50_program_tx_prep(struct nv50_pc *pc) p->cfg.regs[1] |= aid - m; if (flat_nr) { - i = p->cfg.io[pc->attr_nr - flat_nr].hw; + i = p->cfg.in[pc->attr_nr - flat_nr].hw; p->cfg.regs[1] |= (i - m) << 16; } else p->cfg.regs[1] |= p->cfg.regs[1] << 16; /* mark color semantic for light-twoside */ - n = 0x40; - for (i = 0; i < pc->attr_nr; i++) { - ubyte si, sn; - - sn = p->info.input_semantic_name[p->cfg.io[i].id]; - si = p->info.input_semantic_index[p->cfg.io[i].id]; - - if (sn == TGSI_SEMANTIC_COLOR) { - p->cfg.two_side[si] = p->cfg.io[i]; - - /* increase colour count */ - p->cfg.regs[0] += popcnt4( - p->cfg.two_side[si].mask) << 16; - - n = MIN2(n, p->cfg.io[i].hw - m); + n = 0x80; + for (i = 0; i < p->cfg.in_nr; i++) { + if (p->cfg.in[i].sn == TGSI_SEMANTIC_COLOR) { + n = MIN2(n, p->cfg.in[i].hw - m); + p->cfg.two_side[p->cfg.in[i].si] = p->cfg.in[i]; + + p->cfg.regs[0] += /* increase colour count */ + popcnt4(p->cfg.in[i].mask) << 16; } } - if (n < 0x40) + if (n < 0x80) p->cfg.regs[0] += n; + if (p->cfg.prim_id < 0x40) { + pc->sysval[p->cfg.prim_id].rhw = rid++; + emit_interp(pc, &pc->sysval[p->cfg.prim_id], NULL, + INTERP_FLAT); + /* increase FP_INTERPOLANT_CTRL_COUNT */ + p->cfg.regs[1] += 1; + } + /* Initialize FP results: * FragDepth is always first TGSI and last hw output */ @@ -3622,10 +3867,31 @@ free_nv50_pc(struct nv50_pc *pc) FREE(pc->attr); if (pc->temp) FREE(pc->temp); + if (pc->sysval) + FREE(pc->sysval); + if (pc->insn_pos) + FREE(pc->insn_pos); FREE(pc); } +static INLINE uint32_t +nv50_map_gs_output_prim(unsigned pprim) +{ + switch (pprim) { + case PIPE_PRIM_POINTS: + return NV50TCL_GP_OUTPUT_PRIMITIVE_TYPE_POINTS; + case PIPE_PRIM_LINE_STRIP: + return NV50TCL_GP_OUTPUT_PRIMITIVE_TYPE_LINE_STRIP; + case PIPE_PRIM_TRIANGLE_STRIP: + return NV50TCL_GP_OUTPUT_PRIMITIVE_TYPE_TRIANGLE_STRIP; + default: + NOUVEAU_ERR("invalid GS_OUTPUT_PRIMITIVE: %u\n", pprim); + abort(); + return 0; + } +} + static boolean ctor_nv50_pc(struct nv50_pc *pc, struct nv50_program *p) { @@ -3639,25 +3905,55 @@ ctor_nv50_pc(struct nv50_pc *pc, struct nv50_program *p) pc->param_nr = p->info.file_max[TGSI_FILE_CONSTANT] + 1; pc->addr_nr = p->info.file_max[TGSI_FILE_ADDRESS] + 1; assert(pc->addr_nr <= 2); + pc->sysval_nr = p->info.file_max[TGSI_FILE_SYSTEM_VALUE] + 1; p->cfg.high_temp = 4; p->cfg.two_side[0].hw = 0x40; p->cfg.two_side[1].hw = 0x40; + p->cfg.prim_id = 0x40; p->cfg.edgeflag_in = pc->edgeflag_out = 0xff; + for (i = 0; i < p->info.num_properties; ++i) { + unsigned *data = &p->info.properties[i].data[0]; + + switch (p->info.properties[i].name) { + case TGSI_PROPERTY_GS_OUTPUT_PRIM: + p->cfg.prim_type = nv50_map_gs_output_prim(data[0]); + break; + case TGSI_PROPERTY_GS_MAX_VERTICES: + p->cfg.vert_count = data[0]; + break; + default: + break; + } + } + switch (p->type) { case PIPE_SHADER_VERTEX: p->cfg.psiz = 0x40; p->cfg.clpd = 0x40; - p->cfg.io_nr = pc->result_nr; + p->cfg.out_nr = pc->result_nr; + break; + case PIPE_SHADER_GEOMETRY: + assert(p->cfg.prim_type); + assert(p->cfg.vert_count); + + p->cfg.psiz = 0x80; + p->cfg.clpd = 0x80; + p->cfg.prim_id = 0x80; + p->cfg.out_nr = pc->result_nr; + p->cfg.in_nr = pc->attr_nr; + + p->cfg.two_side[0].hw = 0x80; + p->cfg.two_side[1].hw = 0x80; break; case PIPE_SHADER_FRAGMENT: rtype[0] = rtype[1] = P_TEMP; p->cfg.regs[0] = 0x01000004; - p->cfg.io_nr = pc->attr_nr; + p->cfg.in_nr = pc->attr_nr; if (p->info.writes_z) { p->cfg.regs[2] |= 0x00000100; @@ -3715,7 +4011,16 @@ ctor_nv50_pc(struct nv50_pc *pc, struct nv50_program *p) return FALSE; } for (i = 0; i < NV50_SU_MAX_ADDR; ++i) - ctor_reg(&pc->r_addr[i], P_ADDR, -256, i + 1); + ctor_reg(&pc->r_addr[i], P_ADDR, -1, i + 1); + + if (pc->sysval_nr) { + pc->sysval = CALLOC(pc->sysval_nr, sizeof(struct nv50_reg *)); + if (!pc->sysval) + return FALSE; + /* will only ever use SYSTEM_VALUE[i].x (hopefully) */ + for (i = 0; i < pc->sysval_nr; ++i) + ctor_reg(&pc->sysval[i], rtype[0], i, -1); + } return TRUE; } @@ -3877,13 +4182,17 @@ nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p) if (p->param_nr) { unsigned cb; - uint32_t *map = pipe_buffer_map(pscreen, nv50->constbuf[p->type], + uint32_t *map = pipe_buffer_map(pscreen, + nv50->constbuf[p->type], PIPE_BUFFER_USAGE_CPU_READ); - - if (p->type == PIPE_SHADER_VERTEX) + switch (p->type) { + case PIPE_SHADER_GEOMETRY: cb = NV50_CB_PGP; break; + case PIPE_SHADER_FRAGMENT: cb = NV50_CB_PFP; break; + default: cb = NV50_CB_PVP; - else - cb = NV50_CB_PFP; + assert(p->type == PIPE_SHADER_VERTEX); + break; + } nv50_program_upload_data(nv50, map, 0, p->param_nr, cb); pipe_buffer_unmap(pscreen, nv50->constbuf[p->type]); @@ -3977,19 +4286,18 @@ nv50_vertprog_validate(struct nv50_context *nv50) nv50_program_validate_data(nv50, p); nv50_program_validate_code(nv50, p); - so = so_new(5, 8, 2); + so = so_new(5, 7, 2); so_method(so, tesla, NV50TCL_VP_ADDRESS_HIGH, 2); so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | - NOUVEAU_BO_HIGH, 0, 0); + NOUVEAU_BO_HIGH, 0, 0); so_reloc (so, p->bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | - NOUVEAU_BO_LOW, 0, 0); + NOUVEAU_BO_LOW, 0, 0); so_method(so, tesla, NV50TCL_VP_ATTR_EN_0, 2); so_data (so, p->cfg.attr[0]); so_data (so, p->cfg.attr[1]); so_method(so, tesla, NV50TCL_VP_REG_ALLOC_RESULT, 1); so_data (so, p->cfg.high_result); - so_method(so, tesla, NV50TCL_VP_RESULT_MAP_SIZE, 2); - so_data (so, p->cfg.high_result); //8); + so_method(so, tesla, NV50TCL_VP_REG_ALLOC_TEMP, 1); so_data (so, p->cfg.high_temp); so_method(so, tesla, NV50TCL_VP_START_ID, 1); so_data (so, 0); /* program start offset */ @@ -4033,42 +4341,74 @@ nv50_fragprog_validate(struct nv50_context *nv50) so_ref(NULL, &so); } +void +nv50_geomprog_validate(struct nv50_context *nv50) +{ + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nv50_program *p = nv50->geomprog; + struct nouveau_stateobj *so; + + if (!p->translated) { + nv50_program_validate(nv50, p); + if (!p->translated) + assert(0); + } + + nv50_program_validate_data(nv50, p); + nv50_program_validate_code(nv50, p); + + so = so_new(6, 7, 2); + so_method(so, tesla, NV50TCL_GP_ADDRESS_HIGH, 2); + 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, NV50TCL_GP_REG_ALLOC_TEMP, 1); + so_data (so, p->cfg.high_temp); + so_method(so, tesla, NV50TCL_GP_REG_ALLOC_RESULT, 1); + so_data (so, p->cfg.high_result); + so_method(so, tesla, NV50TCL_GP_OUTPUT_PRIMITIVE_TYPE, 1); + so_data (so, p->cfg.prim_type); + so_method(so, tesla, NV50TCL_GP_VERTEX_OUTPUT_COUNT, 1); + so_data (so, p->cfg.vert_count); + so_method(so, tesla, NV50TCL_GP_START_ID, 1); + so_data (so, 0); + so_ref(so, &nv50->state.geomprog); + so_ref(NULL, &so); +} + static uint32_t nv50_pntc_replace(struct nv50_context *nv50, uint32_t pntc[8], unsigned base) { + struct nv50_program *vp; struct nv50_program *fp = nv50->fragprog; - struct nv50_program *vp = nv50->vertprog; unsigned i, c, m = base; uint32_t origin = 0x00000010; + vp = nv50->geomprog ? nv50->geomprog : nv50->vertprog; + /* XXX: this might not work correctly in all cases yet - we'll * just assume that an FP generic input that is not written in * the VP is PointCoord. */ memset(pntc, 0, 8 * sizeof(uint32_t)); - for (i = 0; i < fp->cfg.io_nr; i++) { - uint8_t sn, si; - uint8_t j, k = fp->cfg.io[i].id; - unsigned n = popcnt4(fp->cfg.io[i].mask); + for (i = 0; i < fp->cfg.in_nr; i++) { + unsigned j, n = popcnt4(fp->cfg.in[i].mask); - if (fp->info.input_semantic_name[k] != TGSI_SEMANTIC_GENERIC) { + if (fp->cfg.in[i].sn != TGSI_SEMANTIC_GENERIC) { m += n; continue; } - for (j = 0; j < vp->info.num_outputs; ++j) { - sn = vp->info.output_semantic_name[j]; - si = vp->info.output_semantic_index[j]; - - if (sn == fp->info.input_semantic_name[k] && - si == fp->info.input_semantic_index[k]) + for (j = 0; j < vp->cfg.out_nr; ++j) + if (vp->cfg.out[j].sn == fp->cfg.in[i].sn && + vp->cfg.out[j].si == fp->cfg.in[i].si) break; - } if (j < vp->info.num_outputs) { ubyte enable = - (nv50->rasterizer->pipe.sprite_coord_enable >> si) & 1; + (nv50->rasterizer->pipe.sprite_coord_enable >> vp->cfg.out[j].si) & 1; if (enable == 0) { m += n; @@ -4078,7 +4418,7 @@ nv50_pntc_replace(struct nv50_context *nv50, uint32_t pntc[8], unsigned base) /* this is either PointCoord or replaced by sprite coords */ for (c = 0; c < 4; c++) { - if (!(fp->cfg.io[i].mask & (1 << c))) + if (!(fp->cfg.in[i].mask & (1 << c))) continue; pntc[m / 8] |= (c + 1) << ((m % 8) * 4); ++m; @@ -4088,18 +4428,22 @@ nv50_pntc_replace(struct nv50_context *nv50, uint32_t pntc[8], unsigned base) } static int -nv50_sreg4_map(uint32_t *p_map, int mid, uint32_t lin[4], - struct nv50_sreg4 *fpi, struct nv50_sreg4 *vpo) +nv50_vec4_map(uint32_t *map32, int mid, uint8_t zval, uint32_t lin[4], + struct nv50_sreg4 *fpi, struct nv50_sreg4 *vpo) { int c; uint8_t mv = vpo->mask, mf = fpi->mask, oid = vpo->hw; - uint8_t *map = (uint8_t *)p_map; + uint8_t *map = (uint8_t *)map32; for (c = 0; c < 4; ++c) { if (mf & 1) { if (fpi->linear == TRUE) lin[mid / 32] |= 1 << (mid % 32); - map[mid++] = (mv & 1) ? oid : ((c == 3) ? 0x41 : 0x40); + if (mv & 1) + map[mid] = oid; + else + map[mid] = (c == 3) ? (zval + 1) : zval; + ++mid; } oid += mv & 1; @@ -4111,34 +4455,42 @@ nv50_sreg4_map(uint32_t *p_map, int mid, uint32_t lin[4], } void -nv50_linkage_validate(struct nv50_context *nv50) +nv50_fp_linkage_validate(struct nv50_context *nv50) { struct nouveau_grobj *tesla = nv50->screen->tesla; struct nv50_program *vp = nv50->vertprog; struct nv50_program *fp = nv50->fragprog; struct nouveau_stateobj *so; - struct nv50_sreg4 dummy, *vpo; + struct nv50_sreg4 dummy; int i, n, c, m = 0; - uint32_t map[16], lin[4], reg[5], pcrd[8]; + uint32_t map[16], lin[4], reg[6], pcrd[8]; + uint8_t zval = 0x40; + if (nv50->geomprog) { + vp = nv50->geomprog; + zval = 0x80; + } memset(map, 0, sizeof(map)); memset(lin, 0, sizeof(lin)); reg[1] = 0x00000004; /* low and high clip distance map ids */ reg[2] = 0x00000000; /* layer index map id (disabled, GP only) */ reg[3] = 0x00000000; /* point size map id & enable */ + reg[5] = 0x00000000; /* primitive ID map slot */ reg[0] = fp->cfg.regs[0]; /* colour semantic reg */ reg[4] = fp->cfg.regs[1]; /* interpolant info */ dummy.linear = FALSE; dummy.mask = 0xf; /* map all components of HPOS */ - m = nv50_sreg4_map(map, m, lin, &dummy, &vp->cfg.io[0]); + m = nv50_vec4_map(map, m, zval, lin, &dummy, &vp->cfg.out[0]); dummy.mask = 0x0; if (vp->cfg.clpd < 0x40) { - for (c = 0; c < vp->cfg.clpd_nr; ++c) - map[m++] = vp->cfg.clpd + c; + for (c = 0; c < vp->cfg.clpd_nr; ++c) { + map[m / 4] |= (vp->cfg.clpd + c) << ((m % 4) * 8); + ++m; + } reg[1] = (m << 8); } @@ -4146,35 +4498,37 @@ nv50_linkage_validate(struct nv50_context *nv50) /* if light_twoside is active, it seems FFC0_ID == BFC0_ID is bad */ if (nv50->rasterizer->pipe.light_twoside) { - vpo = &vp->cfg.two_side[0]; + struct nv50_sreg4 *vpo = &vp->cfg.two_side[0]; + struct nv50_sreg4 *fpi = &fp->cfg.two_side[0]; - m = nv50_sreg4_map(map, m, lin, &fp->cfg.two_side[0], &vpo[0]); - m = nv50_sreg4_map(map, m, lin, &fp->cfg.two_side[1], &vpo[1]); + m = nv50_vec4_map(map, m, zval, lin, &fpi[0], &vpo[0]); + m = nv50_vec4_map(map, m, zval, lin, &fpi[1], &vpo[1]); } reg[0] += m - 4; /* adjust FFC0 id */ reg[4] |= m << 8; /* set mid where 'normal' FP inputs start */ - for (i = 0; i < fp->cfg.io_nr; i++) { - ubyte sn = fp->info.input_semantic_name[fp->cfg.io[i].id]; - ubyte si = fp->info.input_semantic_index[fp->cfg.io[i].id]; - - /* position must be mapped first */ - assert(i == 0 || sn != TGSI_SEMANTIC_POSITION); - + for (i = 0; i < fp->cfg.in_nr; i++) { /* maybe even remove these from cfg.io */ - if (sn == TGSI_SEMANTIC_POSITION || sn == TGSI_SEMANTIC_FACE) + if (fp->cfg.in[i].sn == TGSI_SEMANTIC_POSITION || + fp->cfg.in[i].sn == TGSI_SEMANTIC_FACE) continue; - /* VP outputs and vp->cfg.io are in the same order */ - for (n = 0; n < vp->info.num_outputs; ++n) { - if (vp->info.output_semantic_name[n] == sn && - vp->info.output_semantic_index[n] == si) + for (n = 0; n < vp->cfg.out_nr; ++n) + if (vp->cfg.out[n].sn == fp->cfg.in[i].sn && + vp->cfg.out[n].si == fp->cfg.in[i].si) break; - } - vpo = (n < vp->info.num_outputs) ? &vp->cfg.io[n] : &dummy; - m = nv50_sreg4_map(map, m, lin, &fp->cfg.io[i], vpo); + m = nv50_vec4_map(map, m, zval, lin, &fp->cfg.in[i], + (n < vp->cfg.out_nr) ? + &vp->cfg.out[n] : &dummy); + } + /* PrimitiveID either is replaced by the system value, or + * written by the geometry shader into an output register + */ + if (fp->cfg.prim_id < 0x40) { + map[m / 4] |= vp->cfg.prim_id << ((m % 4) * 8); + reg[5] = m++; } if (nv50->rasterizer->pipe.point_size_per_vertex) { @@ -4182,14 +4536,28 @@ nv50_linkage_validate(struct nv50_context *nv50) reg[3] = (m++ << 4) | 1; } - /* now fill the stateobj */ - so = so_new(7, 57, 0); + /* now fill the stateobj (at most 28 so_data) */ + so = so_new(10, 54, 0); n = (m + 3) / 4; - so_method(so, tesla, NV50TCL_VP_RESULT_MAP_SIZE, 1); - so_data (so, m); - so_method(so, tesla, NV50TCL_VP_RESULT_MAP(0), n); - so_datap (so, map, n); + assert(m <= 32); + if (vp->type == PIPE_SHADER_GEOMETRY) { + so_method(so, tesla, NV50TCL_GP_RESULT_MAP_SIZE, 1); + so_data (so, m); + so_method(so, tesla, NV50TCL_GP_RESULT_MAP(0), n); + so_datap (so, map, n); + } else { + so_method(so, tesla, NV50TCL_VP_GP_BUILTIN_ATTR_EN, 1); + so_data (so, vp->cfg.regs[0]); + + so_method(so, tesla, NV50TCL_MAP_SEMANTIC_4, 1); + so_data (so, reg[5]); + + so_method(so, tesla, NV50TCL_VP_RESULT_MAP_SIZE, 1); + so_data (so, m); + so_method(so, tesla, NV50TCL_VP_RESULT_MAP(0), n); + so_datap (so, map, n); + } so_method(so, tesla, NV50TCL_MAP_SEMANTIC_0, 4); so_datap (so, reg, 4); @@ -4209,8 +4577,77 @@ nv50_linkage_validate(struct nv50_context *nv50) so_datap (so, pcrd, 8); } - so_ref(so, &nv50->state.programs); - so_ref(NULL, &so); + so_method(so, tesla, NV50TCL_GP_ENABLE, 1); + so_data (so, (vp->type == PIPE_SHADER_GEOMETRY) ? 1 : 0); + + so_ref(so, &nv50->state.fp_linkage); + so_ref(NULL, &so); +} + +static int +construct_vp_gp_mapping(uint32_t *map32, int m, + struct nv50_program *vp, struct nv50_program *gp) +{ + uint8_t *map = (uint8_t *)map32; + int i, j, c; + + for (i = 0; i < gp->cfg.in_nr; ++i) { + uint8_t oid, mv = 0, mg = gp->cfg.in[i].mask; + + for (j = 0; j < vp->cfg.out_nr; ++j) { + if (vp->cfg.out[j].sn == gp->cfg.in[i].sn && + vp->cfg.out[j].si == gp->cfg.in[i].si) { + mv = vp->cfg.out[j].mask; + oid = vp->cfg.out[j].hw; + break; + } + } + + for (c = 0; c < 4; ++c, mv >>= 1, mg >>= 1) { + if (mg & mv & 1) + map[m++] = oid; + else + if (mg & 1) + map[m++] = (c == 3) ? 0x41 : 0x40; + oid += mv & 1; + } + } + return m; +} + +void +nv50_gp_linkage_validate(struct nv50_context *nv50) +{ + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_stateobj *so; + struct nv50_program *vp = nv50->vertprog; + struct nv50_program *gp = nv50->geomprog; + uint32_t map[16]; + int m = 0; + + if (!gp) { + so_ref(NULL, &nv50->state.gp_linkage); + return; + } + memset(map, 0, sizeof(map)); + + m = construct_vp_gp_mapping(map, m, vp, gp); + + so = so_new(3, 24 - 3, 0); + + so_method(so, tesla, NV50TCL_VP_GP_BUILTIN_ATTR_EN, 1); + so_data (so, vp->cfg.regs[0] | gp->cfg.regs[0]); + + assert(m <= 32); + so_method(so, tesla, NV50TCL_VP_RESULT_MAP_SIZE, 1); + so_data (so, m); + + m = (m + 3) / 4; + so_method(so, tesla, NV50TCL_VP_RESULT_MAP(0), m); + so_datap (so, map, m); + + so_ref(so, &nv50->state.gp_linkage); + so_ref(NULL, &so); } void @@ -4227,6 +4664,7 @@ nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p) nouveau_bo_ref(NULL, &p->bo); + FREE(p->immd); nouveau_resource_free(&p->data[0]); p->translated = 0; diff --git a/src/gallium/drivers/nv50/nv50_program.h b/src/gallium/drivers/nv50/nv50_program.h index 461fec1d89..1e3ad6bff0 100644 --- a/src/gallium/drivers/nv50/nv50_program.h +++ b/src/gallium/drivers/nv50/nv50_program.h @@ -16,11 +16,13 @@ struct nv50_program_exec { }; struct nv50_sreg4 { - uint8_t hw; - uint8_t id; /* tgsi index, nv50 needs them sorted: flat ones last */ + uint8_t hw; /* hw index, nv50 wants flat FP inputs last */ + uint8_t id; /* tgsi index */ uint8_t mask; boolean linear; + + ubyte sn, si; /* semantic name & index */ }; struct nv50_program { @@ -49,16 +51,24 @@ struct nv50_program { uint32_t regs[4]; /* for VPs, io_nr doesn't count 'private' results (PSIZ etc.) */ - unsigned io_nr; - struct nv50_sreg4 io[PIPE_MAX_SHADER_OUTPUTS]; + unsigned in_nr, out_nr; + struct nv50_sreg4 in[PIPE_MAX_SHADER_INPUTS]; + struct nv50_sreg4 out[PIPE_MAX_SHADER_OUTPUTS]; /* FP colour inputs, VP/GP back colour outputs */ struct nv50_sreg4 two_side[2]; - /* VP only */ + /* GP only */ + unsigned vert_count; + uint8_t prim_type; + + /* VP & GP only */ uint8_t clpd, clpd_nr; uint8_t psiz; uint8_t edgeflag_in; + + /* FP & GP only */ + uint8_t prim_id; } cfg; }; diff --git a/src/gallium/drivers/nv50/nv50_query.c b/src/gallium/drivers/nv50/nv50_query.c index 5a4ab3508b..57b16a355d 100644 --- a/src/gallium/drivers/nv50/nv50_query.c +++ b/src/gallium/drivers/nv50/nv50_query.c @@ -21,7 +21,7 @@ */ #include "pipe/p_context.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "nv50_context.h" @@ -48,7 +48,7 @@ nv50_query_create(struct pipe_context *pipe, unsigned type) assert (q->type == PIPE_QUERY_OCCLUSION_COUNTER); q->type = type; - ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, 256, + ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 256, 16, &q->bo); if (ret) { FREE(q); @@ -95,11 +95,13 @@ nv50_query_end(struct pipe_context *pipe, struct pipe_query *pq) MARK_RING (chan, 5, 2); /* flush on lack of space or relocs */ BEGIN_RING(chan, tesla, NV50TCL_QUERY_ADDRESS_HIGH, 4); - 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_RELOCh(chan, q->bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR); + OUT_RELOCl(chan, q->bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR); OUT_RING (chan, 0x00000000); OUT_RING (chan, 0x0100f002); - FIRE_RING (chan); + + BEGIN_RING(chan, tesla, NV50TCL_SAMPLECNT_ENABLE, 1); + OUT_RING (chan, 0); } static boolean @@ -123,6 +125,35 @@ nv50_query_result(struct pipe_context *pipe, struct pipe_query *pq, return q->ready; } +static void +nv50_render_condition(struct pipe_context *pipe, + struct pipe_query *pq, uint mode) +{ + struct nv50_context *nv50 = nv50_context(pipe); + struct nouveau_channel *chan = nv50->screen->base.channel; + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nv50_query *q; + + if (!pq) { + BEGIN_RING(chan, tesla, NV50TCL_COND_MODE, 1); + OUT_RING (chan, NV50TCL_COND_MODE_ALWAYS); + return; + } + q = nv50_query(pq); + + if (mode == PIPE_RENDER_COND_WAIT || + mode == PIPE_RENDER_COND_BY_REGION_WAIT) { + /* XXX: big fence, FIFO semaphore might be better */ + BEGIN_RING(chan, tesla, 0x0110, 1); + OUT_RING (chan, 0); + } + + BEGIN_RING(chan, tesla, NV50TCL_COND_ADDRESS_HIGH, 3); + OUT_RELOCh(chan, q->bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_RD); + OUT_RELOCl(chan, q->bo, 0, NOUVEAU_BO_GART | NOUVEAU_BO_RD); + OUT_RING (chan, NV50TCL_COND_MODE_RES); +} + void nv50_init_query_functions(struct nv50_context *nv50) { @@ -131,4 +162,5 @@ nv50_init_query_functions(struct nv50_context *nv50) nv50->pipe.begin_query = nv50_query_begin; nv50->pipe.end_query = nv50_query_end; nv50->pipe.get_query_result = nv50_query_result; + nv50->pipe.render_condition = nv50_render_condition; } diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index 28e2b35dea..8c4478e483 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -135,6 +135,16 @@ nv50_screen_get_param(struct pipe_screen *pscreen, int param) return 1; case NOUVEAU_CAP_HW_IDXBUF: return 0; + case PIPE_CAP_INDEP_BLEND_ENABLE: + return 1; + case PIPE_CAP_INDEP_BLEND_FUNC: + return 0; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 0; default: NOUVEAU_ERR("Unknown PIPE_CAP %d\n", param); return 0; @@ -167,7 +177,7 @@ nv50_screen_destroy(struct pipe_screen *pscreen) struct nv50_screen *screen = nv50_screen(pscreen); unsigned i; - for (i = 0; i < 2; i++) { + for (i = 0; i < 3; i++) { if (screen->constbuf_parm[i]) nouveau_bo_ref(NULL, &screen->constbuf_parm[i]); } @@ -185,6 +195,9 @@ nv50_screen_destroy(struct pipe_screen *pscreen) nouveau_grobj_free(&screen->tesla); nouveau_grobj_free(&screen->eng2d); nouveau_grobj_free(&screen->m2mf); + nouveau_resource_destroy(&screen->immd_heap[0]); + nouveau_resource_destroy(&screen->parm_heap[0]); + nouveau_resource_destroy(&screen->parm_heap[1]); nouveau_screen_fini(&screen->base); FREE(screen); } @@ -238,6 +251,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) pscreen->get_param = nv50_screen_get_param; pscreen->get_paramf = nv50_screen_get_paramf; pscreen->is_format_supported = nv50_screen_is_format_supported; + pscreen->context_create = nv50_create; screen->base.pre_pipebuffer_map_callback = nv50_pre_pipebuffer_map; nv50_screen_init_miptree_functions(pscreen); @@ -329,7 +343,7 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) so_ref(NULL, &so); /* Static tesla init */ - so = so_new(40, 84, 20); + so = so_new(47, 95, 24); so_method(so, screen->tesla, NV50TCL_COND_MODE, 1); so_data (so, NV50TCL_COND_MODE_ALWAYS); @@ -352,10 +366,11 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) so_data (so, 0xf); /* max TIC (bits 4:8) & TSC (ignored) bindings, per program type */ - so_method(so, screen->tesla, NV50TCL_TEX_LIMITS(0), 1); - so_data (so, 0x54); - so_method(so, screen->tesla, NV50TCL_TEX_LIMITS(2), 1); - so_data (so, 0x54); + for (i = 0; i < 3; ++i) { + so_method(so, screen->tesla, NV50TCL_TEX_LIMITS(i), 1); + so_data (so, 0x54); + } + /* origin is top left (set to 1 for bottom left) */ so_method(so, screen->tesla, NV50TCL_Y_ORIGIN_BOTTOM, 1); so_data (so, 0); @@ -370,8 +385,8 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) return NULL; } - for (i = 0; i < 2; i++) { - ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (128 * 4) * 4, + for (i = 0; i < 3; i++) { + ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 0, (256 * 4) * 4, &screen->constbuf_parm[i]); if (ret) { nv50_screen_destroy(pscreen); @@ -406,22 +421,45 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); so_data (so, 0x00000001 | (NV50_CB_PMISC << 12)); so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); + so_data (so, 0x00000021 | (NV50_CB_PMISC << 12)); + so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); so_data (so, 0x00000031 | (NV50_CB_PMISC << 12)); + /* bind auxiliary constbuf to immediate data bo */ so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); - so_reloc (so, screen->constbuf_parm[0], 0, NOUVEAU_BO_VRAM | - NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); - so_reloc (so, screen->constbuf_parm[0], 0, NOUVEAU_BO_VRAM | - NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); + so_reloc (so, screen->constbuf_misc[0], (128 * 4) * 4, + NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); + so_reloc (so, screen->constbuf_misc[0], (128 * 4) * 4, + NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); + so_data (so, (NV50_CB_AUX << 16) | 0x00000200); + so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); + so_data (so, 0x00000201 | (NV50_CB_AUX << 12)); + so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); + so_data (so, 0x00000221 | (NV50_CB_AUX << 12)); + + so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); + so_reloc (so, screen->constbuf_parm[PIPE_SHADER_VERTEX], 0, + NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); + so_reloc (so, screen->constbuf_parm[PIPE_SHADER_VERTEX], 0, + NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); so_data (so, (NV50_CB_PVP << 16) | 0x00000800); so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); so_data (so, 0x00000101 | (NV50_CB_PVP << 12)); so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 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_reloc (so, screen->constbuf_parm[PIPE_SHADER_GEOMETRY], 0, + NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); + so_reloc (so, screen->constbuf_parm[PIPE_SHADER_GEOMETRY], 0, + NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_LOW, 0, 0); + so_data (so, (NV50_CB_PGP << 16) | 0x00000800); + so_method(so, screen->tesla, NV50TCL_SET_PROGRAM_CB, 1); + so_data (so, 0x00000121 | (NV50_CB_PGP << 12)); + + so_method(so, screen->tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3); + so_reloc (so, screen->constbuf_parm[PIPE_SHADER_FRAGMENT], 0, + NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); + so_reloc (so, screen->constbuf_parm[PIPE_SHADER_FRAGMENT], 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, NV50TCL_SET_PROGRAM_CB, 1); so_data (so, 0x00000131 | (NV50_CB_PFP << 12)); diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index a038a4e3c2..2687b72127 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -9,7 +9,6 @@ struct nv50_screen { struct nouveau_winsys *nvws; - unsigned cur_pctx; struct nv50_context *cur_ctx; struct nouveau_grobj *tesla; @@ -18,10 +17,12 @@ struct nv50_screen { struct nouveau_notifier *sync; struct nouveau_bo *constbuf_misc[1]; - struct nouveau_bo *constbuf_parm[2]; + struct nouveau_bo *constbuf_parm[PIPE_SHADER_TYPES]; struct nouveau_resource *immd_heap[1]; - struct nouveau_resource *parm_heap[2]; + struct nouveau_resource *parm_heap[PIPE_SHADER_TYPES]; + + struct pipe_buffer *strm_vbuf[16]; struct nouveau_bo *tic; struct nouveau_bo *tsc; diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c index f19a21d5cc..7c531b50a5 100644 --- a/src/gallium/drivers/nv50/nv50_state.c +++ b/src/gallium/drivers/nv50/nv50_state.c @@ -22,7 +22,7 @@ #include "pipe/p_state.h" #include "pipe/p_defines.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "tgsi/tgsi_parse.h" @@ -31,6 +31,23 @@ #include "nouveau/nouveau_stateobj.h" +static INLINE uint32_t +nv50_colormask(unsigned mask) +{ + uint32_t cmask = 0; + + if (mask & PIPE_MASK_R) + cmask |= 0x0001; + if (mask & PIPE_MASK_G) + cmask |= 0x0010; + if (mask & PIPE_MASK_B) + cmask |= 0x0100; + if (mask & PIPE_MASK_A) + cmask |= 0x1000; + + return cmask; +} + static void * nv50_blend_state_create(struct pipe_context *pipe, const struct pipe_blend_state *cso) @@ -38,28 +55,37 @@ nv50_blend_state_create(struct pipe_context *pipe, struct nouveau_stateobj *so = so_new(5, 24, 0); struct nouveau_grobj *tesla = nv50_context(pipe)->screen->tesla; struct nv50_blend_stateobj *bso = CALLOC_STRUCT(nv50_blend_stateobj); - unsigned cmask = 0, i; + unsigned i, blend_enabled = 0; /*XXX ignored: * - dither */ - if (cso->blend_enable == 0) { - so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8); + so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8); + if (cso->independent_blend_enable) { + for (i = 0; i < 8; ++i) { + so_data(so, cso->rt[i].blend_enable); + if (cso->rt[i].blend_enable) + blend_enabled = 1; + } + } else + if (cso->rt[0].blend_enable) { + blend_enabled = 1; for (i = 0; i < 8; i++) - so_data(so, 0); + so_data(so, 1); } else { - so_method(so, tesla, NV50TCL_BLEND_ENABLE(0), 8); for (i = 0; i < 8; i++) - so_data(so, 1); + so_data(so, 0); + } + if (blend_enabled) { so_method(so, tesla, NV50TCL_BLEND_EQUATION_RGB, 5); - so_data (so, nvgl_blend_eqn(cso->rgb_func)); - so_data (so, 0x4000 | nvgl_blend_func(cso->rgb_src_factor)); - so_data (so, 0x4000 | nvgl_blend_func(cso->rgb_dst_factor)); - so_data (so, nvgl_blend_eqn(cso->alpha_func)); - so_data (so, 0x4000 | nvgl_blend_func(cso->alpha_src_factor)); + so_data (so, nvgl_blend_eqn(cso->rt[0].rgb_func)); + so_data (so, 0x4000 | nvgl_blend_func(cso->rt[0].rgb_src_factor)); + so_data (so, 0x4000 | nvgl_blend_func(cso->rt[0].rgb_dst_factor)); + so_data (so, nvgl_blend_eqn(cso->rt[0].alpha_func)); + so_data (so, 0x4000 | nvgl_blend_func(cso->rt[0].alpha_src_factor)); so_method(so, tesla, NV50TCL_BLEND_FUNC_DST_ALPHA, 1); - so_data (so, 0x4000 | nvgl_blend_func(cso->alpha_dst_factor)); + so_data (so, 0x4000 | nvgl_blend_func(cso->rt[0].alpha_dst_factor)); } if (cso->logicop_enable == 0 ) { @@ -71,17 +97,15 @@ nv50_blend_state_create(struct pipe_context *pipe, so_data (so, nvgl_logicop_func(cso->logicop_func)); } - if (cso->colormask & PIPE_MASK_R) - cmask |= (1 << 0); - if (cso->colormask & PIPE_MASK_G) - cmask |= (1 << 4); - if (cso->colormask & PIPE_MASK_B) - cmask |= (1 << 8); - if (cso->colormask & PIPE_MASK_A) - cmask |= (1 << 12); so_method(so, tesla, NV50TCL_COLOR_MASK(0), 8); - for (i = 0; i < 8; i++) - so_data(so, cmask); + if (cso->independent_blend_enable) + for (i = 0; i < 8; ++i) + so_data(so, nv50_colormask(cso->rt[i].colormask)); + else { + uint32_t cmask = nv50_colormask(cso->rt[0].colormask); + for (i = 0; i < 8; i++) + so_data(so, cmask); + } bso->pipe = *cso; so_ref(so, &bso->so); @@ -531,7 +555,7 @@ nv50_vp_state_delete(struct pipe_context *pipe, void *hwcso) struct nv50_program *p = hwcso; nv50_program_destroy(nv50, p); - FREE((void*)p->pipe.tokens); + FREE((void *)p->pipe.tokens); FREE(p); } @@ -563,7 +587,39 @@ nv50_fp_state_delete(struct pipe_context *pipe, void *hwcso) struct nv50_program *p = hwcso; nv50_program_destroy(nv50, p); - FREE((void*)p->pipe.tokens); + FREE((void *)p->pipe.tokens); + FREE(p); +} + +static void * +nv50_gp_state_create(struct pipe_context *pipe, + const struct pipe_shader_state *cso) +{ + struct nv50_program *p = CALLOC_STRUCT(nv50_program); + + p->pipe.tokens = tgsi_dup_tokens(cso->tokens); + p->type = PIPE_SHADER_GEOMETRY; + tgsi_scan_shader(p->pipe.tokens, &p->info); + return (void *)p; +} + +static void +nv50_gp_state_bind(struct pipe_context *pipe, void *hwcso) +{ + struct nv50_context *nv50 = nv50_context(pipe); + + nv50->fragprog = hwcso; + nv50->dirty |= NV50_NEW_GEOMPROG; +} + +static void +nv50_gp_state_delete(struct pipe_context *pipe, void *hwcso) +{ + struct nv50_context *nv50 = nv50_context(pipe); + struct nv50_program *p = hwcso; + + nv50_program_destroy(nv50, p); + FREE((void *)p->pipe.tokens); FREE(p); } @@ -585,17 +641,21 @@ nv50_set_clip_state(struct pipe_context *pipe, static void nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - const struct pipe_constant_buffer *buf ) + struct pipe_buffer *buf ) { struct nv50_context *nv50 = nv50_context(pipe); if (shader == PIPE_SHADER_VERTEX) { - nv50->constbuf[PIPE_SHADER_VERTEX] = buf->buffer; + nv50->constbuf[PIPE_SHADER_VERTEX] = buf; nv50->dirty |= NV50_NEW_VERTPROG_CB; } else if (shader == PIPE_SHADER_FRAGMENT) { - nv50->constbuf[PIPE_SHADER_FRAGMENT] = buf->buffer; + nv50->constbuf[PIPE_SHADER_FRAGMENT] = buf; nv50->dirty |= NV50_NEW_FRAGPROG_CB; + } else + if (shader == PIPE_SHADER_GEOMETRY) { + nv50->constbuf[PIPE_SHADER_GEOMETRY] = buf; + nv50->dirty |= NV50_NEW_GEOMPROG_CB; } } @@ -696,6 +756,10 @@ nv50_init_state_functions(struct nv50_context *nv50) nv50->pipe.bind_fs_state = nv50_fp_state_bind; nv50->pipe.delete_fs_state = nv50_fp_state_delete; + nv50->pipe.create_gs_state = nv50_gp_state_create; + nv50->pipe.bind_gs_state = nv50_gp_state_bind; + nv50->pipe.delete_gs_state = nv50_gp_state_delete; + nv50->pipe.set_blend_color = nv50_set_blend_color; nv50->pipe.set_clip_state = nv50_set_clip_state; nv50->pipe.set_constant_buffer = nv50_set_constant_buffer; diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c index f83232f43c..ee28fa63c1 100644 --- a/src/gallium/drivers/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -185,10 +185,10 @@ nv50_state_emit(struct nv50_context *nv50) struct nv50_screen *screen = nv50->screen; struct nouveau_channel *chan = screen->base.channel; - /* I don't want to copy headers from the winsys. */ - screen->cur_ctx = nv50; - - if (nv50->pctx_id != screen->cur_pctx) { + /* XXX: this is racy for multiple contexts active on separate + * threads. + */ + if (screen->cur_ctx != nv50) { if (nv50->state.fb) nv50->state.dirty |= NV50_NEW_FRAMEBUFFER; if (nv50->state.blend) @@ -199,6 +199,8 @@ nv50_state_emit(struct nv50_context *nv50) nv50->state.dirty |= NV50_NEW_VERTPROG; if (nv50->state.fragprog) nv50->state.dirty |= NV50_NEW_FRAGPROG; + if (nv50->state.geomprog) + nv50->state.dirty |= NV50_NEW_GEOMPROG; if (nv50->state.rast) nv50->state.dirty |= NV50_NEW_RASTERIZER; if (nv50->state.blend_colour) @@ -215,7 +217,7 @@ nv50_state_emit(struct nv50_context *nv50) nv50->state.dirty |= NV50_NEW_TEXTURE; if (nv50->state.vtxfmt && nv50->state.vtxbuf) nv50->state.dirty |= NV50_NEW_ARRAYS; - screen->cur_pctx = nv50->pctx_id; + screen->cur_ctx = nv50; } if (nv50->state.dirty & NV50_NEW_FRAMEBUFFER) @@ -228,9 +230,14 @@ nv50_state_emit(struct nv50_context *nv50) so_emit(chan, nv50->state.vertprog); if (nv50->state.dirty & NV50_NEW_FRAGPROG) so_emit(chan, nv50->state.fragprog); + if (nv50->state.dirty & NV50_NEW_GEOMPROG && nv50->state.geomprog) + so_emit(chan, nv50->state.geomprog); if (nv50->state.dirty & (NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG | - NV50_NEW_RASTERIZER)) - so_emit(chan, nv50->state.programs); + NV50_NEW_GEOMPROG | NV50_NEW_RASTERIZER)) + so_emit(chan, nv50->state.fp_linkage); + if ((nv50->state.dirty & (NV50_NEW_VERTPROG | NV50_NEW_GEOMPROG)) + && nv50->state.gp_linkage) + so_emit(chan, nv50->state.gp_linkage); if (nv50->state.dirty & NV50_NEW_RASTERIZER) so_emit(chan, nv50->state.rast); if (nv50->state.dirty & NV50_NEW_BLEND_COLOUR) @@ -267,6 +274,9 @@ nv50_state_flush_notify(struct nouveau_channel *chan) 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); + + if (nv50->state.instbuf) + so_emit_reloc_markers(chan, nv50->state.instbuf); } boolean @@ -291,9 +301,15 @@ nv50_state_validate(struct nv50_context *nv50) if (nv50->dirty & (NV50_NEW_FRAGPROG | NV50_NEW_FRAGPROG_CB)) nv50_fragprog_validate(nv50); + if (nv50->dirty & (NV50_NEW_GEOMPROG | NV50_NEW_GEOMPROG_CB)) + nv50_geomprog_validate(nv50); + if (nv50->dirty & (NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG | - NV50_NEW_RASTERIZER)) - nv50_linkage_validate(nv50); + NV50_NEW_GEOMPROG | NV50_NEW_RASTERIZER)) + nv50_fp_linkage_validate(nv50); + + if (nv50->dirty & (NV50_NEW_GEOMPROG | NV50_NEW_VERTPROG)) + nv50_gp_linkage_validate(nv50); if (nv50->dirty & NV50_NEW_RASTERIZER) so_ref(nv50->rasterizer->so, &nv50->state.rast); @@ -400,8 +416,9 @@ viewport_uptodate: for (i = 0; i < PIPE_SHADER_TYPES; ++i) nr += nv50->sampler_nr[i]; - so = so_new(1+ 5 * PIPE_SHADER_TYPES, 1+ 19 * PIPE_SHADER_TYPES - + nr * 8, PIPE_SHADER_TYPES * 2); + so = so_new(1 + 5 * PIPE_SHADER_TYPES, + 1 + 19 * PIPE_SHADER_TYPES + nr * 8, + PIPE_SHADER_TYPES * 2); nv50_validate_samplers(nv50, so, PIPE_SHADER_VERTEX); nv50_validate_samplers(nv50, so, PIPE_SHADER_FRAGMENT); diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c index 6378132979..ac0c1d0270 100644 --- a/src/gallium/drivers/nv50/nv50_surface.c +++ b/src/gallium/drivers/nv50/nv50_surface.c @@ -25,8 +25,8 @@ #include "nouveau/nouveau_pushbuf.h" #include "nv50_context.h" #include "pipe/p_defines.h" -#include "pipe/internal/p_winsys_screen.h" -#include "pipe/p_inlines.h" +#include "util/u_simple_screen.h" +#include "util/u_inlines.h" #include "util/u_tile.h" diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c index bef548b728..9f1a171303 100644 --- a/src/gallium/drivers/nv50/nv50_tex.c +++ b/src/gallium/drivers/nv50/nv50_tex.c @@ -155,7 +155,7 @@ static boolean nv50_validate_textures(struct nv50_context *nv50, struct nouveau_stateobj *so, unsigned p) { - static const unsigned p_remap[PIPE_SHADER_TYPES] = { 0, 2 }; + static const unsigned p_remap[PIPE_SHADER_TYPES] = { 0, 2, 1 }; struct nouveau_grobj *eng2d = nv50->screen->eng2d; struct nouveau_grobj *tesla = nv50->screen->tesla; @@ -220,11 +220,8 @@ nv50_tex_validate(struct nv50_context *nv50) return; } - /* not sure if the following really do what I think: */ so_method(so, tesla, 0x1330, 1); /* flush TIC */ so_data (so, 0); - so_method(so, tesla, 0x1338, 1); /* flush texture caches */ - so_data (so, 0x20); so_ref(so, &nv50->state.tic_upload); so_ref(NULL, &so); diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c index a2f1db2914..d08b4d7354 100644 --- a/src/gallium/drivers/nv50/nv50_transfer.c +++ b/src/gallium/drivers/nv50/nv50_transfer.c @@ -1,6 +1,6 @@ #include "pipe/p_context.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_format.h" #include "util/u_math.h" diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c index f2e510fba6..ca2f8061f3 100644 --- a/src/gallium/drivers/nv50/nv50_vbo.c +++ b/src/gallium/drivers/nv50/nv50_vbo.c @@ -22,7 +22,7 @@ #include "pipe/p_context.h" #include "pipe/p_state.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_format.h" @@ -40,6 +40,8 @@ nv50_push_elements_u32(struct nv50_context *, uint32_t *, unsigned); static boolean nv50_push_arrays(struct nv50_context *, unsigned, unsigned); +#define NV50_USING_LOATHED_EDGEFLAG(ctx) ((ctx)->vertprog->cfg.edgeflag_in < 16) + static INLINE unsigned nv50_prim(unsigned mode) { @@ -55,6 +57,14 @@ nv50_prim(unsigned mode) case PIPE_PRIM_QUADS: return NV50TCL_VERTEX_BEGIN_QUADS; case PIPE_PRIM_QUAD_STRIP: return NV50TCL_VERTEX_BEGIN_QUAD_STRIP; case PIPE_PRIM_POLYGON: return NV50TCL_VERTEX_BEGIN_POLYGON; + case PIPE_PRIM_LINES_ADJACENCY: + return NV50TCL_VERTEX_BEGIN_LINES_ADJACENCY; + case PIPE_PRIM_LINE_STRIP_ADJACENCY: + return NV50TCL_VERTEX_BEGIN_LINE_STRIP_ADJACENCY; + case PIPE_PRIM_TRIANGLES_ADJACENCY: + return NV50TCL_VERTEX_BEGIN_TRIANGLES_ADJACENCY; + case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: + return NV50TCL_VERTEX_BEGIN_TRIANGLE_STRIP_ADJACENCY; default: break; } @@ -152,6 +162,309 @@ nv50_vbo_vtxelt_to_hw(struct pipe_vertex_element *ve) return (hw_type | hw_size); } +/* For instanced drawing from user buffers, hitting the FIFO repeatedly + * with the same vertex data is probably worse than uploading all data. + */ +static boolean +nv50_upload_vtxbuf(struct nv50_context *nv50, unsigned i) +{ + struct nv50_screen *nscreen = nv50->screen; + struct pipe_screen *pscreen = &nscreen->base.base; + struct pipe_buffer *buf = nscreen->strm_vbuf[i]; + struct pipe_vertex_buffer *vb = &nv50->vtxbuf[i]; + uint8_t *src; + unsigned size = align(vb->buffer->size, 4096); + + if (buf && buf->size < size) + pipe_buffer_reference(&nscreen->strm_vbuf[i], NULL); + + if (!nscreen->strm_vbuf[i]) { + nscreen->strm_vbuf[i] = pipe_buffer_create( + pscreen, 0, PIPE_BUFFER_USAGE_VERTEX, size); + buf = nscreen->strm_vbuf[i]; + } + + src = pipe_buffer_map(pscreen, vb->buffer, PIPE_BUFFER_USAGE_CPU_READ); + if (!src) + return FALSE; + src += vb->buffer_offset; + + size = (vb->max_index + 1) * vb->stride + 16; /* + 16 is for stride 0 */ + if (vb->buffer_offset + size > vb->buffer->size) + size = vb->buffer->size - vb->buffer_offset; + + pipe_buffer_write(pscreen, buf, vb->buffer_offset, size, src); + pipe_buffer_unmap(pscreen, vb->buffer); + + vb->buffer = buf; /* don't pipe_reference, this is a private copy */ + return TRUE; +} + +static void +nv50_upload_user_vbufs(struct nv50_context *nv50) +{ + unsigned i; + + if (nv50->vbo_fifo) + nv50->dirty |= NV50_NEW_ARRAYS; + if (!(nv50->dirty & NV50_NEW_ARRAYS)) + return; + + for (i = 0; i < nv50->vtxbuf_nr; ++i) { + if (nv50->vtxbuf[i].buffer->usage & PIPE_BUFFER_USAGE_VERTEX) + continue; + nv50_upload_vtxbuf(nv50, i); + } +} + +static void +nv50_set_static_vtxattr(struct nv50_context *nv50, unsigned i, void *data) +{ + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + float v[4]; + + util_format_read_4f(nv50->vtxelt[i].src_format, + v, 0, data, 0, 0, 0, 1, 1); + + switch (nv50->vtxelt[i].nr_components) { + case 4: + BEGIN_RING(chan, tesla, NV50TCL_VTX_ATTR_4F_X(i), 4); + OUT_RINGf (chan, v[0]); + OUT_RINGf (chan, v[1]); + OUT_RINGf (chan, v[2]); + OUT_RINGf (chan, v[3]); + break; + case 3: + BEGIN_RING(chan, tesla, NV50TCL_VTX_ATTR_3F_X(i), 3); + OUT_RINGf (chan, v[0]); + OUT_RINGf (chan, v[1]); + OUT_RINGf (chan, v[2]); + break; + case 2: + BEGIN_RING(chan, tesla, NV50TCL_VTX_ATTR_2F_X(i), 2); + OUT_RINGf (chan, v[0]); + OUT_RINGf (chan, v[1]); + break; + case 1: + BEGIN_RING(chan, tesla, NV50TCL_VTX_ATTR_1F(i), 1); + OUT_RINGf (chan, v[0]); + break; + default: + assert(0); + break; + } +} + +static unsigned +init_per_instance_arrays_immd(struct nv50_context *nv50, + unsigned startInstance, + unsigned pos[16], unsigned step[16]) +{ + struct nouveau_bo *bo; + unsigned i, b, count = 0; + + for (i = 0; i < nv50->vtxelt_nr; ++i) { + if (!nv50->vtxelt[i].instance_divisor) + continue; + ++count; + b = nv50->vtxelt[i].vertex_buffer_index; + + pos[i] = nv50->vtxelt[i].src_offset + + nv50->vtxbuf[b].buffer_offset + + startInstance * nv50->vtxbuf[b].stride; + step[i] = startInstance % nv50->vtxelt[i].instance_divisor; + + bo = nouveau_bo(nv50->vtxbuf[b].buffer); + if (!bo->map) + nouveau_bo_map(bo, NOUVEAU_BO_RD); + + nv50_set_static_vtxattr(nv50, i, (uint8_t *)bo->map + pos[i]); + } + + return count; +} + +static unsigned +init_per_instance_arrays(struct nv50_context *nv50, + unsigned startInstance, + unsigned pos[16], unsigned step[16]) +{ + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + struct nouveau_bo *bo; + struct nouveau_stateobj *so; + unsigned i, b, count = 0; + const uint32_t rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; + + if (nv50->vbo_fifo) + return init_per_instance_arrays_immd(nv50, startInstance, + pos, step); + + so = so_new(nv50->vtxelt_nr, nv50->vtxelt_nr * 2, nv50->vtxelt_nr * 2); + + for (i = 0; i < nv50->vtxelt_nr; ++i) { + if (!nv50->vtxelt[i].instance_divisor) + continue; + ++count; + b = nv50->vtxelt[i].vertex_buffer_index; + + pos[i] = nv50->vtxelt[i].src_offset + + nv50->vtxbuf[b].buffer_offset + + startInstance * nv50->vtxbuf[b].stride; + + if (!startInstance) { + step[i] = 0; + continue; + } + step[i] = startInstance % nv50->vtxelt[i].instance_divisor; + + bo = nouveau_bo(nv50->vtxbuf[b].buffer); + + so_method(so, tesla, NV50TCL_VERTEX_ARRAY_START_HIGH(i), 2); + so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_HIGH, 0, 0); + so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_LOW, 0, 0); + } + + if (count && startInstance) { + so_ref (so, &nv50->state.instbuf); /* for flush notify */ + so_emit(chan, nv50->state.instbuf); + } + so_ref (NULL, &so); + + return count; +} + +static void +step_per_instance_arrays_immd(struct nv50_context *nv50, + unsigned pos[16], unsigned step[16]) +{ + struct nouveau_bo *bo; + unsigned i, b; + + for (i = 0; i < nv50->vtxelt_nr; ++i) { + if (!nv50->vtxelt[i].instance_divisor) + continue; + if (++step[i] != nv50->vtxelt[i].instance_divisor) + continue; + b = nv50->vtxelt[i].vertex_buffer_index; + bo = nouveau_bo(nv50->vtxbuf[b].buffer); + + step[i] = 0; + pos[i] += nv50->vtxbuf[b].stride; + + nv50_set_static_vtxattr(nv50, i, (uint8_t *)bo->map + pos[i]); + } +} + +static void +step_per_instance_arrays(struct nv50_context *nv50, + unsigned pos[16], unsigned step[16]) +{ + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + struct nouveau_bo *bo; + struct nouveau_stateobj *so; + unsigned i, b; + const uint32_t rl = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; + + if (nv50->vbo_fifo) { + step_per_instance_arrays_immd(nv50, pos, step); + return; + } + + so = so_new(nv50->vtxelt_nr, nv50->vtxelt_nr * 2, nv50->vtxelt_nr * 2); + + for (i = 0; i < nv50->vtxelt_nr; ++i) { + if (!nv50->vtxelt[i].instance_divisor) + continue; + b = nv50->vtxelt[i].vertex_buffer_index; + + if (++step[i] == nv50->vtxelt[i].instance_divisor) { + step[i] = 0; + pos[i] += nv50->vtxbuf[b].stride; + } + + bo = nouveau_bo(nv50->vtxbuf[b].buffer); + + so_method(so, tesla, NV50TCL_VERTEX_ARRAY_START_HIGH(i), 2); + so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_HIGH, 0, 0); + so_reloc (so, bo, pos[i], rl | NOUVEAU_BO_LOW, 0, 0); + } + + so_ref (so, &nv50->state.instbuf); /* for flush notify */ + so_ref (NULL, &so); + + so_emit(chan, nv50->state.instbuf); +} + +static INLINE void +nv50_unmap_vbufs(struct nv50_context *nv50) +{ + unsigned i; + + for (i = 0; i < nv50->vtxbuf_nr; ++i) + if (nouveau_bo(nv50->vtxbuf[i].buffer)->map) + nouveau_bo_unmap(nouveau_bo(nv50->vtxbuf[i].buffer)); +} + +void +nv50_draw_arrays_instanced(struct pipe_context *pipe, + unsigned mode, unsigned start, unsigned count, + unsigned startInstance, unsigned instanceCount) +{ + struct nv50_context *nv50 = nv50_context(pipe); + struct nouveau_channel *chan = nv50->screen->tesla->channel; + struct nouveau_grobj *tesla = nv50->screen->tesla; + unsigned i, nz_divisors; + unsigned step[16], pos[16]; + + if (!NV50_USING_LOATHED_EDGEFLAG(nv50)) + nv50_upload_user_vbufs(nv50); + + nv50_state_validate(nv50); + + nz_divisors = init_per_instance_arrays(nv50, startInstance, pos, step); + + BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 2); + OUT_RING (chan, NV50_CB_AUX | (24 << 8)); + OUT_RING (chan, startInstance); + + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); + OUT_RING (chan, nv50_prim(mode)); + + if (nv50->vbo_fifo) + nv50_push_arrays(nv50, start, count); + else { + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BUFFER_FIRST, 2); + OUT_RING (chan, start); + OUT_RING (chan, count); + } + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); + OUT_RING (chan, 0); + + for (i = 1; i < instanceCount; i++) { + if (nz_divisors) /* any non-zero array divisors ? */ + step_per_instance_arrays(nv50, pos, step); + + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); + OUT_RING (chan, nv50_prim(mode) | (1 << 28)); + + if (nv50->vbo_fifo) + nv50_push_arrays(nv50, start, count); + else { + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BUFFER_FIRST, 2); + OUT_RING (chan, start); + OUT_RING (chan, count); + } + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); + OUT_RING (chan, 0); + } + nv50_unmap_vbufs(nv50); + + so_ref(NULL, &nv50->state.instbuf); +} + void nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) @@ -182,6 +495,8 @@ nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start, BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); OUT_RING (chan, 0); + nv50_unmap_vbufs(nv50); + /* XXX: not sure what to do if ret != TRUE: flush and retry? */ assert(ret); @@ -210,7 +525,7 @@ nv50_draw_elements_inline_u08(struct nv50_context *nv50, uint8_t *map, unsigned nr = count > 2046 ? 2046 : count; int i; - BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16 | 0x40000000, nr >> 1); + BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U16, nr >> 1); for (i = 0; i < nr; i += 2) OUT_RING (chan, (map[i + 1] << 16) | map[i]); @@ -243,7 +558,7 @@ nv50_draw_elements_inline_u16(struct nv50_context *nv50, uint16_t *map, unsigned nr = count > 2046 ? 2046 : count; int i; - BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U16 | 0x40000000, nr >> 1); + BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U16, nr >> 1); for (i = 0; i < nr; i += 2) OUT_RING (chan, (map[i + 1] << 16) | map[i]); @@ -268,7 +583,7 @@ nv50_draw_elements_inline_u32(struct nv50_context *nv50, uint32_t *map, while (count) { unsigned nr = count > 2047 ? 2047 : count; - BEGIN_RING(chan, tesla, NV50TCL_VB_ELEMENT_U32 | 0x40000000, nr); + BEGIN_RING_NI(chan, tesla, NV50TCL_VB_ELEMENT_U32, nr); OUT_RINGp (chan, map, nr); count -= nr; @@ -277,6 +592,77 @@ nv50_draw_elements_inline_u32(struct nv50_context *nv50, uint32_t *map, return TRUE; } +static INLINE void +nv50_draw_elements_inline(struct nv50_context *nv50, + void *map, unsigned indexSize, + unsigned start, unsigned count) +{ + switch (indexSize) { + case 1: + nv50_draw_elements_inline_u08(nv50, map, start, count); + break; + case 2: + nv50_draw_elements_inline_u16(nv50, map, start, count); + break; + case 4: + nv50_draw_elements_inline_u32(nv50, map, start, count); + break; + } +} + +void +nv50_draw_elements_instanced(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned mode, unsigned start, unsigned count, + unsigned startInstance, unsigned instanceCount) +{ + struct nv50_context *nv50 = nv50_context(pipe); + struct nouveau_grobj *tesla = nv50->screen->tesla; + struct nouveau_channel *chan = tesla->channel; + struct pipe_screen *pscreen = pipe->screen; + void *map; + unsigned i, nz_divisors; + unsigned step[16], pos[16]; + + map = pipe_buffer_map(pscreen, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); + + if (!NV50_USING_LOATHED_EDGEFLAG(nv50)) + nv50_upload_user_vbufs(nv50); + + nv50_state_validate(nv50); + + nz_divisors = init_per_instance_arrays(nv50, startInstance, pos, step); + + BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 2); + OUT_RING (chan, NV50_CB_AUX | (24 << 8)); + OUT_RING (chan, startInstance); + + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); + OUT_RING (chan, nv50_prim(mode)); + + nv50_draw_elements_inline(nv50, map, indexSize, start, count); + + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); + OUT_RING (chan, 0); + + for (i = 1; i < instanceCount; ++i) { + if (nz_divisors) /* any non-zero array divisors ? */ + step_per_instance_arrays(nv50, pos, step); + + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); + OUT_RING (chan, nv50_prim(mode) | (1 << 28)); + + nv50_draw_elements_inline(nv50, map, indexSize, start, count); + + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); + OUT_RING (chan, 0); + } + nv50_unmap_vbufs(nv50); + + so_ref(NULL, &nv50->state.instbuf); +} + void nv50_draw_elements(struct pipe_context *pipe, struct pipe_buffer *indexBuffer, unsigned indexSize, @@ -287,7 +673,6 @@ nv50_draw_elements(struct pipe_context *pipe, struct nouveau_grobj *tesla = nv50->screen->tesla; struct pipe_screen *pscreen = pipe->screen; void *map; - boolean ret; map = pipe_buffer_map(pscreen, indexBuffer, PIPE_BUFFER_USAGE_CPU_READ); @@ -300,29 +685,15 @@ nv50_draw_elements(struct pipe_context *pipe, BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1); OUT_RING (chan, nv50_prim(mode)); - switch (indexSize) { - case 1: - ret = nv50_draw_elements_inline_u08(nv50, map, start, count); - break; - case 2: - ret = nv50_draw_elements_inline_u16(nv50, map, start, count); - break; - case 4: - ret = nv50_draw_elements_inline_u32(nv50, map, start, count); - break; - default: - assert(0); - ret = FALSE; - break; - } + + nv50_draw_elements_inline(nv50, map, indexSize, start, count); + BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1); OUT_RING (chan, 0); + nv50_unmap_vbufs(nv50); + pipe_buffer_unmap(pscreen, indexBuffer); - - /* XXX: what to do if ret != TRUE? Flush and retry? - */ - assert(ret); } static INLINE boolean @@ -335,23 +706,16 @@ nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib, struct nouveau_stateobj *so; struct nouveau_grobj *tesla = nv50->screen->tesla; struct nouveau_bo *bo = nouveau_bo(vb->buffer); - float *v; + float v[4]; int ret; - enum pipe_format pf = ve->src_format; - const struct util_format_description *desc; - - desc = util_format_description(pf); - assert(desc); - - if ((desc->channel[0].type != UTIL_FORMAT_TYPE_FLOAT) || - util_format_get_component_bits(pf, UTIL_FORMAT_COLORSPACE_RGB, 0) != 32) - return FALSE; ret = nouveau_bo_map(bo, NOUVEAU_BO_RD); if (ret) return FALSE; - v = (float *)(bo->map + (vb->buffer_offset + ve->src_offset)); + util_format_read_4f(ve->src_format, v, 0, (uint8_t *)bo->map + + (vb->buffer_offset + ve->src_offset), 0, + 0, 0, 1, 1); so = *pso; if (!so) *pso = so = so_new(nv50->vtxelt_nr, nv50->vtxelt_nr * 4, 0); @@ -409,7 +773,7 @@ nv50_vbo_validate(struct nv50_context *nv50) !(nv50->vtxbuf[i].buffer->usage & PIPE_BUFFER_USAGE_VERTEX)) nv50->vbo_fifo = 0xffff; - if (nv50->vertprog->cfg.edgeflag_in < 16) + if (NV50_USING_LOATHED_EDGEFLAG(nv50)) nv50->vbo_fifo = 0xffff; /* vertprog can't set edgeflag */ n_ve = MAX2(nv50->vtxelt_nr, nv50->state.vtxelt_nr); @@ -437,17 +801,20 @@ nv50_vbo_validate(struct nv50_context *nv50) nv50->vbo_fifo &= ~(1 << i); continue; } - so_data(vtxfmt, hw | i); if (nv50->vbo_fifo) { + so_data (vtxfmt, hw | + (ve->instance_divisor ? (1 << 4) : i)); so_method(vtxbuf, tesla, NV50TCL_VERTEX_ARRAY_FORMAT(i), 1); so_data (vtxbuf, 0); continue; } + so_data(vtxfmt, hw | i); so_method(vtxbuf, tesla, NV50TCL_VERTEX_ARRAY_FORMAT(i), 3); - so_data (vtxbuf, 0x20000000 | vb->stride); + so_data (vtxbuf, 0x20000000 | + (ve->instance_divisor ? 0 : vb->stride)); so_reloc (vtxbuf, bo, vb->buffer_offset + ve->src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_HIGH, 0, 0); @@ -485,7 +852,7 @@ typedef void (*pfn_push)(struct nouveau_channel *, void *); struct nv50_vbo_emitctx { pfn_push push[16]; - void *map[16]; + uint8_t *map[16]; unsigned stride[16]; unsigned nr_ve; unsigned vtx_dwords; @@ -523,19 +890,18 @@ nv50_map_vbufs(struct nv50_context *nv50) for (i = 0; i < nv50->vtxbuf_nr; ++i) { struct pipe_vertex_buffer *vb = &nv50->vtxbuf[i]; - unsigned size, delta; + unsigned size = vb->stride * (vb->max_index + 1) + 16; if (nouveau_bo(vb->buffer)->map) continue; - size = vb->stride * (vb->max_index + 1); - delta = vb->buffer_offset; - + size = vb->stride * (vb->max_index + 1) + 16; + size = MIN2(size, vb->buffer->size); if (!size) - size = vb->buffer->size - vb->buffer_offset; + size = vb->buffer->size; if (nouveau_bo_map_range(nouveau_bo(vb->buffer), - delta, size, NOUVEAU_BO_RD)) + 0, size, NOUVEAU_BO_RD)) break; } @@ -546,16 +912,6 @@ nv50_map_vbufs(struct nv50_context *nv50) return FALSE; } -static INLINE void -nv50_unmap_vbufs(struct nv50_context *nv50) -{ - unsigned i; - - for (i = 0; i < nv50->vtxbuf_nr; ++i) - if (nouveau_bo(nv50->vtxbuf[i].buffer)->map) - nouveau_bo_unmap(nouveau_bo(nv50->vtxbuf[i].buffer)); -} - static void emit_b32_1(struct nouveau_channel *chan, void *data) { @@ -650,12 +1006,13 @@ emit_prepare(struct nv50_context *nv50, struct nv50_vbo_emitctx *emit, ve = &nv50->vtxelt[i]; vb = &nv50->vtxbuf[ve->vertex_buffer_index]; - if (!(nv50->vbo_fifo & (1 << i))) + if (!(nv50->vbo_fifo & (1 << i)) || ve->instance_divisor) continue; n = emit->nr_ve++; emit->stride[n] = vb->stride; - emit->map[n] = nouveau_bo(vb->buffer)->map + + emit->map[n] = (uint8_t *)nouveau_bo(vb->buffer)->map + + vb->buffer_offset + (start * vb->stride + ve->src_offset); desc = util_format_description(ve->src_format); @@ -745,13 +1102,12 @@ nv50_push_arrays(struct nv50_context *nv50, unsigned start, unsigned count) set_edgeflag(chan, tesla, &emit, 0); /* nr will be 1 */ - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw); + BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, dw); for (i = 0; i < nr; ++i) emit_vtx_next(chan, &emit); count -= nr; } - nv50_unmap_vbufs(nv50); return TRUE; } @@ -772,13 +1128,12 @@ nv50_push_elements_u32(struct nv50_context *nv50, uint32_t *map, unsigned count) set_edgeflag(chan, tesla, &emit, *map); - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw); + BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, dw); for (i = 0; i < nr; ++i) emit_vtx(chan, &emit, *map++); count -= nr; } - nv50_unmap_vbufs(nv50); return TRUE; } @@ -799,13 +1154,12 @@ nv50_push_elements_u16(struct nv50_context *nv50, uint16_t *map, unsigned count) set_edgeflag(chan, tesla, &emit, *map); - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw); + BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, dw); for (i = 0; i < nr; ++i) emit_vtx(chan, &emit, *map++); count -= nr; } - nv50_unmap_vbufs(nv50); return TRUE; } @@ -826,13 +1180,12 @@ nv50_push_elements_u08(struct nv50_context *nv50, uint8_t *map, unsigned count) set_edgeflag(chan, tesla, &emit, *map); - BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw); + BEGIN_RING_NI(chan, tesla, NV50TCL_VERTEX_DATA, dw); for (i = 0; i < nr; ++i) emit_vtx(chan, &emit, *map++); count -= nr; } - nv50_unmap_vbufs(nv50); return TRUE; } diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index c14414fff6..cdedb30220 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -23,8 +23,6 @@ #include "r300_blit.h" #include "r300_context.h" -#include "util/u_rect.h" - static void r300_blitter_save_states(struct r300_context* r300) { util_blitter_save_blend(r300->blitter, r300->blend_state.state); @@ -75,13 +73,15 @@ void r300_clear(struct pipe_context* pipe, */ struct r300_context* r300 = r300_context(pipe); + struct pipe_framebuffer_state* fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; r300_blitter_save_states(r300); util_blitter_clear(r300->blitter, - r300->framebuffer_state.width, - r300->framebuffer_state.height, - r300->framebuffer_state.nr_cbufs, + fb->width, + fb->height, + fb->nr_cbufs, buffers, rgba, depth, stencil); } @@ -99,7 +99,7 @@ void r300_surface_copy(struct pipe_context* pipe, * is really transparent. The states will be restored by the blitter once * copying is done. */ r300_blitter_save_states(r300); - util_blitter_save_framebuffer(r300->blitter, &r300->framebuffer_state); + util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state); util_blitter_save_fragment_sampler_states( r300->blitter, r300->sampler_count, (void**)r300->sampler_states); @@ -123,7 +123,7 @@ void r300_surface_fill(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); r300_blitter_save_states(r300); - util_blitter_save_framebuffer(r300->blitter, &r300->framebuffer_state); + util_blitter_save_framebuffer(r300->blitter, r300->fb_state.state); util_blitter_fill(r300->blitter, dst, dstx, dsty, width, height, value); diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c index 51fdb82ff3..92de297ef1 100644 --- a/src/gallium/drivers/r300/r300_chipset.c +++ b/src/gallium/drivers/r300/r300_chipset.c @@ -33,6 +33,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) /* Reasonable defaults */ caps->num_vert_fpus = 4; caps->has_tcl = debug_get_bool_option("RADEON_NO_TCL", FALSE) ? FALSE : TRUE; + caps->is_r400 = FALSE; caps->is_r500 = FALSE; caps->high_second_pipe = FALSE; @@ -123,6 +124,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x4A54: caps->family = CHIP_FAMILY_R420; caps->num_vert_fpus = 6; + caps->is_r400 = TRUE; break; case 0x5548: @@ -136,6 +138,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x5D57: caps->family = CHIP_FAMILY_R423; caps->num_vert_fpus = 6; + caps->is_r400 = TRUE; break; case 0x554C: @@ -147,6 +150,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x5D4A: caps->family = CHIP_FAMILY_R430; caps->num_vert_fpus = 6; + caps->is_r400 = TRUE; break; case 0x5D4C: @@ -157,6 +161,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x5D52: caps->family = CHIP_FAMILY_R480; caps->num_vert_fpus = 6; + caps->is_r400 = TRUE; break; case 0x4B48: @@ -166,6 +171,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x4B4C: caps->family = CHIP_FAMILY_R481; caps->num_vert_fpus = 6; + caps->is_r400 = TRUE; break; case 0x5E4C: @@ -182,6 +188,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x5E4D: caps->family = CHIP_FAMILY_RV410; caps->num_vert_fpus = 6; + caps->is_r400 = TRUE; break; case 0x5954: @@ -212,6 +219,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x791F: caps->family = CHIP_FAMILY_RS690; caps->has_tcl = FALSE; + caps->is_r400 = TRUE; break; case 0x793F: @@ -219,6 +227,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x7942: caps->family = CHIP_FAMILY_RS600; caps->has_tcl = FALSE; + caps->is_r400 = TRUE; break; case 0x796C: @@ -227,6 +236,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x796F: caps->family = CHIP_FAMILY_RS740; caps->has_tcl = FALSE; + caps->is_r400 = TRUE; break; case 0x7100: diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h index 0633a8b8a7..2808486492 100644 --- a/src/gallium/drivers/r300/r300_chipset.h +++ b/src/gallium/drivers/r300/r300_chipset.h @@ -40,11 +40,18 @@ struct r300_capabilities { unsigned num_z_pipes; /* Whether or not TCL is physically present */ boolean has_tcl; + /* Whether or not this is R400. The differences compared to their R3xx + * cousins are: + * - Extended fragment shader registers + * - Blend LTE/GTE thresholds */ + boolean is_r400; /* Whether or not this is an RV515 or newer; R500s have many differences * that require extra consideration, compared to their R3xx cousins: * - Extra bit of width and height on texture sizes * - Blend color is split across two registers - * - Universal Shader (US) block used for fragment shaders */ + * - Blend LTE/GTE thresholds + * - Universal Shader (US) block used for fragment shaders + * - FP16 blending and multisampling */ boolean is_r500; /* Whether or not the second pixel pipe is accessed with the high bit */ boolean high_second_pipe; diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index af95bbe789..14820ca854 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -22,9 +22,6 @@ #include "draw/draw_context.h" -#include "tgsi/tgsi_scan.h" - -#include "util/u_hash_table.h" #include "util/u_memory.h" #include "util/u_simple_list.h" @@ -35,30 +32,16 @@ #include "r300_query.h" #include "r300_render.h" #include "r300_screen.h" -#include "r300_state_derived.h" #include "r300_state_invariant.h" #include "r300_texture.h" #include "r300_winsys.h" -static enum pipe_error r300_clear_hash_table(void* key, void* value, - void* data) -{ - FREE(key); - FREE(value); - return PIPE_OK; -} - static void r300_destroy_context(struct pipe_context* context) { struct r300_context* r300 = r300_context(context); struct r300_query* query, * temp; util_blitter_destroy(r300->blitter); - - util_hash_table_foreach(r300->shader_hash_table, r300_clear_hash_table, - NULL); - util_hash_table_destroy(r300->shader_hash_table); - draw_destroy(r300->draw); /* Free the OQ BO. */ @@ -72,9 +55,10 @@ static void r300_destroy_context(struct pipe_context* context) FREE(r300->blend_color_state.state); FREE(r300->clip_state.state); - FREE(r300->rs_block); + FREE(r300->fb_state.state); + FREE(r300->rs_block_state.state); FREE(r300->scissor_state.state); - FREE(r300->vertex_info); + FREE(r300->vertex_format_state.state); FREE(r300->viewport_state.state); FREE(r300->ztop_state.state); FREE(r300); @@ -87,7 +71,7 @@ r300_is_texture_referenced(struct pipe_context *pipe, { struct pipe_buffer* buf = 0; - r300_get_texture_buffer(texture, &buf, NULL); + r300_get_texture_buffer(pipe->screen, texture, &buf, NULL); return pipe->is_buffer_referenced(pipe, buf); } @@ -110,30 +94,48 @@ static void r300_flush_cb(void *data) cs_context_copy->context.flush(&cs_context_copy->context, 0, NULL); } -#define R300_INIT_ATOM(name) \ - r300->name##_state.state = NULL; \ - r300->name##_state.emit = r300_emit_##name##_state; \ - r300->name##_state.dirty = FALSE; \ - insert_at_tail(&r300->atom_list, &r300->name##_state); +#define R300_INIT_ATOM(atomname, atomsize) \ + r300->atomname##_state.name = #atomname; \ + r300->atomname##_state.state = NULL; \ + r300->atomname##_state.size = atomsize; \ + r300->atomname##_state.emit = r300_emit_##atomname##_state; \ + r300->atomname##_state.dirty = FALSE; \ + insert_at_tail(&r300->atom_list, &r300->atomname##_state); static void r300_setup_atoms(struct r300_context* r300) { + /* Create the actual atom list. + * + * Each atom is examined and emitted in the order it appears here, which + * can affect performance and conformance if not handled with care. + * + * Some atoms never change size, others change every emit. This is just + * an upper bound on each atom, to keep the emission machinery from + * underallocating space. */ make_empty_list(&r300->atom_list); - R300_INIT_ATOM(ztop); - R300_INIT_ATOM(blend); - R300_INIT_ATOM(blend_color); - R300_INIT_ATOM(clip); - R300_INIT_ATOM(dsa); - R300_INIT_ATOM(rs); - R300_INIT_ATOM(scissor); - R300_INIT_ATOM(viewport); + R300_INIT_ATOM(invariant, 71); + R300_INIT_ATOM(ztop, 2); + R300_INIT_ATOM(blend, 8); + R300_INIT_ATOM(blend_color, 3); + R300_INIT_ATOM(clip, 29); + R300_INIT_ATOM(dsa, 8); + R300_INIT_ATOM(fb, 56); + R300_INIT_ATOM(rs, 25); + R300_INIT_ATOM(scissor, 3); + R300_INIT_ATOM(viewport, 9); + R300_INIT_ATOM(rs_block, 21); + R300_INIT_ATOM(vertex_format, 26); + + /* Some non-CSO atoms need explicit space to store the state locally. */ + r300->fb_state.state = CALLOC_STRUCT(pipe_framebuffer_state); } struct pipe_context* r300_create_context(struct pipe_screen* screen, - struct radeon_winsys* radeon_winsys) + void *priv) { struct r300_context* r300 = CALLOC_STRUCT(r300_context); struct r300_screen* r300screen = r300_screen(screen); + struct radeon_winsys* radeon_winsys = r300screen->radeon_winsys; if (!r300) return NULL; @@ -142,8 +144,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300->context.winsys = (struct pipe_winsys*)radeon_winsys; r300->context.screen = screen; - - r300_init_debug(r300); + r300->context.priv = priv; r300->context.destroy = r300_destroy_context; @@ -174,16 +175,13 @@ 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; - r300->shader_hash_table = util_hash_table_create(r300_shader_key_hash, - r300_shader_key_compare); - r300_setup_atoms(r300); r300->blend_color_state.state = CALLOC_STRUCT(r300_blend_color_state); r300->clip_state.state = CALLOC_STRUCT(pipe_clip_state); - r300->rs_block = CALLOC_STRUCT(r300_rs_block); - r300->scissor_state.state = CALLOC_STRUCT(r300_scissor_state); - r300->vertex_info = CALLOC_STRUCT(r300_vertex_info); + r300->rs_block_state.state = CALLOC_STRUCT(r300_rs_block); + r300->scissor_state.state = CALLOC_STRUCT(pipe_scissor_state); + r300->vertex_format_state.state = CALLOC_STRUCT(r300_vertex_info); r300->viewport_state.state = CALLOC_STRUCT(r300_viewport_state); r300->ztop_state.state = CALLOC_STRUCT(r300_ztop_state); @@ -200,7 +198,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300_init_state_functions(r300); - r300_emit_invariant_state(r300); + r300->invariant_state.dirty = TRUE; r300->winsys->set_flush_cb(r300->winsys, r300_flush_cb, r300); r300->dirty_state = R300_NEW_KITCHEN_SINK; diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 5937f0e2cc..8461757812 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -28,7 +28,9 @@ #include "util/u_blitter.h" #include "pipe/p_context.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" + +#include "r300_screen.h" struct r300_context; @@ -36,10 +38,20 @@ struct r300_fragment_shader; struct r300_vertex_shader; struct r300_atom { + /* List pointers. */ struct r300_atom *prev, *next; + /* Name, for debugging. */ + const char* name; + /* Opaque state. */ void* state; + /* Emit the state to the context. */ void (*emit)(struct r300_context*, void*); + /* Upper bound on number of dwords to emit. */ + unsigned size; + /* Whether this atom should be emitted. */ boolean dirty; + /* Another dirty flag that is never automatically cleared. */ + boolean always_dirty; }; struct r300_blend_state { @@ -72,13 +84,14 @@ struct r300_rs_state { struct pipe_rasterizer_state rs; uint32_t vap_control_status; /* R300_VAP_CNTL_STATUS: 0x2140 */ + uint32_t antialiasing_config; /* R300_GB_AA_CONFIG: 0x4020 */ uint32_t point_size; /* R300_GA_POINT_SIZE: 0x421c */ uint32_t point_minmax; /* R300_GA_POINT_MINMAX: 0x4230 */ uint32_t line_control; /* R300_GA_LINE_CNTL: 0x4234 */ - uint32_t depth_scale_front; /* R300_SU_POLY_OFFSET_FRONT_SCALE: 0x42a4 */ - uint32_t depth_offset_front;/* R300_SU_POLY_OFFSET_FRONT_OFFSET: 0x42a8 */ - uint32_t depth_scale_back; /* R300_SU_POLY_OFFSET_BACK_SCALE: 0x42ac */ - uint32_t depth_offset_back; /* R300_SU_POLY_OFFSET_BACK_OFFSET: 0x42b0 */ + float depth_scale; /* R300_SU_POLY_OFFSET_FRONT_SCALE: 0x42a4 */ + /* R300_SU_POLY_OFFSET_BACK_SCALE: 0x42ac */ + float depth_offset; /* R300_SU_POLY_OFFSET_FRONT_OFFSET: 0x42a8 */ + /* R300_SU_POLY_OFFSET_BACK_OFFSET: 0x42b0 */ uint32_t polygon_offset_enable; /* R300_SU_POLY_OFFSET_ENABLE: 0x42b4 */ uint32_t cull_mode; /* R300_SU_CULL_MODE: 0x42b8 */ uint32_t line_stipple_config; /* R300_GA_LINE_STIPPLE_CONFIG: 0x4328 */ @@ -106,16 +119,6 @@ struct r300_sampler_state { unsigned min_lod, max_lod; }; -struct r300_scissor_regs { - uint32_t top_left; /* R300_SC_SCISSORS_TL: 0x43e0 */ - uint32_t bottom_right; /* R300_SC_SCISSORS_BR: 0x43e4 */ -}; - -struct r300_scissor_state { - struct r300_scissor_regs framebuffer; - struct r300_scissor_regs scissor; -}; - struct r300_texture_state { uint32_t format0; /* R300_TX_FORMAT0: 0x4480 */ uint32_t format1; /* R300_TX_FORMAT1: 0x44c0 */ @@ -136,15 +139,12 @@ struct r300_ztop_state { uint32_t z_buffer_top; /* R300_ZB_ZTOP: 0x4f14 */ }; -#define R300_NEW_FRAMEBUFFERS 0x00000010 #define R300_NEW_FRAGMENT_SHADER 0x00000020 #define R300_NEW_FRAGMENT_SHADER_CONSTANTS 0x00000040 -#define R300_NEW_RS_BLOCK 0x00000100 #define R300_NEW_SAMPLER 0x00000200 #define R300_ANY_NEW_SAMPLERS 0x0001fe00 #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_VERTEX_SHADER_CONSTANTS 0x10000000 #define R300_NEW_QUERY 0x40000000 @@ -188,6 +188,12 @@ struct r300_query { struct r300_query* next; }; +enum r300_buffer_tiling { + R300_BUFFER_LINEAR = 0, + R300_BUFFER_TILED, + R300_BUFFER_SQUARETILED +}; + struct r300_texture { /* Parent class */ struct pipe_texture tex; @@ -224,6 +230,9 @@ struct r300_texture { /* Registers carrying texture format data. */ struct r300_texture_state state; + + /* Buffer tiling */ + enum r300_buffer_tiling microtile, macrotile; }; struct r300_vertex_info { @@ -260,11 +269,8 @@ struct r300_context { struct r300_query *query_current; struct r300_query query_list; - /* Shader hash table. Used to store vertex formatting information, which - * depends on the combination of both currently loaded shaders. */ - struct util_hash_table* shader_hash_table; /* Vertex formatting information. */ - struct r300_vertex_info* vertex_info; + struct r300_atom vertex_format_state; /* Various CSO state objects. */ /* Beginning of atom list. */ @@ -281,12 +287,12 @@ struct r300_context { struct r300_atom dsa_state; /* Fragment shader. */ struct r300_fragment_shader* fs; - /* Framebuffer state. We currently don't need our own version of this. */ - struct pipe_framebuffer_state framebuffer_state; + /* Framebuffer state. */ + struct r300_atom fb_state; /* Rasterizer state. */ struct r300_atom rs_state; /* RS block state. */ - struct r300_rs_block* rs_block; + struct r300_atom rs_block_state; /* Sampler states. */ struct r300_sampler_state* sampler_states[8]; int sampler_count; @@ -302,6 +308,9 @@ struct r300_context { /* ZTOP state. */ struct r300_atom ztop_state; + /* Invariant state. This must be emitted to get the engine started. */ + struct r300_atom invariant_state; + /* Vertex buffers for Gallium. */ struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; int vertex_buffer_count; @@ -315,9 +324,10 @@ struct r300_context { uint32_t dirty_hw; /* Whether the TCL engine should be in bypass mode. */ boolean tcl_bypass; - - /** Combination of DBG_xxx flags */ - unsigned debug; + /* Whether polygon offset is enabled. */ + boolean polygon_offset_enabled; + /* Z buffer bit depth. */ + uint32_t zbuffer_bpp; }; /* Convenience cast wrapper. */ @@ -326,40 +336,24 @@ static INLINE struct r300_context* r300_context(struct pipe_context* context) return (struct r300_context*)context; } + +struct pipe_context* r300_create_context(struct pipe_screen* screen, + void *priv); + /* Context initialization. */ struct draw_stage* r300_draw_stage(struct r300_context* r300); void r300_init_state_functions(struct r300_context* r300); void r300_init_surface_functions(struct r300_context* r300); -/* Debug functionality. */ - -/** - * Debug flags to disable/enable certain groups of debugging outputs. - * - * \note These may be rather coarse, and the grouping may be impractical. - * If you find, while debugging the driver, that a different grouping - * of these flags would be beneficial, just feel free to change them - * but make sure to update the documentation in r300_debug.c to reflect - * those changes. - */ -/*@{*/ -#define DBG_HELP 0x0000001 -#define DBG_FP 0x0000002 -#define DBG_VP 0x0000004 -#define DBG_CS 0x0000008 -#define DBG_DRAW 0x0000010 -#define DBG_TEX 0x0000020 -#define DBG_FALL 0x0000040 -/*@}*/ - -static INLINE boolean DBG_ON(struct r300_context * ctx, unsigned flags) +static INLINE boolean CTX_DBG_ON(struct r300_context * ctx, unsigned flags) { - return (ctx->debug & flags) ? TRUE : FALSE; + return SCREEN_DBG_ON(r300_screen(ctx->context.screen), flags); } -static INLINE void DBG(struct r300_context * ctx, unsigned flags, const char * fmt, ...) +static INLINE void CTX_DBG(struct r300_context * ctx, unsigned flags, + const char * fmt, ...) { - if (DBG_ON(ctx, flags)) { + if (CTX_DBG_ON(ctx, flags)) { va_list va; va_start(va, fmt); debug_vprintf(fmt, va); @@ -367,6 +361,8 @@ static INLINE void DBG(struct r300_context * ctx, unsigned flags, const char * f } } -void r300_init_debug(struct r300_context * ctx); +#define DBG_ON CTX_DBG_ON +#define DBG CTX_DBG #endif /* R300_CONTEXT_H */ + diff --git a/src/gallium/drivers/r300/r300_cs.h b/src/gallium/drivers/r300/r300_cs.h index d142fee050..151f72b0fe 100644 --- a/src/gallium/drivers/r300/r300_cs.h +++ b/src/gallium/drivers/r300/r300_cs.h @@ -52,7 +52,7 @@ #define CS_LOCALS(context) \ struct r300_context* const cs_context_copy = (context); \ struct radeon_winsys* cs_winsys = cs_context_copy->winsys; \ - int cs_count = 0; + int cs_count = 0; (void) cs_count; #define CHECK_CS(size) \ assert(cs_winsys->check_cs(cs_winsys, (size))) diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c index 2a6ed54ac9..b881730848 100644 --- a/src/gallium/drivers/r300/r300_debug.c +++ b/src/gallium/drivers/r300/r300_debug.c @@ -22,8 +22,6 @@ #include "r300_context.h" -#include <ctype.h> - struct debug_option { const char * name; @@ -46,7 +44,7 @@ static struct debug_option debug_options[] = { { 0, 0, 0 } }; -void r300_init_debug(struct r300_context * ctx) +void r300_init_debug(struct r300_screen * screen) { const char * options = debug_get_option("RADEON_DEBUG", 0); boolean printhint = FALSE; @@ -64,7 +62,7 @@ void r300_init_debug(struct r300_context * ctx) for(opt = debug_options; opt->name; ++opt) { if (!strncmp(options, opt->name, length)) { - ctx->debug |= opt->flag; + screen->debug |= opt->flag; break; } } @@ -77,11 +75,11 @@ void r300_init_debug(struct r300_context * ctx) options += length; } - if (!ctx->debug) + if (!screen->debug) printhint = TRUE; } - if (printhint || ctx->debug & DBG_HELP) { + if (printhint || screen->debug & DBG_HELP) { debug_printf("You can enable debug output by setting the RADEON_DEBUG environment variable\n" "to a comma-separated list of debug options. Available options are:\n"); for(opt = debug_options; opt->name; ++opt) { diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 0e5533c790..ae83511a85 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -32,19 +32,20 @@ #include "r300_emit.h" #include "r300_fs.h" #include "r300_screen.h" -#include "r300_state_derived.h" #include "r300_state_inlines.h" -#include "r300_texture.h" #include "r300_vs.h" void r300_emit_blend_state(struct r300_context* r300, void* state) { struct r300_blend_state* blend = (struct r300_blend_state*)state; + struct pipe_framebuffer_state* fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; CS_LOCALS(r300); + BEGIN_CS(8); OUT_CS_REG(R300_RB3D_ROPCNTL, blend->rop); OUT_CS_REG_SEQ(R300_RB3D_CBLEND, 3); - if (r300->framebuffer_state.nr_cbufs) { + if (fb->nr_cbufs) { OUT_CS(blend->blend_control); OUT_CS(blend->alpha_blend_control); OUT_CS(blend->color_channel_mask); @@ -111,19 +112,15 @@ void r300_emit_dsa_state(struct r300_context* r300, void* state) { struct r300_dsa_state* dsa = (struct r300_dsa_state*)state; struct r300_screen* r300screen = r300_screen(r300->context.screen); + struct pipe_framebuffer_state* fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; CS_LOCALS(r300); BEGIN_CS(r300screen->caps->is_r500 ? 8 : 6); OUT_CS_REG(R300_FG_ALPHA_FUNC, dsa->alpha_function); - - /* not needed since we use the 8bit alpha ref */ - /*if (r300screen->caps->is_r500) { - OUT_CS_REG(R500_FG_ALPHA_VALUE, dsa->alpha_reference); - }*/ - OUT_CS_REG_SEQ(R300_ZB_CNTL, 3); - if (r300->framebuffer_state.zsbuf) { + if (fb->zsbuf) { OUT_CS(dsa->z_buffer_control); OUT_CS(dsa->z_stencil_control); } else { @@ -133,7 +130,6 @@ void r300_emit_dsa_state(struct r300_context* r300, void* state) OUT_CS(dsa->stencil_ref_mask); - /* XXX it seems r3xx doesn't support STENCILREFMASK_BF */ if (r300screen->caps->is_r500) { OUT_CS_REG(R500_ZB_STENCILREFMASK_BF, dsa->stencil_ref_bf); } @@ -167,9 +163,8 @@ static const float * get_shader_constant( vec[1] = 1.0 / tex->height0; break; - /* Texture compare-fail value. */ - /* XXX Since Gallium doesn't support GL_ARB_shadow_ambient, - * this is always (0,0,0,0), right? */ + /* Texture compare-fail value. Shouldn't ever show up, but if + * it does, we'll be ready. */ case RC_STATE_SHADOW_AMBIENT: vec[3] = 0; break; @@ -383,17 +378,14 @@ void r500_emit_fs_constant_buffer(struct r300_context* r300, END_CS; } -void r300_emit_fb_state(struct r300_context* r300, - struct pipe_framebuffer_state* fb) +void r300_emit_fb_state(struct r300_context* r300, void* state) { + struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)state; struct r300_texture* tex; struct pipe_surface* surf; int i; CS_LOCALS(r300); - /* Shouldn't fail unless there is a bug in the state tracker. */ - assert(fb->nr_cbufs <= 4); - BEGIN_CS((10 * fb->nr_cbufs) + (2 * (4 - fb->nr_cbufs)) + (fb->zsbuf ? 10 : 0) + 6); @@ -406,7 +398,14 @@ void r300_emit_fb_state(struct r300_context* r300, R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE); /* Set the number of colorbuffers. */ - OUT_CS_REG(R300_RB3D_CCTL, R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs)); + if (fb->nr_cbufs > 1) { + OUT_CS_REG(R300_RB3D_CCTL, + R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs) | + R300_RB3D_CCTL_INDEPENDENT_COLOR_CHANNEL_MASK_ENABLE | + R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE); + } else { + OUT_CS_REG(R300_RB3D_CCTL, 0x0); + } /* Set up colorbuffers. */ for (i = 0; i < fb->nr_cbufs; i++) { @@ -419,8 +418,10 @@ void r300_emit_fb_state(struct r300_context* r300, OUT_CS_REG_SEQ(R300_RB3D_COLORPITCH0 + (4 * i), 1); OUT_CS_RELOC(tex->buffer, tex->pitch[surf->level] | - r300_translate_colorformat(tex->tex.format), 0, - RADEON_GEM_DOMAIN_VRAM, 0); + r300_translate_colorformat(tex->tex.format) | + R300_COLOR_TILE(tex->macrotile) | + R300_COLOR_MICROTILE(tex->microtile), + 0, RADEON_GEM_DOMAIN_VRAM, 0); OUT_CS_REG(R300_US_OUT_FMT_0 + (4 * i), r300_translate_out_fmt(surf->format)); @@ -443,8 +444,10 @@ void r300_emit_fb_state(struct r300_context* r300, OUT_CS_REG(R300_ZB_FORMAT, r300_translate_zsformat(tex->tex.format)); OUT_CS_REG_SEQ(R300_ZB_DEPTHPITCH, 1); - OUT_CS_RELOC(tex->buffer, tex->pitch[surf->level], 0, - RADEON_GEM_DOMAIN_VRAM, 0); + OUT_CS_RELOC(tex->buffer, tex->pitch[surf->level] | + R300_DEPTHMACROTILE(tex->macrotile) | + R300_DEPTHMICROTILE(tex->microtile), + 0, RADEON_GEM_DOMAIN_VRAM, 0); } END_CS; @@ -579,32 +582,52 @@ void r300_emit_query_end(struct r300_context* r300) void r300_emit_rs_state(struct r300_context* r300, void* state) { struct r300_rs_state* rs = (struct r300_rs_state*)state; + float scale, offset; CS_LOCALS(r300); - BEGIN_CS(22); + BEGIN_CS(18 + (rs->polygon_offset_enable ? 5 : 0)); OUT_CS_REG(R300_VAP_CNTL_STATUS, rs->vap_control_status); + + OUT_CS_REG(R300_GB_AA_CONFIG, rs->antialiasing_config); + OUT_CS_REG(R300_GA_POINT_SIZE, rs->point_size); OUT_CS_REG_SEQ(R300_GA_POINT_MINMAX, 2); OUT_CS(rs->point_minmax); OUT_CS(rs->line_control); - OUT_CS_REG_SEQ(R300_SU_POLY_OFFSET_FRONT_SCALE, 6); - OUT_CS(rs->depth_scale_front); - OUT_CS(rs->depth_offset_front); - OUT_CS(rs->depth_scale_back); - OUT_CS(rs->depth_offset_back); + + if (rs->polygon_offset_enable) { + scale = rs->depth_scale * 12; + offset = rs->depth_offset; + + switch (r300->zbuffer_bpp) { + case 16: + offset *= 4; + break; + case 24: + offset *= 2; + break; + } + + OUT_CS_REG_SEQ(R300_SU_POLY_OFFSET_FRONT_SCALE, 4); + OUT_CS_32F(scale); + OUT_CS_32F(offset); + OUT_CS_32F(scale); + OUT_CS_32F(offset); + } + + OUT_CS_REG_SEQ(R300_SU_POLY_OFFSET_ENABLE, 2); OUT_CS(rs->polygon_offset_enable); OUT_CS(rs->cull_mode); OUT_CS_REG(R300_GA_LINE_STIPPLE_CONFIG, rs->line_stipple_config); OUT_CS_REG(R300_GA_LINE_STIPPLE_VALUE, rs->line_stipple_value); - OUT_CS_REG(R300_GA_COLOR_CONTROL, rs->color_control); OUT_CS_REG(R300_GA_POLY_MODE, rs->polygon_mode); END_CS; } -void r300_emit_rs_block_state(struct r300_context* r300, - struct r300_rs_block* rs) +void r300_emit_rs_block_state(struct r300_context* r300, void* state) { - int i; + struct r300_rs_block* rs = (struct r300_rs_block*)state; + unsigned i; struct r300_screen* r300screen = r300_screen(r300->context.screen); CS_LOCALS(r300); @@ -641,27 +664,65 @@ void r300_emit_rs_block_state(struct r300_context* r300, END_CS; } -static void r300_emit_scissor_regs(struct r300_context* r300, - struct r300_scissor_regs* scissor) +void r300_emit_scissor_state(struct r300_context* r300, void* state) { + unsigned minx, miny, maxx, maxy; + uint32_t top_left, bottom_right; + struct r300_screen* r300screen = r300_screen(r300->context.screen); + struct pipe_scissor_state* scissor = (struct pipe_scissor_state*)state; + struct pipe_framebuffer_state* fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; CS_LOCALS(r300); - BEGIN_CS(3); - OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2); - OUT_CS(scissor->top_left); - OUT_CS(scissor->bottom_right); - END_CS; -} + minx = miny = 0; + maxx = fb->width; + maxy = fb->height; -void r300_emit_scissor_state(struct r300_context* r300, void* state) -{ - struct r300_scissor_state* scissor = (struct r300_scissor_state*)state; - /* XXX argfl! */ if (((struct r300_rs_state*)r300->rs_state.state)->rs.scissor) { - r300_emit_scissor_regs(r300, &scissor->scissor); + minx = MAX2(minx, scissor->minx); + miny = MAX2(miny, scissor->miny); + maxx = MIN2(maxx, scissor->maxx); + maxy = MIN2(maxy, scissor->maxy); + } + + /* Special case for zero-area scissor. + * + * We can't allow the variables maxx and maxy to be zero because they are + * subtracted from later in the code, which would cause emitting ~0 and + * making the kernel checker angry. + * + * Let's consider we change maxx and maxy to 1, which is effectively + * a one-pixel area. We must then change minx and miny to a number which is + * greater than 1 to get the zero area back. */ + if (!maxx || !maxy) { + minx = 2; + miny = 2; + maxx = 1; + maxy = 1; + } + + if (r300screen->caps->is_r500) { + top_left = + (minx << R300_SCISSORS_X_SHIFT) | + (miny << R300_SCISSORS_Y_SHIFT); + bottom_right = + ((maxx - 1) << R300_SCISSORS_X_SHIFT) | + ((maxy - 1) << R300_SCISSORS_Y_SHIFT); } else { - r300_emit_scissor_regs(r300, &scissor->framebuffer); + /* Offset of 1440 in non-R500 chipsets. */ + top_left = + ((minx + 1440) << R300_SCISSORS_X_SHIFT) | + ((miny + 1440) << R300_SCISSORS_Y_SHIFT); + bottom_right = + (((maxx - 1) + 1440) << R300_SCISSORS_X_SHIFT) | + (((maxy - 1) + 1440) << R300_SCISSORS_Y_SHIFT); } + + BEGIN_CS(3); + OUT_CS_REG_SEQ(R300_SC_SCISSORS_TL, 2); + OUT_CS(top_left); + OUT_CS(bottom_right); + END_CS; } void r300_emit_texture(struct r300_context* r300, @@ -680,12 +741,18 @@ void r300_emit_texture(struct r300_context* r300, filter0 |= R300_TX_WRAP_T(R300_TX_CLAMP_TO_EDGE); } - /* determine min/max levels */ - /* the MAX_MIP level is the largest (finest) one */ - max_level = MIN2(sampler->max_lod, tex->tex.last_level); - min_level = MIN2(sampler->min_lod, max_level); - format0 |= R300_TX_NUM_LEVELS(max_level); - filter0 |= R300_TX_MAX_MIP_LEVEL(min_level); + if (tex->is_npot) { + /* NPOT textures don't support mip filter, unfortunately. + * This prevents incorrect rendering. */ + filter0 &= ~R300_TX_MIN_FILTER_MIP_MASK; + } else { + /* determine min/max levels */ + /* the MAX_MIP level is the largest (finest) one */ + max_level = MIN2(sampler->max_lod, tex->tex.last_level); + min_level = MIN2(sampler->min_lod, max_level); + format0 |= R300_TX_NUM_LEVELS(max_level); + filter0 |= R300_TX_MAX_MIP_LEVEL(min_level); + } BEGIN_CS(16); OUT_CS_REG(R300_TX_FILTER0_0 + (offset * 4), filter0 | @@ -697,27 +764,13 @@ void r300_emit_texture(struct r300_context* r300, OUT_CS_REG(R300_TX_FORMAT1_0 + (offset * 4), tex->state.format1); OUT_CS_REG(R300_TX_FORMAT2_0 + (offset * 4), tex->state.format2); OUT_CS_REG_SEQ(R300_TX_OFFSET_0 + (offset * 4), 1); - OUT_CS_RELOC(tex->buffer, 0, - RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0); + OUT_CS_RELOC(tex->buffer, + R300_TXO_MACRO_TILE(tex->macrotile) | + R300_TXO_MICRO_TILE(tex->microtile), + RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0, 0); END_CS; } -static boolean r300_validate_aos(struct r300_context *r300) -{ - struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; - struct pipe_vertex_element *velem = r300->vertex_element; - int i; - - /* Check if formats and strides are aligned to the size of DWORD. */ - for (i = 0; i < r300->vertex_element_count; i++) { - if (vbuf[velem[i].vertex_buffer_index].stride % 4 != 0 || - util_format_get_blocksize(velem[i].src_format) % 4 != 0) { - return FALSE; - } - } - return TRUE; -} - void r300_emit_aos(struct r300_context* r300, unsigned offset) { struct pipe_vertex_buffer *vb1, *vb2, *vbuf = r300->vertex_buffer; @@ -727,12 +780,6 @@ void r300_emit_aos(struct r300_context* r300, unsigned offset) unsigned packet_size = (aos_count * 3 + 1) / 2; CS_LOCALS(r300); - /* XXX Move this checking to a more approriate place. */ - if (!r300_validate_aos(r300)) { - /* XXX We should fallback using Draw. */ - assert(0); - } - BEGIN_CS(2 + packet_size + aos_count * 2); OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size); OUT_CS(aos_count); @@ -764,64 +811,39 @@ void r300_emit_aos(struct r300_context* r300, unsigned offset) END_CS; } -#if 0 -void r300_emit_draw_packet(struct r300_context* r300) +void r300_emit_vertex_format_state(struct r300_context* r300, void* state) { - CS_LOCALS(r300); - - DBG(r300, DBG_DRAW, "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; -} -#endif - -void r300_emit_vertex_format_state(struct r300_context* r300) -{ - int i; + struct r300_vertex_info* vertex_info = (struct r300_vertex_info*)state; + unsigned i; CS_LOCALS(r300); DBG(r300, DBG_DRAW, "r300: VAP/PSC emit:\n"); BEGIN_CS(26); - OUT_CS_REG(R300_VAP_VTX_SIZE, r300->vertex_info->vinfo.size); + OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_info->vinfo.size); OUT_CS_REG_SEQ(R300_VAP_VTX_STATE_CNTL, 2); - OUT_CS(r300->vertex_info->vinfo.hwfmt[0]); - OUT_CS(r300->vertex_info->vinfo.hwfmt[1]); + OUT_CS(vertex_info->vinfo.hwfmt[0]); + OUT_CS(vertex_info->vinfo.hwfmt[1]); 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]); + OUT_CS(vertex_info->vinfo.hwfmt[2]); + OUT_CS(vertex_info->vinfo.hwfmt[3]); for (i = 0; i < 4; i++) { DBG(r300, DBG_DRAW, " : hwfmt%d: 0x%08x\n", i, - r300->vertex_info->vinfo.hwfmt[i]); + 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]); + OUT_CS(vertex_info->vap_prog_stream_cntl[i]); DBG(r300, DBG_DRAW, " : prog_stream_cntl%d: 0x%08x\n", i, - r300->vertex_info->vap_prog_stream_cntl[i]); + 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]); + OUT_CS(vertex_info->vap_prog_stream_cntl_ext[i]); DBG(r300, DBG_DRAW, " : prog_stream_cntl_ext%d: 0x%08x\n", i, - r300->vertex_info->vap_prog_stream_cntl_ext[i]); + vertex_info->vap_prog_stream_cntl_ext[i]); } END_CS; } @@ -986,30 +1008,21 @@ static void r300_flush_pvs(struct r300_context* r300) END_CS; } -/* Emit all dirty state. */ -void r300_emit_dirty_state(struct r300_context* r300) +void r300_emit_buffer_validate(struct r300_context *r300) { - struct r300_screen* r300screen = r300_screen(r300->context.screen); + struct pipe_framebuffer_state* fb = + (struct pipe_framebuffer_state*)r300->fb_state.state; struct r300_texture* tex; - struct r300_atom* atom; - int i, dirty_tex = 0; + unsigned i; boolean invalid = FALSE; - /* Check size of CS. */ - /* Make sure we have at least 8*1024 spare dwords. */ - /* XXX It would be nice to know the number of dwords we really need to - * XXX emit. */ - if (!r300->winsys->check_cs(r300->winsys, 8*1024)) { - r300->context.flush(&r300->context, 0, NULL); - } - /* Clean out BOs. */ r300->winsys->reset_bos(r300->winsys); validate: /* Color buffers... */ - for (i = 0; i < r300->framebuffer_state.nr_cbufs; i++) { - tex = (struct r300_texture*)r300->framebuffer_state.cbufs[i]->texture; + 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!"); if (!r300->winsys->add_buffer(r300->winsys, tex->buffer, 0, RADEON_GEM_DOMAIN_VRAM)) { @@ -1018,8 +1031,8 @@ validate: } } /* ...depth buffer... */ - if (r300->framebuffer_state.zsbuf) { - tex = (struct r300_texture*)r300->framebuffer_state.zsbuf->texture; + if (fb->zsbuf) { + tex = (struct r300_texture*)fb->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)) { @@ -1039,10 +1052,12 @@ validate: } } /* ...occlusion query buffer... */ - if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo, - 0, RADEON_GEM_DOMAIN_GTT)) { - r300->context.flush(&r300->context, 0, NULL); - goto validate; + if (r300->dirty_state & R300_NEW_QUERY) { + if (!r300->winsys->add_buffer(r300->winsys, r300->oqbo, + 0, RADEON_GEM_DOMAIN_GTT)) { + r300->context.flush(&r300->context, 0, NULL); + goto validate; + } } /* ...and vertex buffer. */ if (r300->vbo) { @@ -1064,6 +1079,31 @@ validate: invalid = TRUE; goto validate; } +} + +/* Emit all dirty state. */ +void r300_emit_dirty_state(struct r300_context* r300) +{ + struct r300_screen* r300screen = r300_screen(r300->context.screen); + struct r300_atom* atom; + unsigned i, dwords = 1024; + int dirty_tex = 0; + + /* Check the required number of dwords against the space remaining in the + * current CS object. If we need more, then flush. */ + + foreach(atom, &r300->atom_list) { + if (atom->dirty || atom->always_dirty) { + dwords += atom->size; + } + } + + /* Make sure we have at least 2*1024 spare dwords. */ + /* XXX It would be nice to know the number of dwords we really need to + * XXX emit. */ + while (!r300->winsys->check_cs(r300->winsys, dwords)) { + r300->context.flush(&r300->context, 0, NULL); + } if (r300->dirty_state & R300_NEW_QUERY) { r300_emit_query_start(r300); @@ -1071,7 +1111,7 @@ validate: } foreach(atom, &r300->atom_list) { - if (atom->dirty) { + if (atom->dirty || atom->always_dirty) { atom->emit(r300, atom->state); atom->dirty = FALSE; } @@ -1098,16 +1138,6 @@ validate: r300->dirty_state &= ~R300_NEW_FRAGMENT_SHADER_CONSTANTS; } - if (r300->dirty_state & R300_NEW_FRAMEBUFFERS) { - r300_emit_fb_state(r300, &r300->framebuffer_state); - r300->dirty_state &= ~R300_NEW_FRAMEBUFFERS; - } - - if (r300->dirty_state & R300_NEW_RS_BLOCK) { - r300_emit_rs_block_state(r300, r300->rs_block); - r300->dirty_state &= ~R300_NEW_RS_BLOCK; - } - /* Samplers and textures are tracked separately but emitted together. */ if (r300->dirty_state & (R300_ANY_NEW_SAMPLERS | R300_ANY_NEW_TEXTURES)) { @@ -1133,11 +1163,6 @@ validate: r300_flush_textures(r300); } - if (r300->dirty_state & R300_NEW_VERTEX_FORMAT) { - r300_emit_vertex_format_state(r300); - r300->dirty_state &= ~R300_NEW_VERTEX_FORMAT; - } - if (r300->dirty_state & (R300_NEW_VERTEX_SHADER | R300_NEW_VERTEX_SHADER_CONSTANTS)) { r300_flush_pvs(r300); } diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h index 05a6bfeae8..6b96d9b57c 100644 --- a/src/gallium/drivers/r300/r300_emit.h +++ b/src/gallium/drivers/r300/r300_emit.h @@ -51,8 +51,7 @@ void r500_emit_fragment_program_code(struct r300_context* r300, void r500_emit_fs_constant_buffer(struct r300_context* r300, struct rc_constant_list* constants); -void r300_emit_fb_state(struct r300_context* r300, - struct pipe_framebuffer_state* fb); +void r300_emit_fb_state(struct r300_context* r300, void* state); void r300_emit_query_begin(struct r300_context* r300, struct r300_query* query); @@ -61,8 +60,7 @@ void r300_emit_query_end(struct r300_context* r300); void r300_emit_rs_state(struct r300_context* r300, void* state); -void r300_emit_rs_block_state(struct r300_context* r300, - struct r300_rs_block* rs); +void r300_emit_rs_block_state(struct r300_context* r300, void* state); void r300_emit_scissor_state(struct r300_context* r300, void* state); @@ -73,7 +71,7 @@ void r300_emit_texture(struct r300_context* r300, void r300_emit_vertex_buffer(struct r300_context* r300); -void r300_emit_vertex_format_state(struct r300_context* r300); +void r300_emit_vertex_format_state(struct r300_context* r300, void* state); void r300_emit_vertex_program_code(struct r300_context* r300, struct r300_vertex_program_code* code); @@ -95,4 +93,6 @@ void r300_flush_textures(struct r300_context* r300); /* Emit all dirty state. */ void r300_emit_dirty_state(struct r300_context* r300); +void r300_emit_buffer_validate(struct r300_context *r300); + #endif /* R300_EMIT_H */ diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c index 14a08241fc..e37d309270 100644 --- a/src/gallium/drivers/r300/r300_flush.c +++ b/src/gallium/drivers/r300/r300_flush.c @@ -29,7 +29,6 @@ #include "r300_cs.h" #include "r300_emit.h" #include "r300_flush.h" -#include "r300_state_invariant.h" static void r300_flush(struct pipe_context* pipe, unsigned flags, @@ -37,8 +36,10 @@ static void r300_flush(struct pipe_context* pipe, { struct r300_context *r300 = r300_context(pipe); struct r300_query *query; + struct r300_atom *atom; CS_LOCALS(r300); + (void) cs_count; /* 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. * @@ -51,10 +52,17 @@ static void r300_flush(struct pipe_context* pipe, if (r300->dirty_hw) { FLUSH_CS; - r300_emit_invariant_state(r300); r300->dirty_state = R300_NEW_KITCHEN_SINK; r300->dirty_hw = 0; + + /* New kitchen sink, baby. */ + foreach(atom, &r300->atom_list) { + if (atom->state) { + atom->dirty = TRUE; + } + } } + /* reset flushed query */ foreach(query, &r300->query_list) { query->flushed = TRUE; diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index 60ea9c171d..75a05498eb 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -49,12 +49,12 @@ void r300_shader_read_fs_inputs(struct tgsi_shader_info* info, switch (info->input_semantic_name[i]) { case TGSI_SEMANTIC_COLOR: - assert(index <= ATTR_COLOR_COUNT); + assert(index < ATTR_COLOR_COUNT); fs_inputs->color[index] = i; break; case TGSI_SEMANTIC_GENERIC: - assert(index <= ATTR_GENERIC_COUNT); + assert(index < ATTR_GENERIC_COUNT); fs_inputs->generic[index] = i; break; @@ -77,17 +77,21 @@ void r300_shader_read_fs_inputs(struct tgsi_shader_info* info, static void find_output_registers(struct r300_fragment_program_compiler * compiler, struct r300_fragment_shader * fs) { - unsigned i; + unsigned i, colorbuf_count = 0; /* Mark the outputs as not present initially */ - compiler->OutputColor = fs->info.num_outputs; + compiler->OutputColor[0] = fs->info.num_outputs; + compiler->OutputColor[1] = fs->info.num_outputs; + compiler->OutputColor[2] = fs->info.num_outputs; + compiler->OutputColor[3] = fs->info.num_outputs; compiler->OutputDepth = fs->info.num_outputs; /* Now see where they really are. */ for(i = 0; i < fs->info.num_outputs; ++i) { switch(fs->info.output_semantic_name[i]) { case TGSI_SEMANTIC_COLOR: - compiler->OutputColor = i; + compiler->OutputColor[colorbuf_count] = i; + colorbuf_count++; break; case TGSI_SEMANTIC_POSITION: compiler->OutputDepth = i; diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h index 034bfc15cf..361813891f 100644 --- a/src/gallium/drivers/r300/r300_reg.h +++ b/src/gallium/drivers/r300/r300_reg.h @@ -1619,18 +1619,20 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define R300_TX_OFFSET_5 0x4554 #define R300_TX_OFFSET_6 0x4558 #define R300_TX_OFFSET_7 0x455C - /* BEGIN: Guess from R200 */ + # define R300_TXO_ENDIAN_NO_SWAP (0 << 0) # define R300_TXO_ENDIAN_BYTE_SWAP (1 << 0) # define R300_TXO_ENDIAN_WORD_SWAP (2 << 0) # define R300_TXO_ENDIAN_HALFDW_SWAP (3 << 0) -# define R300_TXO_MACRO_TILE (1 << 2) +# define R300_TXO_MACRO_TILE_LINEAR (0 << 2) +# define R300_TXO_MACRO_TILE_TILED (1 << 2) +# define R300_TXO_MACRO_TILE(x) ((x) << 2) # define R300_TXO_MICRO_TILE_LINEAR (0 << 3) -# define R300_TXO_MICRO_TILE (1 << 3) -# define R300_TXO_MICRO_TILE_SQUARE (2 << 3) +# define R300_TXO_MICRO_TILE_TILED (1 << 3) +# define R300_TXO_MICRO_TILE_TILED_SQUARE (2 << 3) +# define R300_TXO_MICRO_TILE(x) ((x) << 3) # define R300_TXO_OFFSET_MASK 0xffffffe0 # define R300_TXO_OFFSET_SHIFT 5 - /* END: Guess from R200 */ /* 32 bit chroma key */ #define R300_TX_CHROMA_KEY_0 0x4580 @@ -2283,9 +2285,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_COLORPITCH_MASK 0x00003FFE # define R300_COLOR_TILE_DISABLE (0 << 16) # define R300_COLOR_TILE_ENABLE (1 << 16) +# define R300_COLOR_TILE(x) ((x) << 16) # define R300_COLOR_MICROTILE_DISABLE (0 << 17) # define R300_COLOR_MICROTILE_ENABLE (1 << 17) # define R300_COLOR_MICROTILE_ENABLE_SQUARE (2 << 17) /* Only available in 16-bit */ +# define R300_COLOR_MICROTILE(x) ((x) << 17) # define R300_COLOR_ENDIAN_NO_SWAP (0 << 19) # define R300_COLOR_ENDIAN_WORD_SWAP (1 << 19) # define R300_COLOR_ENDIAN_DWORD_SWAP (2 << 19) @@ -2544,9 +2548,11 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. # define R300_DEPTHPITCH_MASK 0x00003FFC # define R300_DEPTHMACROTILE_DISABLE (0 << 16) # define R300_DEPTHMACROTILE_ENABLE (1 << 16) +# define R300_DEPTHMACROTILE(x) ((x) << 16) # define R300_DEPTHMICROTILE_LINEAR (0 << 17) # define R300_DEPTHMICROTILE_TILED (1 << 17) # define R300_DEPTHMICROTILE_TILED_SQUARE (2 << 17) +# define R300_DEPTHMICROTILE(x) ((x) << 17) # define R300_DEPTHENDIAN_NO_SWAP (0 << 18) # define R300_DEPTHENDIAN_WORD_SWAP (1 << 18) # define R300_DEPTHENDIAN_DWORD_SWAP (2 << 18) diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index ee43421cdb..cd4971ae13 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -26,8 +26,9 @@ #include "draw/draw_context.h" #include "draw/draw_vbuf.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" +#include "util/u_format.h" #include "util/u_memory.h" #include "util/u_prim.h" @@ -114,6 +115,97 @@ static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300, return color_control; } +static boolean immd_is_good_idea(struct r300_context *r300, + unsigned count) +{ + return count <= 4; +} + +static void r300_emit_draw_arrays_immediate(struct r300_context *r300, + unsigned mode, + unsigned start, + unsigned count) +{ + struct pipe_vertex_element* velem; + struct pipe_vertex_buffer* vbuf; + unsigned vertex_element_count = r300->vertex_element_count; + unsigned i, v, vbi, dw, elem_offset; + + /* Size of the vertex, in dwords. */ + unsigned vertex_size = 0; + + /* Offsets of the attribute, in dwords, from the start of the vertex. */ + unsigned offset[PIPE_MAX_ATTRIBS]; + + /* Size of the vertex element, in dwords. */ + unsigned size[PIPE_MAX_ATTRIBS]; + + /* Stride to the same attrib in the next vertex in the vertex buffer, + * in dwords. */ + unsigned stride[PIPE_MAX_ATTRIBS] = {0}; + + /* Mapped vertex buffers. */ + uint32_t* map[PIPE_MAX_ATTRIBS] = {0}; + + CS_LOCALS(r300); + + /* Calculate the vertex size, offsets, strides etc. and map the buffers. */ + for (i = 0; i < vertex_element_count; i++) { + velem = &r300->vertex_element[i]; + offset[i] = velem->src_offset / 4; + size[i] = util_format_get_blocksize(velem->src_format) / 4; + vertex_size += size[i]; + vbi = velem->vertex_buffer_index; + + /* Map the buffer. */ + if (!map[vbi]) { + vbuf = &r300->vertex_buffer[vbi]; + map[vbi] = (uint32_t*)pipe_buffer_map(r300->context.screen, + vbuf->buffer, + PIPE_BUFFER_USAGE_CPU_READ); + map[vbi] += vbuf->buffer_offset / 4; + stride[vbi] = vbuf->stride / 4; + } + } + + r300_emit_dirty_state(r300); + + BEGIN_CS(10 + count * vertex_size); + OUT_CS_REG(R300_GA_COLOR_CONTROL, + r300_provoking_vertex_fixes(r300, mode)); + OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); + OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, 0); + OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1); + OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size); + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) | + r300_translate_primitive(mode)); + + /* Emit vertices. */ + for (v = 0; v < count; v++) { + for (i = 0; i < vertex_element_count; i++) { + velem = &r300->vertex_element[i]; + vbi = velem->vertex_buffer_index; + elem_offset = offset[i] + stride[vbi] * (v + start); + + for (dw = 0; dw < size[i]; dw++) { + OUT_CS(map[vbi][elem_offset + dw]); + } + } + } + END_CS; + + /* Unmap buffers. */ + for (i = 0; i < vertex_element_count; i++) { + vbi = r300->vertex_element[i].vertex_buffer_index; + + if (map[vbi]) { + vbuf = &r300->vertex_buffer[vbi]; + pipe_buffer_unmap(r300->context.screen, vbuf->buffer); + map[vbi] = NULL; + } + } +} + static void r300_emit_draw_arrays(struct r300_context *r300, unsigned mode, unsigned count) @@ -183,17 +275,18 @@ static void r300_emit_draw_elements(struct r300_context *r300, END_CS; } - static boolean r300_setup_vertex_buffers(struct r300_context *r300) { struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; struct pipe_vertex_element *velem = r300->vertex_element; + struct pipe_buffer *pbuf; validate: for (int i = 0; i < r300->vertex_element_count; i++) { - if (!r300->winsys->add_buffer(r300->winsys, - vbuf[velem[i].vertex_buffer_index].buffer, - RADEON_GEM_DOMAIN_GTT, 0)) { + pbuf = vbuf[velem[i].vertex_buffer_index].buffer; + + if (!r300->winsys->add_buffer(r300->winsys, pbuf, + RADEON_GEM_DOMAIN_GTT, 0)) { r300->context.flush(&r300->context, 0, NULL); goto validate; } @@ -207,17 +300,49 @@ validate: return TRUE; } +static void r300_shorten_ubyte_elts(struct r300_context* r300, + struct pipe_buffer** elts, + unsigned count) +{ + struct pipe_screen* screen = r300->context.screen; + struct pipe_buffer* new_elts; + unsigned char *in_map; + unsigned short *out_map; + unsigned i; + + new_elts = screen->buffer_create(screen, 32, + PIPE_BUFFER_USAGE_INDEX | + PIPE_BUFFER_USAGE_CPU_WRITE | + PIPE_BUFFER_USAGE_GPU_READ, + 2 * count); + + in_map = pipe_buffer_map(screen, *elts, PIPE_BUFFER_USAGE_CPU_READ); + out_map = pipe_buffer_map(screen, new_elts, PIPE_BUFFER_USAGE_CPU_WRITE); + + for (i = 0; i < count; i++) { + *out_map = (unsigned short)*in_map; + in_map++; + out_map++; + } + + pipe_buffer_unmap(screen, *elts); + pipe_buffer_unmap(screen, new_elts); + + *elts = new_elts; +} + /* This is the fast-path drawing & emission for HW TCL. */ void r300_draw_range_elements(struct pipe_context* pipe, - struct pipe_buffer* indexBuffer, - unsigned indexSize, - unsigned minIndex, - unsigned maxIndex, - unsigned mode, - unsigned start, - unsigned count) + struct pipe_buffer* indexBuffer, + unsigned indexSize, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count) { struct r300_context* r300 = r300_context(pipe); + struct pipe_buffer* orgIndexBuffer = indexBuffer; if (!u_trim_pipe_prim(mode, &count)) { return; @@ -232,17 +357,24 @@ void r300_draw_range_elements(struct pipe_context* pipe, r300_update_derived_state(r300); + r300_emit_buffer_validate(r300); + if (!r300_setup_vertex_buffers(r300)) { return; } + if (indexSize == 1) { + r300_shorten_ubyte_elts(r300, &indexBuffer, count); + indexSize = 2; + } + if (!r300->winsys->add_buffer(r300->winsys, indexBuffer, RADEON_GEM_DOMAIN_GTT, 0)) { - return; + goto cleanup; } if (!r300->winsys->validate(r300->winsys)) { - return; + goto cleanup; } r300_emit_dirty_state(r300); @@ -251,6 +383,11 @@ void r300_draw_range_elements(struct pipe_context* pipe, r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count); + +cleanup: + if (indexBuffer != orgIndexBuffer) { + pipe->screen->buffer_destroy(indexBuffer); + } } /* Simple helpers for context setup. Should probably be moved to util. */ @@ -264,7 +401,7 @@ void r300_draw_elements(struct pipe_context* pipe, } void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, - unsigned start, unsigned count) + unsigned start, unsigned count) { struct r300_context* r300 = r300_context(pipe); @@ -281,15 +418,19 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, r300_update_derived_state(r300); - if (!r300_setup_vertex_buffers(r300)) { - return; - } - - r300_emit_dirty_state(r300); + r300_emit_buffer_validate(r300); - r300_emit_aos(r300, start); + if (immd_is_good_idea(r300, count)) { + r300_emit_draw_arrays_immediate(r300, mode, start, count); + } else { + if (!r300_setup_vertex_buffers(r300)) { + return; + } - r300_emit_draw_arrays(r300, mode, count); + r300_emit_dirty_state(r300); + r300_emit_aos(r300, start); + r300_emit_draw_arrays(r300, mode, count); + } } /**************************************************************************** @@ -321,6 +462,7 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe, draw_set_mapped_constant_buffer(r300->draw, PIPE_SHADER_VERTEX, + 0, r300->shader_constants[PIPE_SHADER_VERTEX].constants, r300->shader_constants[PIPE_SHADER_VERTEX].count * (sizeof(float) * 4)); @@ -365,6 +507,7 @@ void r300_swtcl_draw_range_elements(struct pipe_context* pipe, draw_set_mapped_constant_buffer(r300->draw, PIPE_SHADER_VERTEX, + 0, r300->shader_constants[PIPE_SHADER_VERTEX].constants, r300->shader_constants[PIPE_SHADER_VERTEX].count * (sizeof(float) * 4)); @@ -416,7 +559,7 @@ r300_render_get_vertex_info(struct vbuf_render* render) r300_update_derived_state(r300); - return &r300->vertex_info->vinfo; + return (struct vertex_info*)r300->vertex_format_state.state; } static boolean r300_render_allocate_vertices(struct vbuf_render* render, diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 287664b1d2..da4ec542ad 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.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 "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_format.h" #include "util/u_memory.h" #include "util/u_simple_screen.h" @@ -30,6 +30,7 @@ #include "r300_texture.h" #include "radeon_winsys.h" +#include "r300_winsys.h" /* Return the identifier behind whom the brave coders responsible for this * amalgamation of code, sweat, and duct tape, routinely obscure their names. @@ -113,6 +114,8 @@ static int r300_get_param(struct pipe_screen* pscreen, int param) * ~ C. */ return 1; + case PIPE_CAP_DUAL_SOURCE_BLEND: + return 0; case PIPE_CAP_ANISOTROPIC_FILTER: return 1; case PIPE_CAP_POINT_SPRITE: @@ -149,6 +152,20 @@ static int r300_get_param(struct pipe_screen* pscreen, int param) } else { return 0; } + case PIPE_CAP_INDEP_BLEND_ENABLE: + if (r300screen->caps->is_r500) { + return 1; + } else { + return 0; + } + case PIPE_CAP_INDEP_BLEND_FUNC: + return 0; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 0; default: debug_printf("r300: Implementation error: Bad param %d\n", param); @@ -183,10 +200,20 @@ static float r300_get_paramf(struct pipe_screen* pscreen, int param) } } -static boolean check_tex_format(enum pipe_format format, uint32_t usage, - boolean is_r500) +static boolean r300_is_format_supported(struct pipe_screen* screen, + enum pipe_format format, + enum pipe_texture_target target, + unsigned usage, + unsigned geom_flags) { uint32_t retval = 0; + boolean is_r500 = r300_screen(screen)->caps->is_r500; + + if (target >= PIPE_MAX_TEXTURE_TYPES) { + debug_printf("r300: Implementation error: Received bogus texture " + "target %d in %s\n", target, __FUNCTION__); + return FALSE; + } switch (format) { /* Supported formats. */ @@ -194,6 +221,8 @@ static boolean check_tex_format(enum pipe_format format, uint32_t usage, case PIPE_FORMAT_A4R4G4B4_UNORM: case PIPE_FORMAT_R5G6B5_UNORM: case PIPE_FORMAT_A1R5G5B5_UNORM: + case PIPE_FORMAT_A8_UNORM: + case PIPE_FORMAT_L8_UNORM: retval = usage & (PIPE_TEXTURE_USAGE_RENDER_TARGET | PIPE_TEXTURE_USAGE_DISPLAY_TARGET | @@ -208,7 +237,8 @@ static boolean check_tex_format(enum pipe_format format, uint32_t usage, case PIPE_FORMAT_DXT3_RGBA: case PIPE_FORMAT_DXT5_RGBA: case PIPE_FORMAT_YCBCR: - case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_L8_SRGB: + case PIPE_FORMAT_A8L8_SRGB: case PIPE_FORMAT_A8L8_UNORM: retval = usage & PIPE_TEXTURE_USAGE_SAMPLER; break; @@ -247,28 +277,13 @@ static boolean check_tex_format(enum pipe_format format, uint32_t usage, case PIPE_FORMAT_Z32_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__); + SCREEN_DBG(r300_screen(screen), DBG_TEX, + "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: - case PIPE_FORMAT_A16R16G16B16: */ - /* XXX What the deuce is UV88? (r3xx accel page 14) - debug_printf("r300: Warning: Got unimplemented format: %s in %s\n", - pf_name(format), __FUNCTION__); - return FALSE; */ - - /* XXX Supported yet unimplemented r5xx formats: */ - /* XXX Again, what is UV1010 this time? (r5xx accel page 148) */ - /* XXX Even more that don't exist - case PIPE_FORMAT_A10R10G10B10_UNORM: - case PIPE_FORMAT_A2R10G10B10_UNORM: - case PIPE_FORMAT_I10_UNORM: - debug_printf( - "r300: Warning: Got unimplemented r500 format: %s in %s\n", - pf_name(format), __FUNCTION__); - return FALSE; */ + /* XXX Add all remaining gallium-supported formats, + * see util/u_format.csv. */ default: /* Unknown format... */ @@ -286,30 +301,6 @@ static boolean check_tex_format(enum pipe_format format, uint32_t usage, return (retval >= usage); } -static boolean r300_is_format_supported(struct pipe_screen* pscreen, - enum pipe_format format, - enum pipe_texture_target target, - unsigned tex_usage, - unsigned geom_flags) -{ - switch (target) { - case PIPE_TEXTURE_1D: /* handle 1D textures as 2D ones */ - case PIPE_TEXTURE_2D: - case PIPE_TEXTURE_3D: - case PIPE_TEXTURE_CUBE: - return check_tex_format(format, tex_usage, - r300_screen(pscreen)->caps->is_r500); - - default: - debug_printf("r300: Fatal: This is not a format target: %d\n", - target); - assert(0); - break; - } - - return FALSE; -} - static struct pipe_transfer* r300_get_tex_transfer(struct pipe_screen *screen, struct pipe_texture *texture, @@ -319,6 +310,7 @@ r300_get_tex_transfer(struct pipe_screen *screen, { struct r300_texture *tex = (struct r300_texture *)texture; struct r300_transfer *trans; + struct r300_screen *rscreen = r300_screen(screen); unsigned offset; offset = r300_texture_get_offset(tex, level, zslice, face); /* in bytes */ @@ -330,11 +322,8 @@ r300_get_tex_transfer(struct pipe_screen *screen, trans->transfer.y = y; trans->transfer.width = w; trans->transfer.height = h; - trans->transfer.stride = r300_texture_get_stride(tex, level); + trans->transfer.stride = r300_texture_get_stride(rscreen, tex, level); trans->transfer.usage = usage; - - /* XXX not sure whether it's required to set these two, - the driver doesn't use them */ trans->transfer.zslice = zslice; trans->transfer.face = face; @@ -389,16 +378,21 @@ struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys) struct r300_screen* r300screen = CALLOC_STRUCT(r300_screen); struct r300_capabilities* caps = CALLOC_STRUCT(r300_capabilities); - if (!r300screen || !caps) + if (!r300screen || !caps) { + FREE(r300screen); + FREE(caps); return NULL; + } caps->pci_id = radeon_winsys->pci_id; caps->num_frag_pipes = radeon_winsys->gb_pipes; caps->num_z_pipes = radeon_winsys->z_pipes; + r300_init_debug(r300screen); r300_parse_chipset(caps); r300screen->caps = caps; + r300screen->radeon_winsys = radeon_winsys; r300screen->screen.winsys = (struct pipe_winsys*)radeon_winsys; r300screen->screen.destroy = r300_destroy_screen; r300screen->screen.get_name = r300_get_name; @@ -406,6 +400,7 @@ struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys) r300screen->screen.get_param = r300_get_param; r300screen->screen.get_paramf = r300_get_paramf; r300screen->screen.is_format_supported = r300_is_format_supported; + r300screen->screen.context_create = r300_create_context; r300screen->screen.get_tex_transfer = r300_get_tex_transfer; r300screen->screen.tex_transfer_destroy = r300_tex_transfer_destroy; r300screen->screen.transfer_map = r300_transfer_map; diff --git a/src/gallium/drivers/r300/r300_screen.h b/src/gallium/drivers/r300/r300_screen.h index 2217988add..502fbfa5a2 100644 --- a/src/gallium/drivers/r300/r300_screen.h +++ b/src/gallium/drivers/r300/r300_screen.h @@ -33,8 +33,13 @@ struct r300_screen { /* Parent class */ struct pipe_screen screen; + struct radeon_winsys* radeon_winsys; + /* Chipset capabilities */ struct r300_capabilities* caps; + + /** Combination of DBG_xxx flags */ + unsigned debug; }; struct r300_transfer { @@ -57,7 +62,44 @@ r300_transfer(struct pipe_transfer* transfer) return (struct r300_transfer*)transfer; } -/* Creates a new r300 screen. */ -struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys); +/* Debug functionality. */ + +/** + * Debug flags to disable/enable certain groups of debugging outputs. + * + * \note These may be rather coarse, and the grouping may be impractical. + * If you find, while debugging the driver, that a different grouping + * of these flags would be beneficial, just feel free to change them + * but make sure to update the documentation in r300_debug.c to reflect + * those changes. + */ +/*@{*/ +#define DBG_HELP 0x0000001 +#define DBG_FP 0x0000002 +#define DBG_VP 0x0000004 +#define DBG_CS 0x0000008 +#define DBG_DRAW 0x0000010 +#define DBG_TEX 0x0000020 +#define DBG_FALL 0x0000040 +/*@}*/ + +static INLINE boolean SCREEN_DBG_ON(struct r300_screen * screen, unsigned flags) +{ + return (screen->debug & flags) ? TRUE : FALSE; +} + +static INLINE void SCREEN_DBG(struct r300_screen * screen, unsigned flags, + const char * fmt, ...) +{ + if (SCREEN_DBG_ON(screen, flags)) { + va_list va; + va_start(va, fmt); + debug_vprintf(fmt, va); + va_end(va); + } +} + +void r300_init_debug(struct r300_screen* ctx); #endif /* R300_SCREEN_H */ + diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 435e613ddf..d07e90860c 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -30,7 +30,6 @@ #include "tgsi/tgsi_parse.h" #include "pipe/p_config.h" -#include "pipe/internal/p_winsys_screen.h" #include "r300_context.h" #include "r300_reg.h" @@ -156,23 +155,33 @@ static boolean blend_discard_if_src_alpha_color_1(unsigned srcRGB, unsigned srcA dstA == PIPE_BLENDFACTOR_ONE); } +static unsigned bgra_cmask(unsigned mask) +{ + /* Gallium uses RGBA color ordering while R300 expects BGRA. */ + + return ((mask & PIPE_MASK_R) << 2) | + ((mask & PIPE_MASK_B) >> 2) | + (mask & (PIPE_MASK_G | PIPE_MASK_A)); +} + /* Create a new blend state based on the CSO blend state. * * This encompasses alpha blending, logic/raster ops, and blend dithering. */ static void* r300_create_blend_state(struct pipe_context* pipe, const struct pipe_blend_state* state) { + struct r300_screen* r300screen = r300_screen(pipe->screen); struct r300_blend_state* blend = CALLOC_STRUCT(r300_blend_state); - if (state->blend_enable) + if (state->rt[0].blend_enable) { - unsigned eqRGB = state->rgb_func; - unsigned srcRGB = state->rgb_src_factor; - unsigned dstRGB = state->rgb_dst_factor; + unsigned eqRGB = state->rt[0].rgb_func; + unsigned srcRGB = state->rt[0].rgb_src_factor; + unsigned dstRGB = state->rt[0].rgb_dst_factor; - unsigned eqA = state->alpha_func; - unsigned srcA = state->alpha_src_factor; - unsigned dstA = state->alpha_dst_factor; + unsigned eqA = state->rt[0].alpha_func; + unsigned srcA = state->rt[0].alpha_src_factor; + unsigned dstA = state->rt[0].alpha_dst_factor; /* despite the name, ALPHA_BLEND_ENABLE has nothing to do with alpha, * this is just the crappy D3D naming */ @@ -289,18 +298,18 @@ static void* r300_create_blend_state(struct pipe_context* pipe, (state->logicop_func) << R300_RB3D_ROPCNTL_ROP_SHIFT; } - /* Color Channel Mask */ - if (state->colormask & PIPE_MASK_R) { - blend->color_channel_mask |= RB3D_COLOR_CHANNEL_MASK_RED_MASK0; - } - if (state->colormask & PIPE_MASK_G) { - blend->color_channel_mask |= RB3D_COLOR_CHANNEL_MASK_GREEN_MASK0; - } - if (state->colormask & PIPE_MASK_B) { - blend->color_channel_mask |= RB3D_COLOR_CHANNEL_MASK_BLUE_MASK0; - } - if (state->colormask & PIPE_MASK_A) { - blend->color_channel_mask |= RB3D_COLOR_CHANNEL_MASK_ALPHA_MASK0; + /* Color channel masks for all MRTs. */ + blend->color_channel_mask = bgra_cmask(state->rt[0].colormask); + if (r300screen->caps->is_r500 && state->independent_blend_enable) { + if (state->rt[1].blend_enable) { + blend->color_channel_mask |= bgra_cmask(state->rt[1].colormask) << 4; + } + if (state->rt[2].blend_enable) { + blend->color_channel_mask |= bgra_cmask(state->rt[2].colormask) << 8; + } + if (state->rt[3].blend_enable) { + blend->color_channel_mask |= bgra_cmask(state->rt[3].colormask) << 12; + } } if (state->dither) { @@ -340,6 +349,7 @@ static void r300_set_blend_color(struct pipe_context* pipe, const struct pipe_blend_color* color) { struct r300_context* r300 = r300_context(pipe); + struct r300_screen* r300screen = r300_screen(pipe->screen); struct r300_blend_color_state* state = (struct r300_blend_color_state*)r300->blend_color_state.state; union util_color uc; @@ -355,6 +365,7 @@ static void r300_set_blend_color(struct pipe_context* pipe, float_to_fixed10(color->color[2]) | (float_to_fixed10(color->color[1]) << 16); + r300->blend_color_state.size = r300screen->caps->is_r500 ? 3 : 2; r300->blend_color_state.dirty = TRUE; } @@ -365,11 +376,14 @@ static void r300_set_clip_state(struct pipe_context* pipe, if (r300_screen(pipe->screen)->caps->has_tcl) { memcpy(r300->clip_state.state, state, sizeof(struct pipe_clip_state)); - r300->clip_state.dirty = TRUE; + r300->clip_state.size = 29; } else { draw_flush(r300->draw); draw_set_clip_state(r300->draw, state); + r300->clip_state.size = 2; } + + r300->clip_state.dirty = TRUE; } /* Create a new depth, stencil, and alpha state based on the CSO dsa state. @@ -427,7 +441,6 @@ static void* (r300_translate_stencil_op(state->stencil[1].zfail_op) << R300_S_BACK_ZFAIL_OP_SHIFT); - /* XXX it seems r3xx doesn't support STENCILREFMASK_BF */ if (caps->is_r500) { dsa->z_buffer_control |= R500_STENCIL_REFMASK_FRONT_BACK; @@ -446,8 +459,7 @@ static void* r300_translate_alpha_function(state->alpha.func) | R300_FG_ALPHA_FUNC_ENABLE; - /* XXX figure out why emitting 10bit alpha ref causes CS to dump */ - /* always use 8bit alpha ref */ + /* We could use 10bit alpha ref but who needs that? */ dsa->alpha_function |= float_to_ubyte(state->alpha.ref_value); if (caps->is_r500) @@ -462,8 +474,10 @@ static void r300_bind_dsa_state(struct pipe_context* pipe, void* state) { struct r300_context* r300 = r300_context(pipe); + struct r300_screen* r300screen = r300_screen(pipe->screen); r300->dsa_state.state = state; + r300->dsa_state.size = r300screen->caps->is_r500 ? 8 : 6; r300->dsa_state.dirty = TRUE; } @@ -474,56 +488,52 @@ static void r300_delete_dsa_state(struct pipe_context* pipe, FREE(state); } -static void r300_set_scissor_regs(const struct pipe_scissor_state* state, - struct r300_scissor_regs *scissor, - boolean is_r500) -{ - if (is_r500) { - scissor->top_left = - (state->minx << R300_SCISSORS_X_SHIFT) | - (state->miny << R300_SCISSORS_Y_SHIFT); - scissor->bottom_right = - ((state->maxx - 1) << R300_SCISSORS_X_SHIFT) | - ((state->maxy - 1) << R300_SCISSORS_Y_SHIFT); - } else { - /* Offset of 1440 in non-R500 chipsets. */ - scissor->top_left = - ((state->minx + 1440) << R300_SCISSORS_X_SHIFT) | - ((state->miny + 1440) << R300_SCISSORS_Y_SHIFT); - scissor->bottom_right = - (((state->maxx - 1) + 1440) << R300_SCISSORS_X_SHIFT) | - (((state->maxy - 1) + 1440) << R300_SCISSORS_Y_SHIFT); - } -} - static void r300_set_framebuffer_state(struct pipe_context* pipe, const struct pipe_framebuffer_state* state) { struct r300_context* r300 = r300_context(pipe); - struct r300_scissor_state* scissor = - (struct r300_scissor_state*)r300->scissor_state.state; - struct pipe_scissor_state pscissor; + uint32_t zbuffer_bpp = 0; + + r300->fb_state.size = (10 * state->nr_cbufs) + + (2 * (4 - state->nr_cbufs)) + + (state->zsbuf ? 10 : 0) + 6; + + if (state->nr_cbufs > 4) { + debug_printf("r300: Implementation error: Too many MRTs in %s, " + "refusing to bind framebuffer state!\n", __FUNCTION__); + return; + } if (r300->draw) { draw_flush(r300->draw); } - r300->framebuffer_state = *state; - - /* XXX Arg. This is silly. */ - pscissor.minx = pscissor.miny = 0; - pscissor.maxx = state->width; - pscissor.maxy = state->height; - r300_set_scissor_regs(&pscissor, &scissor->framebuffer, - r300_screen(r300->context.screen)->caps->is_r500); + memcpy(r300->fb_state.state, state, sizeof(struct pipe_framebuffer_state)); /* Don't rely on the order of states being set for the first time. */ - r300->dirty_state |= R300_NEW_FRAMEBUFFERS; - + /* XXX wait what */ r300->blend_state.dirty = TRUE; r300->dsa_state.dirty = TRUE; + r300->fb_state.dirty = TRUE; r300->scissor_state.dirty = TRUE; + + /* Polygon offset depends on the zbuffer bit depth. */ + if (state->zsbuf && r300->polygon_offset_enabled) { + switch (util_format_get_blocksize(state->zsbuf->texture->format)) { + case 2: + zbuffer_bpp = 16; + break; + case 4: + zbuffer_bpp = 24; + break; + } + + if (r300->zbuffer_bpp != zbuffer_bpp) { + r300->zbuffer_bpp = zbuffer_bpp; + r300->rs_state.dirty = TRUE; + } + } } /* Create fragment shader state. */ @@ -559,7 +569,7 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) r300_pick_fragment_shader(r300); if (r300->vs && r300_vertex_shader_setup_wpos(r300)) { - r300->dirty_state |= R300_NEW_VERTEX_FORMAT; + r300->vertex_format_state.dirty = TRUE; } r300->dirty_state |= R300_NEW_FRAGMENT_SHADER | R300_NEW_FRAGMENT_SHADER_CONSTANTS; @@ -629,9 +639,6 @@ static void* r300_create_rs_state(struct pipe_context* pipe, rs->line_control = pack_float_16_6x(state->line_width) | R300_GA_LINE_CNTL_END_TYPE_COMP; - /* XXX I think there is something wrong with the polygon mode, - * XXX re-test when r300g is in a better shape */ - /* Enable polygon mode */ if (state->fill_cw != PIPE_POLYGON_MODE_FILL || state->fill_ccw != PIPE_POLYGON_MODE_FILL) { @@ -684,10 +691,8 @@ static void* r300_create_rs_state(struct pipe_context* pipe, } if (rs->polygon_offset_enable) { - rs->depth_offset_front = rs->depth_offset_back = - fui(state->offset_units); - rs->depth_scale_front = rs->depth_scale_back = - fui(state->offset_scale); + rs->depth_offset = state->offset_units; + rs->depth_scale = state->offset_scale; } if (state->line_stipple_enable) { @@ -719,7 +724,13 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) draw_set_rasterizer_state(r300->draw, &rs->rs); } - r300->tcl_bypass = rs->rs.bypass_vs_clip_and_viewport; + if (rs) { + r300->tcl_bypass = rs->rs.bypass_vs_clip_and_viewport; + r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw; + } else { + r300->tcl_bypass = FALSE; + r300->polygon_offset_enabled = FALSE; + } r300->rs_state.state = rs; r300->rs_state.dirty = TRUE; @@ -728,7 +739,6 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) r300->viewport_state.dirty = TRUE; /* XXX Clean these up when we move to atom emits */ - r300->dirty_state |= R300_NEW_RS_BLOCK; if (r300->fs && r300->fs->inputs.wpos != ATTR_UNUSED) { r300->dirty_state |= R300_NEW_FRAGMENT_SHADER_CONSTANTS; } @@ -866,11 +876,9 @@ static void r300_set_scissor_state(struct pipe_context* pipe, const struct pipe_scissor_state* state) { struct r300_context* r300 = r300_context(pipe); - struct r300_scissor_state* scissor = - (struct r300_scissor_state*)r300->scissor_state.state; - r300_set_scissor_regs(state, &scissor->scissor, - r300_screen(r300->context.screen)->caps->is_r500); + memcpy(r300->scissor_state.state, state, + sizeof(struct pipe_scissor_state)); r300->scissor_state.dirty = TRUE; } @@ -931,7 +939,23 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, draw_set_vertex_buffers(r300->draw, count, buffers); } - r300->dirty_state |= R300_NEW_VERTEX_FORMAT; + r300->vertex_format_state.dirty = TRUE; +} + +static boolean r300_validate_aos(struct r300_context *r300) +{ + struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; + struct pipe_vertex_element *velem = r300->vertex_element; + int i; + + /* Check if formats and strides are aligned to the size of DWORD. */ + for (i = 0; i < r300->vertex_element_count; i++) { + if (vbuf[velem[i].vertex_buffer_index].stride % 4 != 0 || + util_format_get_blocksize(velem[i].src_format) % 4 != 0) { + return FALSE; + } + } + return TRUE; } static void r300_set_vertex_elements(struct pipe_context* pipe, @@ -949,6 +973,12 @@ static void r300_set_vertex_elements(struct pipe_context* pipe, draw_flush(r300->draw); draw_set_vertex_elements(r300->draw, count, elements); } + + if (!r300_validate_aos(r300)) { + /* XXX We should fallback using draw. */ + assert(0); + abort(); + } } static void* r300_create_vs_state(struct pipe_context* pipe, @@ -989,9 +1019,10 @@ static void r300_bind_vs_state(struct pipe_context* pipe, void* shader) r300_vertex_shader_setup_wpos(r300); } + r300->vertex_format_state.dirty = TRUE; + r300->dirty_state |= - R300_NEW_VERTEX_SHADER | R300_NEW_VERTEX_SHADER_CONSTANTS | - R300_NEW_VERTEX_FORMAT; + R300_NEW_VERTEX_SHADER | R300_NEW_VERTEX_SHADER_CONSTANTS; } else { draw_flush(r300->draw); draw_bind_vertex_shader(r300->draw, @@ -1017,22 +1048,22 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader) static void r300_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - const struct pipe_constant_buffer *buf) + struct pipe_buffer *buf) { struct r300_context* r300 = r300_context(pipe); void *mapped; - if (buf == NULL || buf->buffer->size == 0 || - (mapped = pipe_buffer_map(pipe->screen, buf->buffer, PIPE_BUFFER_USAGE_CPU_READ)) == NULL) + if (buf == NULL || buf->size == 0 || + (mapped = pipe_buffer_map(pipe->screen, buf, PIPE_BUFFER_USAGE_CPU_READ)) == NULL) { r300->shader_constants[shader].count = 0; return; } - assert((buf->buffer->size % 4 * sizeof(float)) == 0); - memcpy(r300->shader_constants[shader].constants, mapped, buf->buffer->size); - r300->shader_constants[shader].count = buf->buffer->size / (4 * sizeof(float)); - pipe_buffer_unmap(pipe->screen, buf->buffer); + assert((buf->size % 4 * sizeof(float)) == 0); + memcpy(r300->shader_constants[shader].constants, mapped, buf->size); + r300->shader_constants[shader].count = buf->size / (4 * sizeof(float)); + pipe_buffer_unmap(pipe->screen, buf); if (shader == PIPE_SHADER_VERTEX) r300->dirty_state |= R300_NEW_VERTEX_SHADER_CONSTANTS; diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 192846411b..bad9e76067 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -37,32 +37,6 @@ /* r300_state_derived: Various bits of state which are dependent upon * currently bound CSO data. */ -struct r300_shader_key { - struct r300_vertex_shader* vs; - struct r300_fragment_shader* fs; -}; - -struct r300_shader_derived_value { - struct r300_vertex_format* vformat; - struct r300_rs_block* rs_block; -}; - -unsigned r300_shader_key_hash(void* key) { - struct r300_shader_key* shader_key = (struct r300_shader_key*)key; - unsigned vs = (intptr_t)shader_key->vs; - unsigned fs = (intptr_t)shader_key->fs; - - return (vs << 16) | (fs & 0xffff); -} - -int r300_shader_key_compare(void* key1, void* key2) { - struct r300_shader_key* shader_key1 = (struct r300_shader_key*)key1; - struct r300_shader_key* shader_key2 = (struct r300_shader_key*)key2; - - return (shader_key1->vs == shader_key2->vs) && - (shader_key1->fs == shader_key2->fs); -} - static void r300_draw_emit_attrib(struct r300_context* r300, enum attrib_emit emit, enum interp_mode interp, @@ -74,7 +48,9 @@ static void r300_draw_emit_attrib(struct r300_context* r300, output = draw_find_shader_output(r300->draw, info->output_semantic_name[index], info->output_semantic_index[index]); - draw_emit_vertex_attr(&r300->vertex_info->vinfo, emit, interp, output); + draw_emit_vertex_attr( + (struct vertex_info*)r300->vertex_format_state.state, + emit, interp, output); } static void r300_draw_emit_all_attribs(struct r300_context* r300) @@ -130,7 +106,8 @@ static void r300_draw_emit_all_attribs(struct r300_context* r300) /* Update the PSC tables. */ static void r300_vertex_psc(struct r300_context* r300) { - struct r300_vertex_info *vformat = r300->vertex_info; + struct r300_vertex_info *vformat = + (struct r300_vertex_info*)r300->vertex_format_state.state; uint16_t type, swizzle; enum pipe_format format; unsigned i; @@ -182,7 +159,8 @@ static void r300_vertex_psc(struct r300_context* r300) /* Update the PSC tables for SW TCL, using Draw. */ static void r300_swtcl_vertex_psc(struct r300_context* r300) { - struct r300_vertex_info *vformat = r300->vertex_info; + struct r300_vertex_info *vformat = + (struct r300_vertex_info*)r300->vertex_format_state.state; struct vertex_info* vinfo = &vformat->vinfo; uint16_t type, swizzle; enum pipe_format format; @@ -327,7 +305,7 @@ static void r300_update_rs_block(struct r300_context* r300, struct r300_shader_semantics* vs_outputs, struct r300_shader_semantics* fs_inputs) { - struct r300_rs_block* rs = r300->rs_block; + struct r300_rs_block rs = { { 0 } }; int i, col_count = 0, tex_count = 0, fp_offset = 0; void (*rX00_rs_col)(struct r300_rs_block*, int, int, boolean); void (*rX00_rs_col_write)(struct r300_rs_block*, int, int); @@ -350,14 +328,15 @@ static void r300_update_rs_block(struct r300_context* r300, /* Rasterize colors. */ for (i = 0; i < ATTR_COLOR_COUNT; i++) { - if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used) { + if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used || + vs_outputs->color[1] != ATTR_UNUSED) { /* Always rasterize if it's written by the VS, * otherwise it locks up. */ - rX00_rs_col(rs, col_count, i, FALSE); + rX00_rs_col(&rs, col_count, i, FALSE); /* Write it to the FS input register if it's used by the FS. */ if (fs_inputs->color[i] != ATTR_UNUSED) { - rX00_rs_col_write(rs, col_count, fp_offset); + rX00_rs_col_write(&rs, col_count, fp_offset); fp_offset++; } col_count++; @@ -375,11 +354,11 @@ static void r300_update_rs_block(struct r300_context* r300, if (vs_outputs->generic[i] != ATTR_UNUSED) { /* Always rasterize if it's written by the VS, * otherwise it locks up. */ - rX00_rs_tex(rs, tex_count, tex_count, FALSE); + rX00_rs_tex(&rs, tex_count, tex_count, FALSE); /* Write it to the FS input register if it's used by the FS. */ if (fs_inputs->generic[i] != ATTR_UNUSED) { - rX00_rs_tex_write(rs, tex_count, fp_offset); + rX00_rs_tex_write(&rs, tex_count, fp_offset); fp_offset++; } tex_count++; @@ -396,11 +375,11 @@ static void r300_update_rs_block(struct r300_context* r300, if (vs_outputs->fog != ATTR_UNUSED) { /* Always rasterize if it's written by the VS, * otherwise it locks up. */ - rX00_rs_tex(rs, tex_count, tex_count, TRUE); + rX00_rs_tex(&rs, tex_count, tex_count, TRUE); /* Write it to the FS input register if it's used by the FS. */ if (fs_inputs->fog != ATTR_UNUSED) { - rX00_rs_tex_write(rs, tex_count, fp_offset); + rX00_rs_tex_write(&rs, tex_count, fp_offset); fp_offset++; } tex_count++; @@ -415,8 +394,8 @@ static void r300_update_rs_block(struct r300_context* r300, /* Rasterize WPOS. */ /* If the FS doesn't need it, it's not written by the VS. */ if (fs_inputs->wpos != ATTR_UNUSED) { - rX00_rs_tex(rs, tex_count, tex_count, FALSE); - rX00_rs_tex_write(rs, tex_count, fp_offset); + rX00_rs_tex(&rs, tex_count, tex_count, FALSE); + rX00_rs_tex_write(&rs, tex_count, fp_offset); fp_offset++; tex_count++; @@ -424,51 +403,33 @@ static void r300_update_rs_block(struct r300_context* r300, /* Rasterize at least one color, or bad things happen. */ if (col_count == 0 && tex_count == 0) { - rX00_rs_col(rs, 0, 0, TRUE); + rX00_rs_col(&rs, 0, 0, TRUE); col_count++; } - rs->count = (tex_count*4) | (col_count << R300_IC_COUNT_SHIFT) | + rs.count = (tex_count*4) | (col_count << R300_IC_COUNT_SHIFT) | R300_HIRES_EN; - rs->inst_count = MAX3(col_count - 1, tex_count - 1, 0); + rs.inst_count = MAX3(col_count - 1, tex_count - 1, 0); + + /* Now, after all that, see if we actually need to update the state. */ + if (memcmp(r300->rs_block_state.state, &rs, sizeof(struct r300_rs_block))) { + memcpy(r300->rs_block_state.state, &rs, sizeof(struct r300_rs_block)); + r300->rs_block_state.dirty = TRUE; + } } -/* Update the vertex format. */ +/* Update the shader-dependant states. */ static void r300_update_derived_shader_state(struct r300_context* r300) { struct r300_screen* r300screen = r300_screen(r300->context.screen); + struct r300_vertex_info *vformat = + (struct r300_vertex_info*)r300->vertex_format_state.state; + struct vertex_info* vinfo = &vformat->vinfo; - /* - struct r300_shader_key* key; - struct r300_shader_derived_value* value; - key = CALLOC_STRUCT(r300_shader_key); - key->vs = r300->vs; - key->fs = r300->fs; - - value = (struct r300_shader_derived_value*) - util_hash_table_get(r300->shader_hash_table, (void*)key); - if (value) { - //vformat = value->vformat; - rs_block = value->rs_block; - - FREE(key); - } else { - rs_block = CALLOC_STRUCT(r300_rs_block); - value = CALLOC_STRUCT(r300_shader_derived_value); - - r300_update_rs_block(r300, rs_block); - - //value->vformat = vformat; - value->rs_block = rs_block; - util_hash_table_set(r300->shader_hash_table, - (void*)key, (void*)value); - } */ - - /* Reset structures */ - memset(r300->rs_block, 0, sizeof(struct r300_rs_block)); - memset(r300->vertex_info, 0, sizeof(struct r300_vertex_info)); - memcpy(r300->vertex_info->vinfo.hwfmt, r300->vs->hwfmt, sizeof(uint)*4); + /* Mmm, delicious hax */ + memset(r300->vertex_format_state.state, 0, sizeof(struct r300_vertex_info)); + memcpy(vinfo->hwfmt, r300->vs->hwfmt, sizeof(uint)*4); r300_update_rs_block(r300, &r300->vs->outputs, &r300->fs->inputs); @@ -476,11 +437,10 @@ static void r300_update_derived_shader_state(struct r300_context* r300) r300_vertex_psc(r300); } else { r300_draw_emit_all_attribs(r300); - draw_compute_vertex_size(&r300->vertex_info->vinfo); + draw_compute_vertex_size( + (struct vertex_info*)r300->vertex_format_state.state); r300_swtcl_vertex_psc(r300); } - - r300->dirty_state |= R300_NEW_RS_BLOCK; } static boolean r300_dsa_writes_depth_stencil(struct r300_dsa_state* dsa) @@ -558,8 +518,8 @@ void r300_update_derived_state(struct r300_context* r300) { /* XXX */ if (r300->dirty_state & - (R300_NEW_FRAGMENT_SHADER | R300_NEW_VERTEX_SHADER | - R300_NEW_VERTEX_FORMAT) || r300->rs_state.dirty) { + (R300_NEW_FRAGMENT_SHADER | R300_NEW_VERTEX_SHADER) || + r300->vertex_format_state.dirty || r300->rs_state.dirty) { r300_update_derived_shader_state(r300); } diff --git a/src/gallium/drivers/r300/r300_state_inlines.h b/src/gallium/drivers/r300/r300_state_inlines.h index 35be00e1b0..5df6815221 100644 --- a/src/gallium/drivers/r300/r300_state_inlines.h +++ b/src/gallium/drivers/r300/r300_state_inlines.h @@ -81,9 +81,6 @@ static INLINE uint32_t r300_translate_blend_factor(int blend_fact) return R300_BLEND_GL_CONST_COLOR; case PIPE_BLENDFACTOR_CONST_ALPHA: return R300_BLEND_GL_CONST_ALPHA; - /* XXX WTF are these? - case PIPE_BLENDFACTOR_SRC1_COLOR: - case PIPE_BLENDFACTOR_SRC1_ALPHA: */ case PIPE_BLENDFACTOR_ZERO: return R300_BLEND_GL_ZERO; case PIPE_BLENDFACTOR_INV_SRC_COLOR: @@ -98,9 +95,16 @@ static INLINE uint32_t r300_translate_blend_factor(int blend_fact) return R300_BLEND_GL_ONE_MINUS_CONST_COLOR; case PIPE_BLENDFACTOR_INV_CONST_ALPHA: return R300_BLEND_GL_ONE_MINUS_CONST_ALPHA; - /* XXX see above + + case PIPE_BLENDFACTOR_SRC1_COLOR: + case PIPE_BLENDFACTOR_SRC1_ALPHA: case PIPE_BLENDFACTOR_INV_SRC1_COLOR: - case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: */ + case PIPE_BLENDFACTOR_INV_SRC1_ALPHA: + debug_printf("r300: Implementation error: " + "Bad blend factor %d not supported!\n", blend_fact); + assert(0); + break; + default: debug_printf("r300: Unknown blend factor %d\n", blend_fact); assert(0); @@ -331,7 +335,10 @@ static INLINE uint32_t r300_translate_colorformat(enum pipe_format format) { switch (format) { /* 8-bit buffers */ + case PIPE_FORMAT_A8_UNORM: case PIPE_FORMAT_I8_UNORM: + case PIPE_FORMAT_L8_UNORM: + /* case PIPE_FORMAT_S8_UNORM: ??? */ return R300_COLOR_FORMAT_I8; /* 16-bit buffers */ case PIPE_FORMAT_R5G6B5_UNORM: @@ -408,6 +415,16 @@ static INLINE uint32_t r300_translate_out_fmt(enum pipe_format format) return R300_US_OUT_FMT_C4_8 | R300_C0_SEL_A | R300_C1_SEL_B | R300_C2_SEL_G | R300_C3_SEL_R; + + /* 8-bit outputs */ + case PIPE_FORMAT_A8_UNORM: + return R300_US_OUT_FMT_C4_8 | + R300_C0_SEL_A; + case PIPE_FORMAT_I8_UNORM: + case PIPE_FORMAT_L8_UNORM: + return R300_US_OUT_FMT_C4_8 | + R300_C0_SEL_R; + /* R300_OUT_SIGN(x) */ default: debug_printf("r300: Implementation error: " "Got unsupported output format %s in %s\n", @@ -537,6 +554,7 @@ r300_translate_vertex_data_type(enum pipe_format format) { static INLINE uint16_t r300_translate_vertex_data_swizzle(enum pipe_format format) { const struct util_format_description *desc = util_format_description(format); + unsigned swizzle[4], i; assert(format); @@ -547,11 +565,26 @@ r300_translate_vertex_data_swizzle(enum pipe_format format) { return 0; } - return ((desc->swizzle[0] << R300_SWIZZLE_SELECT_X_SHIFT) | - (desc->swizzle[1] << R300_SWIZZLE_SELECT_Y_SHIFT) | - (desc->swizzle[2] << R300_SWIZZLE_SELECT_Z_SHIFT) | - (desc->swizzle[3] << R300_SWIZZLE_SELECT_W_SHIFT) | - (0xf << R300_WRITE_ENA_SHIFT)); + /* Swizzles for 8bits formats are in the reversed order, not sure why. */ + if (desc->channel[0].size == 8) { + for (i = 0; i < 4; i++) { + if (desc->swizzle[i] <= 3) { + swizzle[i] = 3 - desc->swizzle[i]; + } else { + swizzle[i] = desc->swizzle[i]; + } + } + } else { + for (i = 0; i < 4; i++) { + swizzle[i] = desc->swizzle[i]; + } + } + + return ((swizzle[0] << R300_SWIZZLE_SELECT_X_SHIFT) | + (swizzle[1] << R300_SWIZZLE_SELECT_Y_SHIFT) | + (swizzle[2] << R300_SWIZZLE_SELECT_Z_SHIFT) | + (swizzle[3] << R300_SWIZZLE_SELECT_W_SHIFT) | + (0xf << R300_WRITE_ENA_SHIFT)); } #endif /* R300_STATE_INLINES_H */ diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c index f25f3ca217..97927acf1b 100644 --- a/src/gallium/drivers/r300/r300_state_invariant.c +++ b/src/gallium/drivers/r300/r300_state_invariant.c @@ -38,12 +38,12 @@ struct pipe_viewport_state r300_viewport_identity = { * * Note that eventually this should be empty, but it's useful for development * and general unduplication of code. */ -void r300_emit_invariant_state(struct r300_context* r300) +void r300_emit_invariant_state(struct r300_context* r300, void* state) { struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps; CS_LOCALS(r300); - BEGIN_CS(16 + (caps->has_tcl ? 2: 0)); + BEGIN_CS(14 + (caps->has_tcl ? 2: 0)); /*** Graphics Backend (GB) ***/ /* Various GB enables */ @@ -58,8 +58,6 @@ void r300_emit_invariant_state(struct r300_context* r300) */ /* 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); /*** Fog (FG) ***/ OUT_CS_REG(R300_FG_FOG_BLEND, 0x0); @@ -79,7 +77,8 @@ void r300_emit_invariant_state(struct r300_context* r300) END_CS; /* XXX unsorted stuff from surface_fill */ - BEGIN_CS(44 + (caps->has_tcl ? 7 : 0) + (caps->is_r500 ? 4 : 0)); + BEGIN_CS(44 + (caps->has_tcl ? 7 : 0) + + (caps->family >= CHIP_FAMILY_RV350 ? 4 : 0)); if (caps->has_tcl) { /*Flushing PVS is required before the VAP_GB registers can be changed*/ @@ -115,10 +114,12 @@ void r300_emit_invariant_state(struct r300_context* r300) OUT_CS_REG(R300_SC_HYPERZ, 0x0000001C); OUT_CS_REG(R300_SC_EDGERULE, 0x2DA49525); OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, 0x00000000); - if (caps->is_r500) { + + if (caps->family >= CHIP_FAMILY_RV350) { OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x01010101); OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFEFEFEFE); } + OUT_CS_REG(R300_ZB_BW_CNTL, 0x00000000); OUT_CS_REG(R300_ZB_DEPTHCLEARVALUE, 0x00000000); OUT_CS_REG(R300_ZB_HIZ_OFFSET, 0x00000000); diff --git a/src/gallium/drivers/r300/r300_state_invariant.h b/src/gallium/drivers/r300/r300_state_invariant.h index 05cff0d6df..5d1a963654 100644 --- a/src/gallium/drivers/r300/r300_state_invariant.h +++ b/src/gallium/drivers/r300/r300_state_invariant.h @@ -25,6 +25,6 @@ struct r300_context; -void r300_emit_invariant_state(struct r300_context* r300); +void r300_emit_invariant_state(struct r300_context* r300, void* state); #endif /* R300_STATE_INVARIANT_H */ diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 9a96206a4d..67bf8ce13f 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -30,10 +30,25 @@ #include "r300_texture.h" #include "r300_screen.h" -static void r300_setup_texture_state(struct r300_texture* tex, boolean is_r500) +#include "radeon_winsys.h" + +#define TILE_WIDTH 0 +#define TILE_HEIGHT 1 + +static const unsigned microblock_table[5][3][2] = { + /*linear tiled square-tiled */ + {{32, 1}, {8, 4}, {0, 0}}, /* 8 bits per pixel */ + {{16, 1}, {8, 2}, {4, 4}}, /* 16 bits per pixel */ + {{ 8, 1}, {4, 2}, {0, 0}}, /* 32 bits per pixel */ + {{ 4, 1}, {0, 0}, {2, 2}}, /* 64 bits per pixel */ + {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */ +}; + +static void r300_setup_texture_state(struct r300_screen* screen, struct r300_texture* tex) { struct r300_texture_state* state = &tex->state; struct pipe_texture *pt = &tex->tex; + boolean is_r500 = screen->caps->is_r500; state->format0 = R300_TX_WIDTH((pt->width0 - 1) & 0x7ff) | R300_TX_HEIGHT((pt->height0 - 1) & 0x7ff); @@ -67,8 +82,8 @@ static void r300_setup_texture_state(struct r300_texture* tex, boolean is_r500) } assert(is_r500 || (pt->width0 <= 2048 && pt->height0 <= 2048)); - debug_printf("r300: Set texture state (%dx%d, %d levels)\n", - pt->width0, pt->height0, pt->last_level); + SCREEN_DBG(screen, DBG_TEX, "r300: Set texture state (%dx%d, %d levels)\n", + pt->width0, pt->height0, pt->last_level); } unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, @@ -92,33 +107,78 @@ unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, } /** + * Return the width (dim==TILE_WIDTH) or height (dim==TILE_HEIGHT) of one tile + * of the given texture. + */ +static unsigned r300_texture_get_tile_size(struct r300_texture* tex, int dim) +{ + unsigned pixsize, tile_size; + + pixsize = util_format_get_blocksize(tex->tex.format); + tile_size = microblock_table[util_logbase2(pixsize)][tex->microtile][dim] * + (tex->macrotile == R300_BUFFER_TILED ? 8 : 1); + + assert(tile_size); + return tile_size; +} + +/** * Return the stride, in bytes, of the texture images of the given texture * at the given level. */ -unsigned r300_texture_get_stride(struct r300_texture* tex, unsigned level) +unsigned r300_texture_get_stride(struct r300_screen* screen, + struct r300_texture* tex, unsigned level) { + unsigned tile_width, width; + if (tex->stride_override) return tex->stride_override; + /* Check the level. */ if (level > tex->tex.last_level) { - debug_printf("%s: level (%u) > last_level (%u)\n", __FUNCTION__, - level, tex->tex.last_level); + SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n", + __FUNCTION__, level, tex->tex.last_level); return 0; } - return align(util_format_get_stride(tex->tex.format, u_minify(tex->tex.width0, level)), 32); + width = u_minify(tex->tex.width0, level); + + if (!util_format_is_compressed(tex->tex.format)) { + tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH); + width = align(width, tile_width); + return util_format_get_stride(tex->tex.format, width); + } else { + return align(util_format_get_stride(tex->tex.format, width), 32); + } } -static void r300_setup_miptree(struct r300_texture* tex) +static unsigned r300_texture_get_nblocksy(struct r300_texture* tex, + unsigned level) +{ + unsigned height, tile_height; + + height = u_minify(tex->tex.height0, level); + + if (!util_format_is_compressed(tex->tex.format)) { + tile_height = r300_texture_get_tile_size(tex, TILE_HEIGHT); + height = align(height, tile_height); + } + + return util_format_get_nblocksy(tex->tex.format, height); +} + +static void r300_setup_miptree(struct r300_screen* screen, + struct r300_texture* tex) { struct pipe_texture* base = &tex->tex; - int stride, size, layer_size; - int i; + unsigned stride, size, layer_size, nblocksy, i; - for (i = 0; i <= base->last_level; i++) { - unsigned nblocksy = util_format_get_nblocksy(base->format, u_minify(base->height0, i)); + SCREEN_DBG(screen, DBG_TEX, "r300: Making miptree for texture, format %s\n", + pf_name(base->format)); - stride = r300_texture_get_stride(tex, i); + for (i = 0; i <= base->last_level; i++) { + stride = r300_texture_get_stride(screen, tex, i); + nblocksy = r300_texture_get_nblocksy(tex, i); layer_size = stride * nblocksy; if (base->target == PIPE_TEXTURE_CUBE) @@ -131,10 +191,10 @@ static void r300_setup_miptree(struct r300_texture* tex) tex->layer_size[i] = layer_size; tex->pitch[i] = stride / util_format_get_blocksize(base->format); - debug_printf("r300: Texture miptree: Level %d " - "(%dx%dx%d px, pitch %d bytes)\n", + SCREEN_DBG(screen, DBG_TEX, "r300: Texture miptree: Level %d " + "(%dx%dx%d px, pitch %d bytes) %d bytes total\n", i, u_minify(base->width0, i), u_minify(base->height0, i), - u_minify(base->depth0, i), stride); + u_minify(base->depth0, i), stride, tex->size); } } @@ -150,6 +210,8 @@ static struct pipe_texture* const struct pipe_texture* template) { struct r300_texture* tex = CALLOC_STRUCT(r300_texture); + struct r300_screen* rscreen = r300_screen(screen); + struct radeon_winsys* winsys = (struct radeon_winsys*)screen->winsys; if (!tex) { return NULL; @@ -160,12 +222,16 @@ static struct pipe_texture* tex->tex.screen = screen; r300_setup_flags(tex); - r300_setup_miptree(tex); - r300_setup_texture_state(tex, r300_screen(screen)->caps->is_r500); + r300_setup_miptree(rscreen, tex); + r300_setup_texture_state(rscreen, tex); - tex->buffer = screen->buffer_create(screen, 1024, + tex->buffer = screen->buffer_create(screen, 2048, PIPE_BUFFER_USAGE_PIXEL, tex->size); + winsys->buffer_set_tiling(winsys, tex->buffer, + tex->pitch[0], + tex->microtile != R300_BUFFER_LINEAR, + tex->macrotile != R300_BUFFER_LINEAR); if (!tex->buffer) { FREE(tex); @@ -227,6 +293,7 @@ static struct pipe_texture* struct pipe_buffer* buffer) { struct r300_texture* tex; + struct r300_screen* rscreen = r300_screen(screen); /* Support only 2D textures without mipmaps */ if (base->target != PIPE_TEXTURE_2D || @@ -248,7 +315,7 @@ static struct pipe_texture* tex->pitch[0] = *stride / util_format_get_blocksize(base->format); r300_setup_flags(tex); - r300_setup_texture_state(tex, r300_screen(screen)->caps->is_r500); + r300_setup_texture_state(rscreen, tex); pipe_buffer_reference(&tex->buffer, buffer); @@ -315,7 +382,8 @@ void r300_init_screen_texture_functions(struct pipe_screen* screen) screen->video_surface_destroy= r300_video_surface_destroy; } -boolean r300_get_texture_buffer(struct pipe_texture* texture, +boolean r300_get_texture_buffer(struct pipe_screen* screen, + struct pipe_texture* texture, struct pipe_buffer** buffer, unsigned* stride) { @@ -327,7 +395,7 @@ boolean r300_get_texture_buffer(struct pipe_texture* texture, pipe_buffer_reference(buffer, tex->buffer); if (stride) { - *stride = r300_texture_get_stride(tex, 0); + *stride = r300_texture_get_stride(r300_screen(screen), tex, 0); } return TRUE; diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h index 55ceb1a513..961bdcc5b3 100644 --- a/src/gallium/drivers/r300/r300_texture.h +++ b/src/gallium/drivers/r300/r300_texture.h @@ -31,31 +31,46 @@ struct r300_texture; void r300_init_screen_texture_functions(struct pipe_screen* screen); -unsigned r300_texture_get_stride(struct r300_texture* tex, unsigned level); +unsigned r300_texture_get_stride(struct r300_screen* screen, + struct r300_texture* tex, unsigned level); unsigned r300_texture_get_offset(struct r300_texture* tex, unsigned level, unsigned zslice, unsigned face); -/* Note the signature of R300_EASY_TX_FORMAT(A, R, G, B, FORMAT)... */ +/* Translate a pipe_format into a useful texture format for sampling. + * + * R300_EASY_TX_FORMAT swizzles the texture. + * Note the signature of R300_EASY_TX_FORMAT: + * R300_EASY_TX_FORMAT(B, G, R, A, FORMAT); + * + * The FORMAT specifies how the texture sampler will treat the texture, and + * makes available X, Y, Z, W, ZERO, and ONE for swizzling. */ static INLINE uint32_t r300_translate_texformat(enum pipe_format format) { switch (format) { /* X8 */ + case PIPE_FORMAT_A8_UNORM: + return R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, X8); case PIPE_FORMAT_I8_UNORM: return R300_EASY_TX_FORMAT(X, X, X, X, X8); case PIPE_FORMAT_L8_UNORM: return R300_EASY_TX_FORMAT(X, X, X, ONE, X8); + case PIPE_FORMAT_L8_SRGB: + return R300_EASY_TX_FORMAT(X, X, X, ONE, X8) | + R300_TX_FORMAT_GAMMA; /* X16 */ case PIPE_FORMAT_R16_UNORM: + case PIPE_FORMAT_Z16_UNORM: return R300_EASY_TX_FORMAT(X, X, X, X, X16); case PIPE_FORMAT_R16_SNORM: return R300_EASY_TX_FORMAT(X, X, X, X, X16) | R300_TX_FORMAT_SIGNED; - case PIPE_FORMAT_Z16_UNORM: - return R300_EASY_TX_FORMAT(X, X, X, X, X16); /* Y8X8 */ case PIPE_FORMAT_A8L8_UNORM: return R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8); + case PIPE_FORMAT_A8L8_SRGB: + return R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8) | + R300_TX_FORMAT_GAMMA; /* W8Z8Y8X8 */ case PIPE_FORMAT_A8R8G8B8_UNORM: return R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8); @@ -115,7 +130,8 @@ r300_video_surface(struct pipe_video_surface *pvs) #ifndef R300_WINSYS_H -boolean r300_get_texture_buffer(struct pipe_texture* texture, +boolean r300_get_texture_buffer(struct pipe_screen* screen, + struct pipe_texture* texture, struct pipe_buffer** buffer, unsigned* stride); diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c index a792c2cf98..941ec17016 100644 --- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c +++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c @@ -201,6 +201,8 @@ static void transform_srcreg( struct rc_src_register * dst, struct tgsi_full_src_register * src) { + unsigned i, j; + dst->File = translate_register_file(src->Register.File); dst->Index = translate_register_index(ttr, src->Register.File, src->Register.Index); dst->RelAddr = src->Register.Indirect; @@ -210,6 +212,21 @@ static void transform_srcreg( dst->Swizzle |= tgsi_util_get_full_src_register_swizzle(src, 3) << 9; dst->Abs = src->Register.Absolute; dst->Negate = src->Register.Negate ? RC_MASK_XYZW : 0; + + if (src->Register.File == TGSI_FILE_IMMEDIATE) { + for (i = 0; i < ttr->imms_to_swizzle_count; i++) { + if (ttr->imms_to_swizzle[i].index == src->Register.Index) { + dst->File = RC_FILE_TEMPORARY; + dst->Index = 0; + dst->Swizzle = 0; + for (j = 0; j < 4; j++) { + dst->Swizzle |= GET_SWZ(ttr->imms_to_swizzle[i].swizzle, + tgsi_util_get_full_src_register_swizzle(src, j)) << (j * 3); + } + break; + } + } + } } static void transform_texture(struct rc_instruction * dst, struct tgsi_instruction_texture src, @@ -277,21 +294,45 @@ static void transform_instruction(struct tgsi_to_rc * ttr, struct tgsi_full_inst &ttr->compiler->Program.ShadowSamplers); } -static void handle_immediate(struct tgsi_to_rc * ttr, struct tgsi_full_immediate * imm) +static void handle_immediate(struct tgsi_to_rc * ttr, + struct tgsi_full_immediate * imm, + unsigned index) { struct rc_constant constant; - int i; + unsigned swizzle = 0; + boolean can_swizzle = TRUE; + unsigned i; - constant.Type = RC_CONSTANT_IMMEDIATE; - constant.Size = 4; - for(i = 0; i < 4; ++i) - constant.u.Immediate[i] = imm->u[i].Float; - rc_constants_add(&ttr->compiler->Program.Constants, &constant); + for (i = 0; i < 4; i++) { + if (imm->u[i].Float == 0.0f) { + swizzle |= RC_SWIZZLE_ZERO << (i * 3); + } else if (imm->u[i].Float == 0.5f) { + swizzle |= RC_SWIZZLE_HALF << (i * 3); + } else if (imm->u[i].Float == 1.0f) { + swizzle |= RC_SWIZZLE_ONE << (i * 3); + } else { + can_swizzle = FALSE; + break; + } + } + + if (can_swizzle) { + ttr->imms_to_swizzle[ttr->imms_to_swizzle_count].index = index; + ttr->imms_to_swizzle[ttr->imms_to_swizzle_count].swizzle = swizzle; + ttr->imms_to_swizzle_count++; + } else { + constant.Type = RC_CONSTANT_IMMEDIATE; + constant.Size = 4; + for(i = 0; i < 4; ++i) + constant.u.Immediate[i] = imm->u[i].Float; + rc_constants_add(&ttr->compiler->Program.Constants, &constant); + } } void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens) { struct tgsi_parse_context parser; + unsigned imm_index = 0; int i; /* Allocate constants placeholders. @@ -308,6 +349,9 @@ void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens) ttr->immediate_offset = ttr->compiler->Program.Constants.Count; + ttr->imms_to_swizzle = malloc(ttr->info->immediate_count * sizeof(struct swizzled_imms)); + ttr->imms_to_swizzle_count = 0; + tgsi_parse_init(&parser, tokens); while (!tgsi_parse_end_of_tokens(&parser)) { @@ -317,7 +361,8 @@ void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens) case TGSI_TOKEN_TYPE_DECLARATION: break; case TGSI_TOKEN_TYPE_IMMEDIATE: - handle_immediate(ttr, &parser.FullToken.FullImmediate); + handle_immediate(ttr, &parser.FullToken.FullImmediate, imm_index); + imm_index++; break; case TGSI_TOKEN_TYPE_INSTRUCTION: transform_instruction(ttr, &parser.FullToken.FullInstruction); @@ -327,6 +372,8 @@ void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens) tgsi_parse_free(&parser); + free(ttr->imms_to_swizzle); + rc_calculate_inputs_outputs(ttr->compiler); } diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.h b/src/gallium/drivers/r300/r300_tgsi_to_rc.h index 93e90ec6d2..39b473c7bf 100644 --- a/src/gallium/drivers/r300/r300_tgsi_to_rc.h +++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.h @@ -29,11 +29,18 @@ struct tgsi_full_declaration; struct tgsi_shader_info; struct tgsi_token; +struct swizzled_imms { + unsigned index; + unsigned swizzle; +}; + struct tgsi_to_rc { struct radeon_compiler * compiler; const struct tgsi_shader_info * info; int immediate_offset; + struct swizzled_imms * imms_to_swizzle; + unsigned imms_to_swizzle_count; }; void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens); diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index 68aef70872..fb81b2439b 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -61,17 +61,17 @@ static void r300_shader_read_vs_outputs( break; case TGSI_SEMANTIC_COLOR: - assert(index <= ATTR_COLOR_COUNT); + assert(index < ATTR_COLOR_COUNT); vs_outputs->color[index] = i; break; case TGSI_SEMANTIC_BCOLOR: - assert(index <= ATTR_COLOR_COUNT); + assert(index < ATTR_COLOR_COUNT); vs_outputs->bcolor[index] = i; break; case TGSI_SEMANTIC_GENERIC: - assert(index <= ATTR_GENERIC_COUNT); + assert(index < ATTR_GENERIC_COUNT); vs_outputs->generic[index] = i; break; @@ -124,7 +124,8 @@ static void r300_shader_vap_output_fmt(struct r300_vertex_shader* vs) /* Colors. */ for (i = 0; i < ATTR_COLOR_COUNT; i++) { - if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used) { + if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used || + vs_outputs->color[1] != ATTR_UNUSED) { hwfmt[1] |= R300_INPUT_CNTL_COLOR; hwfmt[2] |= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_0_PRESENT << i; } @@ -182,7 +183,8 @@ static void r300_stream_locations_notcl( /* Colors. */ for (i = 0; i < ATTR_COLOR_COUNT; i++) { - if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used) { + if (vs_outputs->color[i] != ATTR_UNUSED || any_bcolor_used || + vs_outputs->color[1] != ATTR_UNUSED) { stream_loc[tabi++] = 2 + i; } } @@ -259,7 +261,8 @@ static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c) for (i = 0; i < ATTR_COLOR_COUNT; i++) { if (outputs->color[i] != ATTR_UNUSED) { c->code->outputs[outputs->color[i]] = reg++; - } else if (any_bcolor_used) { + } else if (any_bcolor_used || + outputs->color[1] != ATTR_UNUSED) { reg++; } } diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index 1ae6de70fe..f4a8ae120c 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -29,18 +29,20 @@ extern "C" { /* The public interface header for the r300 pipe driver. * Any winsys hosting this pipe needs to implement r300_winsys and then - * call r300_create_context to start things. */ + * call r300_create_screen to start things. */ #include "pipe/p_defines.h" #include "pipe/p_state.h" -#include "pipe/internal/p_winsys_screen.h" +#include "util/u_simple_screen.h" #include "radeon_winsys.h" -struct pipe_context* r300_create_context(struct pipe_screen* screen, - struct radeon_winsys* radeon_winsys); +/* Creates a new r300 screen. */ +struct pipe_screen* r300_create_screen(struct radeon_winsys* radeon_winsys); -boolean r300_get_texture_buffer(struct pipe_texture* texture, + +boolean r300_get_texture_buffer(struct pipe_screen* screen, + struct pipe_texture* texture, struct pipe_buffer** buffer, unsigned* stride); diff --git a/src/gallium/drivers/softpipe/Makefile b/src/gallium/drivers/softpipe/Makefile index bcb887a0b2..e4ac49fa85 100644 --- a/src/gallium/drivers/softpipe/Makefile +++ b/src/gallium/drivers/softpipe/Makefile @@ -32,6 +32,7 @@ C_SOURCES = \ sp_tex_tile_cache.c \ sp_tile_cache.c \ sp_surface.c \ - sp_video_context.c + sp_video_context.c \ + sp_winsys.c include ../../Makefile.template diff --git a/src/gallium/drivers/softpipe/SConscript b/src/gallium/drivers/softpipe/SConscript index aac9edf44e..3042e556c6 100644 --- a/src/gallium/drivers/softpipe/SConscript +++ b/src/gallium/drivers/softpipe/SConscript @@ -34,6 +34,7 @@ softpipe = env.ConvenienceLibrary( 'sp_texture.c', 'sp_tile_cache.c', 'sp_video_context.c', + 'sp_winsys.c' ]) Export('softpipe') diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index f3ac6760db..2b22ce256e 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -35,6 +35,7 @@ #include "pipe/p_defines.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_inlines.h" #include "sp_clear.h" #include "sp_context.h" #include "sp_flush.h" @@ -43,8 +44,6 @@ #include "sp_surface.h" #include "sp_tile_cache.h" #include "sp_tex_tile_cache.h" -#include "sp_texture.h" -#include "sp_winsys.h" #include "sp_query.h" @@ -112,9 +111,13 @@ softpipe_destroy( struct pipe_context *pipe ) pipe_texture_reference(&softpipe->vertex_textures[i], NULL); } - for (i = 0; i < Elements(softpipe->constants); i++) { - if (softpipe->constants[i].buffer) { - pipe_buffer_reference(&softpipe->constants[i].buffer, NULL); + for (i = 0; i < PIPE_SHADER_TYPES; i++) { + uint j; + + for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) { + if (softpipe->constants[i][j]) { + pipe_buffer_reference(&softpipe->constants[i][j], NULL); + } } } @@ -190,7 +193,8 @@ softpipe_render_condition( struct pipe_context *pipe, struct pipe_context * -softpipe_create( struct pipe_screen *screen ) +softpipe_create_context( struct pipe_screen *screen, + void *priv ) { struct softpipe_context *softpipe = CALLOC_STRUCT(softpipe_context); uint i; @@ -209,6 +213,7 @@ softpipe_create( struct pipe_screen *screen ) softpipe->pipe.winsys = screen->winsys; softpipe->pipe.screen = screen; softpipe->pipe.destroy = softpipe_destroy; + softpipe->pipe.priv = priv; /* state setters */ softpipe->pipe.create_blend_state = softpipe_create_blend_state; @@ -256,6 +261,8 @@ softpipe_create( struct pipe_screen *screen ) softpipe->pipe.draw_arrays = softpipe_draw_arrays; softpipe->pipe.draw_elements = softpipe_draw_elements; softpipe->pipe.draw_range_elements = softpipe_draw_range_elements; + softpipe->pipe.draw_arrays_instanced = softpipe_draw_arrays_instanced; + softpipe->pipe.draw_elements_instanced = softpipe_draw_elements_instanced; softpipe->pipe.clear = softpipe_clear; softpipe->pipe.flush = softpipe_flush; diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index 73fa744f9d..62f9e7aad3 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -63,7 +63,7 @@ struct softpipe_context { /** Other rendering state */ struct pipe_blend_color blend_color; struct pipe_clip_state clip; - struct pipe_constant_buffer constants[PIPE_SHADER_TYPES]; + struct pipe_buffer *constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple poly_stipple; struct pipe_scissor_state scissor; @@ -92,7 +92,7 @@ struct softpipe_context { ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS]; /** Mapped constant buffers */ - void *mapped_constants[PIPE_SHADER_TYPES]; + void *mapped_constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS]; /** Vertex format */ struct vertex_info vertex_info; @@ -166,5 +166,8 @@ softpipe_context( struct pipe_context *pipe ) void softpipe_reset_sampler_varients(struct softpipe_context *softpipe); +struct pipe_context * +softpipe_create_context( struct pipe_screen *, void *priv ); + #endif /* SP_CONTEXT_H */ diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c index 03d35fb3cb..b2acc36bf7 100644 --- a/src/gallium/drivers/softpipe/sp_draw_arrays.c +++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c @@ -33,8 +33,8 @@ #include "pipe/p_defines.h" #include "pipe/p_context.h" -#include "pipe/internal/p_winsys_screen.h" -#include "pipe/p_inlines.h" +#include "util/u_simple_screen.h" +#include "util/u_inlines.h" #include "util/u_prim.h" #include "sp_context.h" @@ -49,30 +49,36 @@ static void softpipe_map_constant_buffers(struct softpipe_context *sp) { struct pipe_winsys *ws = sp->pipe.winsys; - uint i, vssize, gssize; + uint i; for (i = 0; i < PIPE_SHADER_TYPES; i++) { - if (sp->constants[i].buffer && sp->constants[i].buffer->size) - sp->mapped_constants[i] = ws->buffer_map(ws, sp->constants[i].buffer, - PIPE_BUFFER_USAGE_CPU_READ); + uint j; + + for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) { + if (sp->constants[i][j] && sp->constants[i][j]->size) { + sp->mapped_constants[i][j] = ws->buffer_map(ws, + sp->constants[i][j], + PIPE_BUFFER_USAGE_CPU_READ); + } + } } - if (sp->constants[PIPE_SHADER_VERTEX].buffer) - vssize = sp->constants[PIPE_SHADER_VERTEX].buffer->size; - else - vssize = 0; - - if (sp->constants[PIPE_SHADER_GEOMETRY].buffer) - gssize = sp->constants[PIPE_SHADER_GEOMETRY].buffer->size; - else - gssize = 0; - - draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_VERTEX, - sp->mapped_constants[PIPE_SHADER_VERTEX], - vssize); - draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_GEOMETRY, - sp->mapped_constants[PIPE_SHADER_GEOMETRY], - gssize); + for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { + if (sp->constants[PIPE_SHADER_VERTEX][i]) { + draw_set_mapped_constant_buffer(sp->draw, + PIPE_SHADER_VERTEX, + i, + sp->mapped_constants[PIPE_SHADER_VERTEX][i], + sp->constants[PIPE_SHADER_VERTEX][i]->size); + } + if (sp->constants[PIPE_SHADER_GEOMETRY][i]) { + draw_set_mapped_constant_buffer(sp->draw, + PIPE_SHADER_GEOMETRY, + i, + sp->mapped_constants[PIPE_SHADER_GEOMETRY][i], + sp->constants[PIPE_SHADER_GEOMETRY][i]->size); + } + } } @@ -87,30 +93,67 @@ softpipe_unmap_constant_buffers(struct softpipe_context *sp) */ draw_flush(sp->draw); - draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_VERTEX, NULL, 0); - draw_set_mapped_constant_buffer(sp->draw, PIPE_SHADER_GEOMETRY, NULL, 0); + for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { + draw_set_mapped_constant_buffer(sp->draw, + PIPE_SHADER_VERTEX, + i, + NULL, + 0); + draw_set_mapped_constant_buffer(sp->draw, + PIPE_SHADER_GEOMETRY, + i, + NULL, + 0); + } for (i = 0; i < PIPE_SHADER_TYPES; i++) { - if (sp->constants[i].buffer && sp->constants[i].buffer->size) - ws->buffer_unmap(ws, sp->constants[i].buffer); - sp->mapped_constants[i] = NULL; + uint j; + + for (j = 0; j < PIPE_MAX_CONSTANT_BUFFERS; j++) { + if (sp->constants[i][j] && sp->constants[i][j]->size) { + ws->buffer_unmap(ws, sp->constants[i][j]); + } + sp->mapped_constants[i][j] = NULL; + } } } +/** + * Draw vertex arrays, with optional indexing. + * Basically, map the vertex buffers (and drawing surfaces), then hand off + * the drawing to the 'draw' module. + */ +static void +softpipe_draw_range_elements_instanced(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count, + unsigned startInstance, + unsigned instanceCount); + + void softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count) { - softpipe_draw_elements(pipe, NULL, 0, mode, start, count); + softpipe_draw_range_elements_instanced(pipe, + NULL, + 0, + 0, + 0xffffffff, + mode, + start, + count, + 0, + 1); } -/** - * Draw vertex arrays, with optional indexing. - * Basically, map the vertex buffers (and drawing surfaces), then hand off - * the drawing to the 'draw' module. - */ void softpipe_draw_range_elements(struct pipe_context *pipe, struct pipe_buffer *indexBuffer, @@ -119,6 +162,91 @@ softpipe_draw_range_elements(struct pipe_context *pipe, unsigned max_index, unsigned mode, unsigned start, unsigned count) { + softpipe_draw_range_elements_instanced(pipe, + indexBuffer, + indexSize, + min_index, + max_index, + mode, + start, + count, + 0, + 1); +} + + +void +softpipe_draw_elements(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned mode, unsigned start, unsigned count) +{ + softpipe_draw_range_elements_instanced(pipe, + indexBuffer, + indexSize, + 0, + 0xffffffff, + mode, + start, + count, + 0, + 1); +} + +void +softpipe_draw_arrays_instanced(struct pipe_context *pipe, + unsigned mode, + unsigned start, + unsigned count, + unsigned startInstance, + unsigned instanceCount) +{ + softpipe_draw_range_elements_instanced(pipe, + NULL, + 0, + 0, + 0xffffffff, + mode, + start, + count, + startInstance, + instanceCount); +} + +void +softpipe_draw_elements_instanced(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned mode, + unsigned start, + unsigned count, + unsigned startInstance, + unsigned instanceCount) +{ + softpipe_draw_range_elements_instanced(pipe, + indexBuffer, + indexSize, + 0, + 0xffffffff, + mode, + start, + count, + startInstance, + instanceCount); +} + +static void +softpipe_draw_range_elements_instanced(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count, + unsigned startInstance, + unsigned instanceCount) +{ struct softpipe_context *sp = softpipe_context(pipe); struct draw_context *draw = sp->draw; unsigned i; @@ -128,45 +256,48 @@ softpipe_draw_range_elements(struct pipe_context *pipe, sp->reduced_api_prim = u_reduced_prim(mode); - if (sp->dirty) - softpipe_update_derived( sp ); + if (sp->dirty) { + softpipe_update_derived(sp); + } softpipe_map_transfers(sp); softpipe_map_constant_buffers(sp); - /* - * Map vertex buffers - */ + /* Map vertex buffers */ for (i = 0; i < sp->num_vertex_buffers; i++) { - void *buf - = pipe_buffer_map(pipe->screen, - sp->vertex_buffer[i].buffer, - PIPE_BUFFER_USAGE_CPU_READ); + void *buf; + + buf = pipe_buffer_map(pipe->screen, + sp->vertex_buffer[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_buffer_map(pipe->screen, indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); - draw_set_mapped_element_buffer_range(draw, indexSize, - min_index, - max_index, + void *mapped_indexes; + + mapped_indexes = pipe_buffer_map(pipe->screen, + indexBuffer, + PIPE_BUFFER_USAGE_CPU_READ); + draw_set_mapped_element_buffer_range(draw, + indexSize, + minIndex, + maxIndex, mapped_indexes); - } - else { + } 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); + draw_arrays_instanced(draw, mode, start, count, startInstance, instanceCount); - /* - * unmap vertex/index buffers - will cause draw module to flush - */ + /* unmap vertex/index buffers - will cause draw module to flush */ for (i = 0; i < sp->num_vertex_buffers; i++) { draw_set_mapped_vertex_buffer(draw, i, NULL); pipe_buffer_unmap(pipe->screen, sp->vertex_buffer[i].buffer); @@ -176,22 +307,8 @@ softpipe_draw_range_elements(struct pipe_context *pipe, pipe_buffer_unmap(pipe->screen, indexBuffer); } - /* Note: leave drawing surfaces mapped */ softpipe_unmap_constant_buffers(sp); sp->dirty_render_cache = TRUE; } - - -void -softpipe_draw_elements(struct pipe_context *pipe, - struct pipe_buffer *indexBuffer, - unsigned indexSize, - unsigned mode, unsigned start, unsigned count) -{ - softpipe_draw_range_elements( pipe, indexBuffer, - indexSize, - 0, 0xffffffff, - mode, start, count ); -} diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c index 75dac810a1..e8952bf4fb 100644 --- a/src/gallium/drivers/softpipe/sp_flush.c +++ b/src/gallium/drivers/softpipe/sp_flush.c @@ -34,11 +34,9 @@ #include "draw/draw_context.h" #include "sp_flush.h" #include "sp_context.h" -#include "sp_surface.h" #include "sp_state.h" #include "sp_tile_cache.h" #include "sp_tex_tile_cache.h" -#include "sp_winsys.h" void diff --git a/src/gallium/drivers/softpipe/sp_fs_sse.c b/src/gallium/drivers/softpipe/sp_fs_sse.c index f912950658..acee213670 100644 --- a/src/gallium/drivers/softpipe/sp_fs_sse.c +++ b/src/gallium/drivers/softpipe/sp_fs_sse.c @@ -135,7 +135,7 @@ fs_sse_run( const struct sp_fragment_shader *base, tgsi_set_exec_mask(machine, 1, 1, 1, 1); shader->func( machine, - machine->Consts, + (const float (*)[4])machine->Consts[0], (const float (*)[4])shader->immediates, machine->InterpCoefs /*, &machine->QuadPos*/ diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.c b/src/gallium/drivers/softpipe/sp_prim_vbuf.c index 7f573aef3c..98c08eaffa 100644 --- a/src/gallium/drivers/softpipe/sp_prim_vbuf.c +++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.c @@ -526,6 +526,8 @@ static void sp_vbuf_destroy(struct vbuf_render *vbr) { struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); + if(cvbr->vertex_buffer) + align_free(cvbr->vertex_buffer); sp_setup_destroy_context(cvbr->setup); FREE(cvbr); } @@ -541,7 +543,6 @@ sp_create_vbuf_backend(struct softpipe_context *sp) assert(sp->draw); - cvbr->base.max_indices = SP_MAX_VBUF_INDEXES; cvbr->base.max_vertex_buffer_bytes = SP_MAX_VBUF_SIZE; diff --git a/src/gallium/drivers/softpipe/sp_quad_blend.c b/src/gallium/drivers/softpipe/sp_quad_blend.c index d9babe81da..d65307b7f6 100644 --- a/src/gallium/drivers/softpipe/sp_quad_blend.c +++ b/src/gallium/drivers/softpipe/sp_quad_blend.c @@ -35,7 +35,6 @@ #include "util/u_memory.h" #include "sp_context.h" #include "sp_quad.h" -#include "sp_surface.h" #include "sp_tile_cache.h" #include "sp_quad_pipe.h" @@ -224,7 +223,8 @@ logicop_quad(struct quad_stage *qs, static void blend_quad(struct quad_stage *qs, float (*quadColor)[4], - float (*dest)[4]) + float (*dest)[4], + unsigned cbuf) { static const float zero[4] = { 0, 0, 0, 0 }; static const float one[4] = { 1, 1, 1, 1 }; @@ -234,7 +234,7 @@ blend_quad(struct quad_stage *qs, /* * Compute src/first term RGB */ - switch (softpipe->blend->rgb_src_factor) { + switch (softpipe->blend->rt[cbuf].rgb_src_factor) { case PIPE_BLENDFACTOR_ONE: VEC4_COPY(source[0], quadColor[0]); /* R */ VEC4_COPY(source[1], quadColor[1]); /* G */ @@ -384,7 +384,7 @@ blend_quad(struct quad_stage *qs, /* * Compute src/first term A */ - switch (softpipe->blend->alpha_src_factor) { + switch (softpipe->blend->rt[cbuf].alpha_src_factor) { case PIPE_BLENDFACTOR_ONE: VEC4_COPY(source[3], quadColor[3]); /* A */ break; @@ -453,7 +453,7 @@ blend_quad(struct quad_stage *qs, /* * Compute dest/second term RGB */ - switch (softpipe->blend->rgb_dst_factor) { + switch (softpipe->blend->rt[cbuf].rgb_dst_factor) { case PIPE_BLENDFACTOR_ONE: /* dest = dest * 1 NO-OP, leave dest as-is */ break; @@ -593,7 +593,7 @@ blend_quad(struct quad_stage *qs, /* * Compute dest/second term A */ - switch (softpipe->blend->alpha_dst_factor) { + switch (softpipe->blend->rt[cbuf].alpha_dst_factor) { case PIPE_BLENDFACTOR_ONE: /* dest = dest * 1 NO-OP, leave dest as-is */ break; @@ -656,7 +656,7 @@ blend_quad(struct quad_stage *qs, /* * Combine RGB terms */ - switch (softpipe->blend->rgb_func) { + switch (softpipe->blend->rt[cbuf].rgb_func) { case PIPE_BLEND_ADD: VEC4_ADD_SAT(quadColor[0], source[0], dest[0]); /* R */ VEC4_ADD_SAT(quadColor[1], source[1], dest[1]); /* G */ @@ -689,7 +689,7 @@ blend_quad(struct quad_stage *qs, /* * Combine A terms */ - switch (softpipe->blend->alpha_func) { + switch (softpipe->blend->rt[cbuf].alpha_func) { case PIPE_BLEND_ADD: VEC4_ADD_SAT(quadColor[3], source[3], dest[3]); /* A */ break; @@ -711,26 +711,24 @@ blend_quad(struct quad_stage *qs, } static void -colormask_quad(struct quad_stage *qs, +colormask_quad(unsigned colormask, float (*quadColor)[4], float (*dest)[4]) { - struct softpipe_context *softpipe = qs->softpipe; - /* R */ - if (!(softpipe->blend->colormask & PIPE_MASK_R)) + if (!(colormask & PIPE_MASK_R)) COPY_4V(quadColor[0], dest[0]); /* G */ - if (!(softpipe->blend->colormask & PIPE_MASK_G)) + if (!(colormask & PIPE_MASK_G)) COPY_4V(quadColor[1], dest[1]); /* B */ - if (!(softpipe->blend->colormask & PIPE_MASK_B)) + if (!(colormask & PIPE_MASK_B)) COPY_4V(quadColor[2], dest[2]); /* A */ - if (!(softpipe->blend->colormask & PIPE_MASK_A)) + if (!(colormask & PIPE_MASK_A)) COPY_4V(quadColor[3], dest[3]); } @@ -773,12 +771,12 @@ blend_fallback(struct quad_stage *qs, if (blend->logicop_enable) { logicop_quad( qs, quadColor, dest ); } - else if (blend->blend_enable) { - blend_quad( qs, quadColor, dest ); + else if (blend->rt[cbuf].blend_enable) { + blend_quad( qs, quadColor, dest, cbuf ); } - if (blend->colormask != 0xf) - colormask_quad( qs, quadColor, dest ); + if (blend->rt[cbuf].colormask != 0xf) + colormask_quad( blend->rt[cbuf].colormask, quadColor, dest); /* Output color values */ @@ -954,23 +952,23 @@ choose_blend_quad(struct quad_stage *qs, qs->run = blend_noop; } else if (!softpipe->blend->logicop_enable && - softpipe->blend->colormask == 0xf && + softpipe->blend->rt[0].colormask == 0xf && softpipe->framebuffer.nr_cbufs == 1) { - if (!blend->blend_enable) { + if (!blend->rt[0].blend_enable) { qs->run = single_output_color; } - else if (blend->rgb_src_factor == blend->alpha_src_factor && - blend->rgb_dst_factor == blend->alpha_dst_factor && - blend->rgb_func == blend->alpha_func) + else if (blend->rt[0].rgb_src_factor == blend->rt[0].alpha_src_factor && + blend->rt[0].rgb_dst_factor == blend->rt[0].alpha_dst_factor && + blend->rt[0].rgb_func == blend->rt[0].alpha_func) { - if (blend->alpha_func == PIPE_BLEND_ADD) { - if (blend->rgb_src_factor == PIPE_BLENDFACTOR_ONE && - blend->rgb_dst_factor == PIPE_BLENDFACTOR_ONE) { + if (blend->rt[0].alpha_func == PIPE_BLEND_ADD) { + if (blend->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_ONE && + blend->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_ONE) { qs->run = blend_single_add_one_one; } - else if (blend->rgb_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA && - blend->rgb_dst_factor == PIPE_BLENDFACTOR_INV_SRC_ALPHA) + else if (blend->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA && + blend->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_INV_SRC_ALPHA) qs->run = blend_single_add_src_alpha_inv_src_alpha; } diff --git a/src/gallium/drivers/softpipe/sp_quad_depth_test.c b/src/gallium/drivers/softpipe/sp_quad_depth_test.c index 0ca86c4e1c..a981775cbd 100644 --- a/src/gallium/drivers/softpipe/sp_quad_depth_test.c +++ b/src/gallium/drivers/softpipe/sp_quad_depth_test.c @@ -30,11 +30,11 @@ */ #include "pipe/p_defines.h" +#include "util/u_format.h" #include "util/u_memory.h" #include "tgsi/tgsi_scan.h" #include "sp_context.h" #include "sp_quad.h" -#include "sp_surface.h" #include "sp_quad_pipe.h" #include "sp_tile_cache.h" #include "sp_state.h" /* for sp_fragment_shader */ @@ -651,6 +651,20 @@ static unsigned mask_count[16] = +/** helper to get number of Z buffer bits */ +static unsigned +get_depth_bits(struct quad_stage *qs) +{ + struct pipe_surface *zsurf = qs->softpipe->framebuffer.zsbuf; + if (zsurf) + return util_format_get_component_bits(zsurf->format, + UTIL_FORMAT_COLORSPACE_ZS, 0); + else + return 0; +} + + + static void depth_test_quads_fallback(struct quad_stage *qs, struct quad_header *quads[], @@ -666,7 +680,7 @@ depth_test_quads_fallback(struct quad_stage *qs, nr = alpha_test_quads(qs, quads, nr); } - if (qs->softpipe->framebuffer.zsbuf && + if (get_depth_bits(qs) > 0 && (qs->softpipe->depth_stencil->depth.enabled || qs->softpipe->depth_stencil->stencil[0].enabled)) { @@ -884,7 +898,7 @@ choose_depth_test(struct quad_stage *qs, boolean alpha = qs->softpipe->depth_stencil->alpha.enabled; - boolean depth = (qs->softpipe->framebuffer.zsbuf && + boolean depth = (get_depth_bits(qs) > 0 && qs->softpipe->depth_stencil->depth.enabled); unsigned depthfunc = qs->softpipe->depth_stencil->depth.func; @@ -895,7 +909,6 @@ choose_depth_test(struct quad_stage *qs, boolean occlusion = qs->softpipe->active_query_count; - if (!alpha && !depth && !stencil) { diff --git a/src/gallium/drivers/softpipe/sp_quad_fs.c b/src/gallium/drivers/softpipe/sp_quad_fs.c index 1e7533d0f9..ad04dc2afc 100644 --- a/src/gallium/drivers/softpipe/sp_quad_fs.c +++ b/src/gallium/drivers/softpipe/sp_quad_fs.c @@ -45,8 +45,6 @@ #include "sp_state.h" #include "sp_quad.h" #include "sp_quad_pipe.h" -#include "sp_texture.h" -#include "sp_tex_sample.h" struct quad_shade_stage @@ -109,10 +107,11 @@ shade_quads(struct quad_stage *qs, struct quad_shade_stage *qss = quad_shade_stage( qs ); struct softpipe_context *softpipe = qs->softpipe; struct tgsi_exec_machine *machine = qss->machine; - unsigned i, pass = 0; - - machine->Consts = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT]; + + for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) { + machine->Consts[i] = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT][i]; + } machine->InterpCoefs = quads[0]->coef; for (i = 0; i < nr; i++) { diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index bd3532de4f..87415f4340 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -28,13 +28,14 @@ #include "util/u_memory.h" #include "util/u_simple_screen.h" -#include "pipe/internal/p_winsys_screen.h" +#include "util/u_simple_screen.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" #include "sp_texture.h" #include "sp_winsys.h" #include "sp_screen.h" +#include "sp_context.h" static const char * @@ -91,6 +92,19 @@ softpipe_get_param(struct pipe_screen *screen, int param) return 1; case PIPE_CAP_BLEND_EQUATION_SEPARATE: return 1; + case PIPE_CAP_MAX_CONST_BUFFERS: + return PIPE_MAX_CONSTANT_BUFFERS; + case PIPE_CAP_MAX_CONST_BUFFER_SIZE: + return 4096 * 4 * sizeof(float); + case PIPE_CAP_INDEP_BLEND_ENABLE: + return 1; + case PIPE_CAP_INDEP_BLEND_FUNC: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 1; default: return 0; } @@ -191,6 +205,7 @@ softpipe_create_screen(struct pipe_winsys *winsys) screen->base.get_param = softpipe_get_param; screen->base.get_paramf = softpipe_get_paramf; screen->base.is_format_supported = softpipe_is_format_supported; + screen->base.context_create = softpipe_create_context; softpipe_init_screen_texture_funcs(&screen->base); u_simple_screen_init(&screen->base); diff --git a/src/gallium/drivers/softpipe/sp_setup.c b/src/gallium/drivers/softpipe/sp_setup.c index 3da75364c5..b8590a8cc2 100644 --- a/src/gallium/drivers/softpipe/sp_setup.c +++ b/src/gallium/drivers/softpipe/sp_setup.c @@ -38,10 +38,8 @@ #include "sp_setup.h" #include "sp_state.h" #include "draw/draw_context.h" -#include "draw/draw_private.h" #include "draw/draw_vertex.h" #include "pipe/p_shader_tokens.h" -#include "pipe/p_thread.h" #include "util/u_math.h" #include "util/u_memory.h" @@ -395,6 +393,52 @@ static boolean setup_sort_vertices( struct setup_context *setup, } +/* Apply cylindrical wrapping to v0, v1, v2 coordinates, if enabled. + * Input coordinates must be in [0, 1] range, otherwise results are undefined. + * Some combinations of coordinates produce invalid results, + * but this behaviour is acceptable. + */ +static void +tri_apply_cylindrical_wrap(float v0, + float v1, + float v2, + uint cylindrical_wrap, + float output[3]) +{ + if (cylindrical_wrap) { + float delta; + + delta = v1 - v0; + if (delta > 0.5f) { + v0 += 1.0f; + } + else if (delta < -0.5f) { + v1 += 1.0f; + } + + delta = v2 - v1; + if (delta > 0.5f) { + v1 += 1.0f; + } + else if (delta < -0.5f) { + v2 += 1.0f; + } + + delta = v0 - v2; + if (delta > 0.5f) { + v2 += 1.0f; + } + else if (delta < -0.5f) { + v0 += 1.0f; + } + } + + output[0] = v0; + output[1] = v1; + output[2] = v2; +} + + /** * Compute a0 for a constant-valued coefficient (GL_FLAT shading). * The value value comes from vertex[slot][i]. @@ -420,13 +464,16 @@ static void const_coeff( struct setup_context *setup, /** * Compute a0, dadx and dady for a linearly interpolated coefficient, * for a triangle. + * v[0], v[1] and v[2] are vmin, vmid and vmax, respectively. */ -static void tri_linear_coeff( struct setup_context *setup, - struct tgsi_interp_coef *coef, - uint vertSlot, uint i) +static void +tri_linear_coeff(struct setup_context *setup, + struct tgsi_interp_coef *coef, + uint i, + const float v[3]) { - float botda = setup->vmid[vertSlot][i] - setup->vmin[vertSlot][i]; - float majda = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i]; + float botda = v[1] - v[0]; + float majda = v[2] - v[0]; float a = setup->ebot.dy * majda - botda * setup->emaj.dy; float b = setup->emaj.dx * botda - majda * setup->ebot.dx; float dadx = a * setup->oneoverarea; @@ -449,7 +496,7 @@ static void tri_linear_coeff( struct setup_context *setup, * to define a0 as the sample at a pixel center somewhere near vmin * instead - i'll switch to this later. */ - coef->a0[i] = (setup->vmin[vertSlot][i] - + coef->a0[i] = (v[0] - (dadx * (setup->vmin[0][0] - setup->pixel_offset) + dady * (setup->vmin[0][1] - setup->pixel_offset))); @@ -470,16 +517,19 @@ static void tri_linear_coeff( struct setup_context *setup, * the plane coefficients (a0, dadx, dady). * Later, when we compute the value at a particular fragment position we'll * divide the interpolated value by the interpolated W at that fragment. + * v[0], v[1] and v[2] are vmin, vmid and vmax, respectively. */ -static void tri_persp_coeff( struct setup_context *setup, - struct tgsi_interp_coef *coef, - uint vertSlot, uint i) +static void +tri_persp_coeff(struct setup_context *setup, + struct tgsi_interp_coef *coef, + uint i, + const float v[3]) { /* premultiply by 1/w (v[0][3] is always W): */ - float mina = setup->vmin[vertSlot][i] * setup->vmin[0][3]; - float mida = setup->vmid[vertSlot][i] * setup->vmid[0][3]; - float maxa = setup->vmax[vertSlot][i] * setup->vmax[0][3]; + float mina = v[0] * setup->vmin[0][3]; + float mida = v[1] * setup->vmid[0][3]; + float maxa = v[2] * setup->vmax[0][3]; float botda = mida - mina; float majda = maxa - mina; float a = setup->ebot.dy * majda - botda * setup->emaj.dy; @@ -506,21 +556,24 @@ static void tri_persp_coeff( struct setup_context *setup, /** * Special coefficient setup for gl_FragCoord. - * X and Y are trivial, though Y has to be inverted for OpenGL. + * X and Y are trivial, though Y may have to be inverted for OpenGL. * Z and W are copied from posCoef which should have already been computed. * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask. */ static void setup_fragcoord_coeff(struct setup_context *setup, uint slot) { + struct sp_fragment_shader* spfs = setup->softpipe->fs; /*X*/ - setup->coef[slot].a0[0] = 0; + setup->coef[slot].a0[0] = spfs->pixel_center_integer ? 0.0 : 0.5; setup->coef[slot].dadx[0] = 1.0; setup->coef[slot].dady[0] = 0.0; /*Y*/ - setup->coef[slot].a0[1] = 0.0; + setup->coef[slot].a0[1] = + (spfs->origin_lower_left ? setup->softpipe->framebuffer.height : 0) + + (spfs->pixel_center_integer ? 0.0 : 0.5); setup->coef[slot].dadx[1] = 0.0; - setup->coef[slot].dady[1] = 1.0; + setup->coef[slot].dady[1] = spfs->origin_lower_left ? -1.0 : 1.0; /*Z*/ setup->coef[slot].a0[2] = setup->posCoef.a0[2]; setup->coef[slot].dadx[2] = setup->posCoef.dadx[2]; @@ -543,11 +596,19 @@ static void setup_tri_coefficients( struct setup_context *setup ) const struct sp_fragment_shader *spfs = softpipe->fs; const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe); uint fragSlot; + float v[3]; /* z and w are done by linear interpolation: */ - tri_linear_coeff(setup, &setup->posCoef, 0, 2); - tri_linear_coeff(setup, &setup->posCoef, 0, 3); + v[0] = setup->vmin[0][2]; + v[1] = setup->vmid[0][2]; + v[2] = setup->vmax[0][2]; + tri_linear_coeff(setup, &setup->posCoef, 2, v); + + v[0] = setup->vmin[0][3]; + v[1] = setup->vmid[0][3]; + v[2] = setup->vmax[0][3]; + tri_linear_coeff(setup, &setup->posCoef, 3, v); /* setup interpolation for all the remaining attributes: */ @@ -561,12 +622,24 @@ static void setup_tri_coefficients( struct setup_context *setup ) const_coeff(setup, &setup->coef[fragSlot], vertSlot, j); break; case INTERP_LINEAR: - for (j = 0; j < NUM_CHANNELS; j++) - tri_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j); + for (j = 0; j < NUM_CHANNELS; j++) { + tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j], + setup->vmid[vertSlot][j], + setup->vmax[vertSlot][j], + spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j), + v); + tri_linear_coeff(setup, &setup->coef[fragSlot], j, v); + } break; case INTERP_PERSPECTIVE: - for (j = 0; j < NUM_CHANNELS; j++) - tri_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j); + for (j = 0; j < NUM_CHANNELS; j++) { + tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j], + setup->vmid[vertSlot][j], + setup->vmax[vertSlot][j], + spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j), + v); + tri_persp_coeff(setup, &setup->coef[fragSlot], j, v); + } break; case INTERP_POS: setup_fragcoord_coeff(setup, fragSlot); @@ -776,22 +849,49 @@ void sp_setup_tri( struct setup_context *setup, } +/* Apply cylindrical wrapping to v0, v1 coordinates, if enabled. + * Input coordinates must be in [0, 1] range, otherwise results are undefined. + */ +static void +line_apply_cylindrical_wrap(float v0, + float v1, + uint cylindrical_wrap, + float output[2]) +{ + if (cylindrical_wrap) { + float delta; + + delta = v1 - v0; + if (delta > 0.5f) { + v0 += 1.0f; + } + else if (delta < -0.5f) { + v1 += 1.0f; + } + } + + output[0] = v0; + output[1] = v1; +} + /** * Compute a0, dadx and dady for a linearly interpolated coefficient, * for a line. + * v[0] and v[1] are vmin and vmax, respectively. */ static void line_linear_coeff(const struct setup_context *setup, struct tgsi_interp_coef *coef, - uint vertSlot, uint i) + uint i, + const float v[2]) { - const float da = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i]; + const float da = v[1] - v[0]; const float dadx = da * setup->emaj.dx * setup->oneoverarea; const float dady = da * setup->emaj.dy * setup->oneoverarea; coef->dadx[i] = dadx; coef->dady[i] = dady; - coef->a0[i] = (setup->vmin[vertSlot][i] - + coef->a0[i] = (v[0] - (dadx * (setup->vmin[0][0] - setup->pixel_offset) + dady * (setup->vmin[0][1] - setup->pixel_offset))); } @@ -800,21 +900,22 @@ line_linear_coeff(const struct setup_context *setup, /** * Compute a0, dadx and dady for a perspective-corrected interpolant, * for a line. + * v[0] and v[1] are vmin and vmax, respectively. */ static void line_persp_coeff(const struct setup_context *setup, struct tgsi_interp_coef *coef, - uint vertSlot, uint i) + uint i, + const float v[2]) { - /* XXX double-check/verify this arithmetic */ - const float a0 = setup->vmin[vertSlot][i] * setup->vmin[0][3]; - const float a1 = setup->vmax[vertSlot][i] * setup->vmax[0][3]; + const float a0 = v[0] * setup->vmin[0][3]; + const float a1 = v[1] * setup->vmax[0][3]; const float da = a1 - a0; const float dadx = da * setup->emaj.dx * setup->oneoverarea; const float dady = da * setup->emaj.dy * setup->oneoverarea; coef->dadx[i] = dadx; coef->dady[i] = dady; - coef->a0[i] = (setup->vmin[vertSlot][i] - + coef->a0[i] = (a0 - (dadx * (setup->vmin[0][0] - setup->pixel_offset) + dady * (setup->vmin[0][1] - setup->pixel_offset))); } @@ -834,6 +935,7 @@ setup_line_coefficients(struct setup_context *setup, const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe); uint fragSlot; float area; + float v[2]; /* use setup->vmin, vmax to point to vertices */ if (softpipe->rasterizer->flatshade_first) @@ -854,8 +956,13 @@ setup_line_coefficients(struct setup_context *setup, /* z and w are done by linear interpolation: */ - line_linear_coeff(setup, &setup->posCoef, 0, 2); - line_linear_coeff(setup, &setup->posCoef, 0, 3); + v[0] = setup->vmin[0][2]; + v[1] = setup->vmax[0][2]; + line_linear_coeff(setup, &setup->posCoef, 2, v); + + v[0] = setup->vmin[0][3]; + v[1] = setup->vmax[0][3]; + line_linear_coeff(setup, &setup->posCoef, 3, v); /* setup interpolation for all the remaining attributes: */ @@ -869,12 +976,22 @@ setup_line_coefficients(struct setup_context *setup, const_coeff(setup, &setup->coef[fragSlot], vertSlot, j); break; case INTERP_LINEAR: - for (j = 0; j < NUM_CHANNELS; j++) - line_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j); + for (j = 0; j < NUM_CHANNELS; j++) { + line_apply_cylindrical_wrap(setup->vmin[vertSlot][j], + setup->vmax[vertSlot][j], + spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j), + v); + line_linear_coeff(setup, &setup->coef[fragSlot], j, v); + } break; case INTERP_PERSPECTIVE: - for (j = 0; j < NUM_CHANNELS; j++) - line_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j); + for (j = 0; j < NUM_CHANNELS; j++) { + line_apply_cylindrical_wrap(setup->vmin[vertSlot][j], + setup->vmax[vertSlot][j], + spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j), + v); + line_persp_coeff(setup, &setup->coef[fragSlot], j, v); + } break; case INTERP_POS: setup_fragcoord_coeff(setup, fragSlot); diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h index 9b18dac67b..a83cae7361 100644 --- a/src/gallium/drivers/softpipe/sp_state.h +++ b/src/gallium/drivers/softpipe/sp_state.h @@ -68,6 +68,9 @@ struct sp_fragment_shader { struct tgsi_shader_info info; + boolean origin_lower_left; /**< fragment shader uses lower left position origin? */ + boolean pixel_center_integer; /**< fragment shader uses integer pixel center? */ + void (*prepare)( const struct sp_fragment_shader *shader, struct tgsi_exec_machine *machine, struct tgsi_sampler **samplers); @@ -139,7 +142,7 @@ void softpipe_set_clip_state( struct pipe_context *, void softpipe_set_constant_buffer(struct pipe_context *, uint shader, uint index, - const struct pipe_constant_buffer *buf); + struct pipe_buffer *buf); void *softpipe_create_fs_state(struct pipe_context *, const struct pipe_shader_state *); @@ -200,6 +203,24 @@ softpipe_draw_range_elements(struct pipe_context *pipe, unsigned mode, unsigned start, unsigned count); void +softpipe_draw_arrays_instanced(struct pipe_context *pipe, + unsigned mode, + unsigned start, + unsigned count, + unsigned startInstance, + unsigned instanceCount); + +void +softpipe_draw_elements_instanced(struct pipe_context *pipe, + struct pipe_buffer *indexBuffer, + unsigned indexSize, + unsigned mode, + unsigned start, + unsigned count, + unsigned startInstance, + unsigned instanceCount); + +void softpipe_map_transfers(struct softpipe_context *sp); void diff --git a/src/gallium/drivers/softpipe/sp_state_derived.c b/src/gallium/drivers/softpipe/sp_state_derived.c index f6856a5f69..d2eda7324c 100644 --- a/src/gallium/drivers/softpipe/sp_state_derived.c +++ b/src/gallium/drivers/softpipe/sp_state_derived.c @@ -30,7 +30,6 @@ #include "pipe/p_shader_tokens.h" #include "draw/draw_context.h" #include "draw/draw_vertex.h" -#include "draw/draw_private.h" #include "sp_context.h" #include "sp_screen.h" #include "sp_state.h" @@ -67,7 +66,7 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe) /* compute vertex layout now */ const struct sp_fragment_shader *spfs = softpipe->fs; struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf; - const uint num = draw_current_shader_outputs(softpipe->draw); + const uint num = draw_num_shader_outputs(softpipe->draw); uint i; /* Tell draw_vbuf to simply emit the whole post-xform vertex diff --git a/src/gallium/drivers/softpipe/sp_state_fs.c b/src/gallium/drivers/softpipe/sp_state_fs.c index aa12bb215a..c88e213751 100644 --- a/src/gallium/drivers/softpipe/sp_state_fs.c +++ b/src/gallium/drivers/softpipe/sp_state_fs.c @@ -31,6 +31,7 @@ #include "pipe/p_defines.h" #include "util/u_memory.h" +#include "util/u_inlines.h" #include "draw/draw_context.h" #include "draw/draw_vs.h" #include "tgsi/tgsi_dump.h" @@ -44,6 +45,7 @@ softpipe_create_fs_state(struct pipe_context *pipe, { struct softpipe_context *softpipe = softpipe_context(pipe); struct sp_fragment_shader *state; + unsigned i; /* debug */ if (softpipe->dump_fs) @@ -60,6 +62,13 @@ softpipe_create_fs_state(struct pipe_context *pipe, /* get/save the summary info for this shader */ tgsi_scan_shader(templ->tokens, &state->info); + for (i = 0; i < state->info.num_properties; ++i) { + if (state->info.properties[i].name == TGSI_PROPERTY_FS_COORD_ORIGIN) + state->origin_lower_left = state->info.properties[i].data[0]; + else if (state->info.properties[i].name == TGSI_PROPERTY_FS_COORD_PIXEL_CENTER) + state->pixel_center_integer = state->info.properties[i].data[0]; + } + return state; } @@ -159,18 +168,17 @@ softpipe_delete_vs_state(struct pipe_context *pipe, void *vs) void softpipe_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - const struct pipe_constant_buffer *buf) + struct pipe_buffer *buf) { struct softpipe_context *softpipe = softpipe_context(pipe); assert(shader < PIPE_SHADER_TYPES); - assert(index == 0); + assert(index < PIPE_MAX_CONSTANT_BUFFERS); draw_flush(softpipe->draw); /* note: reference counting */ - pipe_buffer_reference(&softpipe->constants[shader].buffer, - buf ? buf->buffer : NULL); + pipe_buffer_reference(&softpipe->constants[shader][index], buf); softpipe->dirty |= SP_NEW_CONSTANTS; } diff --git a/src/gallium/drivers/softpipe/sp_state_surface.c b/src/gallium/drivers/softpipe/sp_state_surface.c index f6154109ea..2db6faeca4 100644 --- a/src/gallium/drivers/softpipe/sp_state_surface.c +++ b/src/gallium/drivers/softpipe/sp_state_surface.c @@ -30,12 +30,12 @@ #include "sp_context.h" #include "sp_state.h" -#include "sp_surface.h" #include "sp_tile_cache.h" #include "draw/draw_context.h" #include "util/u_format.h" +#include "util/u_inlines.h" /** diff --git a/src/gallium/drivers/softpipe/sp_state_vertex.c b/src/gallium/drivers/softpipe/sp_state_vertex.c index 46b6991195..b491d92ed1 100644 --- a/src/gallium/drivers/softpipe/sp_state_vertex.c +++ b/src/gallium/drivers/softpipe/sp_state_vertex.c @@ -31,7 +31,6 @@ #include "sp_context.h" #include "sp_state.h" -#include "sp_surface.h" #include "draw/draw_context.h" diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c index 1ae8fecacf..473ec3e150 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.c +++ b/src/gallium/drivers/softpipe/sp_tex_sample.c @@ -517,7 +517,6 @@ compute_lambda_1d(const struct sp_sampler_varient *samp, const float p[QUAD_SIZE]) { const struct pipe_texture *texture = samp->texture; - const struct pipe_sampler_state *sampler = samp->sampler; float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]); float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]); float rho = MAX2(dsdx, dsdy) * texture->width0; @@ -533,7 +532,6 @@ compute_lambda_2d(const struct sp_sampler_varient *samp, const float p[QUAD_SIZE]) { const struct pipe_texture *texture = samp->texture; - const struct pipe_sampler_state *sampler = samp->sampler; float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]); float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]); float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]); @@ -553,7 +551,6 @@ compute_lambda_3d(const struct sp_sampler_varient *samp, const float p[QUAD_SIZE]) { const struct pipe_texture *texture = samp->texture; - const struct pipe_sampler_state *sampler = samp->sampler; float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]); float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]); float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]); diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c index e50a76a73b..a0b95c8884 100644 --- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c @@ -32,12 +32,11 @@ * Brian Paul */ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_tile.h" #include "util/u_math.h" #include "sp_context.h" -#include "sp_surface.h" #include "sp_texture.h" #include "sp_tex_tile_cache.h" diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index a9436a3394..371c4e2025 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -31,14 +31,13 @@ */ #include "pipe/p_defines.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" #include "sp_context.h" -#include "sp_state.h" #include "sp_texture.h" #include "sp_screen.h" #include "sp_winsys.h" @@ -57,13 +56,8 @@ softpipe_texture_layout(struct pipe_screen *screen, unsigned width = pt->width0; unsigned height = pt->height0; unsigned depth = pt->depth0; - unsigned buffer_size = 0; - pt->width0 = width; - pt->height0 = height; - pt->depth0 = depth; - for (level = 0; level <= pt->last_level; level++) { spt->stride[level] = util_format_get_stride(pt->format, width); @@ -296,6 +290,10 @@ softpipe_get_tex_transfer(struct pipe_screen *screen, assert(texture); assert(level <= texture->last_level); + /* make sure the requested region is in the image bounds */ + assert(x + w <= u_minify(texture->width0, level)); + assert(y + h <= u_minify(texture->height0, level)); + spt = CALLOC_STRUCT(softpipe_transfer); if (spt) { struct pipe_transfer *pt = &spt->base; diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c index 112a6fe0cf..1b50bd7ffe 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tile_cache.c @@ -32,7 +32,7 @@ * Brian Paul */ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_format.h" #include "util/u_memory.h" #include "util/u_tile.h" diff --git a/src/gallium/drivers/softpipe/sp_video_context.c b/src/gallium/drivers/softpipe/sp_video_context.c index cfa2a0b2f1..d8b5b31e95 100644 --- a/src/gallium/drivers/softpipe/sp_video_context.c +++ b/src/gallium/drivers/softpipe/sp_video_context.c @@ -26,9 +26,8 @@ **************************************************************************/ #include "sp_video_context.h" -#include <pipe/p_inlines.h> +#include <util/u_inlines.h> #include <util/u_memory.h> -#include "softpipe/sp_winsys.h" #include "softpipe/sp_texture.h" static void @@ -185,17 +184,18 @@ init_pipe_state(struct sp_mpeg12_context *ctx) ctx->rast = ctx->pipe->create_rasterizer_state(ctx->pipe, &rast); ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rast); - blend.blend_enable = 0; - blend.rgb_func = PIPE_BLEND_ADD; - blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; - blend.rgb_dst_factor = PIPE_BLENDFACTOR_ONE; - blend.alpha_func = PIPE_BLEND_ADD; - blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; - blend.alpha_dst_factor = PIPE_BLENDFACTOR_ONE; + blend.independent_blend_enable = 0; + blend.rt[0].blend_enable = 0; + blend.rt[0].rgb_func = PIPE_BLEND_ADD; + blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_func = PIPE_BLEND_ADD; + blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; blend.logicop_enable = 0; blend.logicop_func = PIPE_LOGICOP_CLEAR; /* Needed to allow color writes to FB, even if blending disabled */ - blend.colormask = PIPE_MASK_RGBA; + blend.rt[0].colormask = PIPE_MASK_RGBA; blend.dither = 0; ctx->blend = ctx->pipe->create_blend_state(ctx->pipe, &blend); ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend); @@ -249,7 +249,7 @@ sp_mpeg12_create(struct pipe_screen *screen, enum pipe_video_profile profile, ctx->base.set_decode_target = sp_mpeg12_set_decode_target; ctx->base.set_csc_matrix = sp_mpeg12_set_csc_matrix; - ctx->pipe = softpipe_create(screen); + ctx->pipe = screen->context_create(screen, NULL); if (!ctx->pipe) { FREE(ctx); return NULL; diff --git a/src/gallium/drivers/softpipe/sp_winsys.c b/src/gallium/drivers/softpipe/sp_winsys.c new file mode 100644 index 0000000000..f6598927d3 --- /dev/null +++ b/src/gallium/drivers/softpipe/sp_winsys.c @@ -0,0 +1,245 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA + * 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 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 + * 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. + * + * + **************************************************************************/ + +/** + * @file + * Malloc softpipe winsys. Uses malloc for all memory allocations. + * + * @author Keith Whitwell + * @author Brian Paul + * @author Jose Fonseca + */ + + +#include "util/u_simple_screen.h"/* port to just p_screen */ +#include "pipe/p_format.h" +#include "pipe/p_context.h" +#include "util/u_format.h" +#include "util/u_math.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "softpipe/sp_winsys.h" + + +struct st_softpipe_buffer +{ + struct pipe_buffer base; + boolean userBuffer; /** Is this a user-space buffer? */ + void *data; + void *mapped; +}; + + +/** Cast wrapper */ +static INLINE struct st_softpipe_buffer * +st_softpipe_buffer( struct pipe_buffer *buf ) +{ + return (struct st_softpipe_buffer *)buf; +} + + +static void * +st_softpipe_buffer_map(struct pipe_winsys *winsys, + struct pipe_buffer *buf, + unsigned flags) +{ + struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf); + st_softpipe_buf->mapped = st_softpipe_buf->data; + return st_softpipe_buf->mapped; +} + + +static void +st_softpipe_buffer_unmap(struct pipe_winsys *winsys, + struct pipe_buffer *buf) +{ + struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf); + st_softpipe_buf->mapped = NULL; +} + + +static void +st_softpipe_buffer_destroy(struct pipe_buffer *buf) +{ + struct st_softpipe_buffer *oldBuf = st_softpipe_buffer(buf); + + if (oldBuf->data) { + if (!oldBuf->userBuffer) + align_free(oldBuf->data); + + oldBuf->data = NULL; + } + + FREE(oldBuf); +} + + +static void +st_softpipe_flush_frontbuffer(struct pipe_winsys *winsys, + struct pipe_surface *surf, + void *context_private) +{ +} + + + +static const char * +st_softpipe_get_name(struct pipe_winsys *winsys) +{ + return "softpipe"; +} + + +static struct pipe_buffer * +st_softpipe_buffer_create(struct pipe_winsys *winsys, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct st_softpipe_buffer *buffer = CALLOC_STRUCT(st_softpipe_buffer); + + pipe_reference_init(&buffer->base.reference, 1); + buffer->base.alignment = alignment; + buffer->base.usage = usage; + buffer->base.size = size; + + buffer->data = align_malloc(size, alignment); + + return &buffer->base; +} + + +/** + * Create buffer which wraps user-space data. + */ +static struct pipe_buffer * +st_softpipe_user_buffer_create(struct pipe_winsys *winsys, + void *ptr, + unsigned bytes) +{ + struct st_softpipe_buffer *buffer; + + buffer = CALLOC_STRUCT(st_softpipe_buffer); + if(!buffer) + return NULL; + + pipe_reference_init(&buffer->base.reference, 1); + buffer->base.size = bytes; + buffer->userBuffer = TRUE; + buffer->data = ptr; + + return &buffer->base; +} + + +static struct pipe_buffer * +st_softpipe_surface_buffer_create(struct pipe_winsys *winsys, + unsigned width, unsigned height, + enum pipe_format format, + unsigned usage, + unsigned tex_usage, + unsigned *stride) +{ + const unsigned alignment = 64; + unsigned nblocksy; + + nblocksy = util_format_get_nblocksy(format, height); + *stride = align(util_format_get_stride(format, width), alignment); + + return winsys->buffer_create(winsys, alignment, + usage, + *stride * nblocksy); +} + + +static void +st_softpipe_fence_reference(struct pipe_winsys *winsys, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ +} + + +static int +st_softpipe_fence_signalled(struct pipe_winsys *winsys, + struct pipe_fence_handle *fence, + unsigned flag) +{ + return 0; +} + + +static int +st_softpipe_fence_finish(struct pipe_winsys *winsys, + struct pipe_fence_handle *fence, + unsigned flag) +{ + return 0; +} + + +static void +st_softpipe_destroy(struct pipe_winsys *winsys) +{ + FREE(winsys); +} + + +struct pipe_screen * +softpipe_create_screen_malloc(void) +{ + static struct pipe_winsys *winsys; + struct pipe_screen *screen; + + winsys = CALLOC_STRUCT(pipe_winsys); + if(!winsys) + return NULL; + + winsys->destroy = st_softpipe_destroy; + + winsys->buffer_create = st_softpipe_buffer_create; + winsys->user_buffer_create = st_softpipe_user_buffer_create; + winsys->buffer_map = st_softpipe_buffer_map; + winsys->buffer_unmap = st_softpipe_buffer_unmap; + winsys->buffer_destroy = st_softpipe_buffer_destroy; + + winsys->surface_buffer_create = st_softpipe_surface_buffer_create; + + winsys->fence_reference = st_softpipe_fence_reference; + winsys->fence_signalled = st_softpipe_fence_signalled; + winsys->fence_finish = st_softpipe_fence_finish; + + winsys->flush_frontbuffer = st_softpipe_flush_frontbuffer; + winsys->get_name = st_softpipe_get_name; + + screen = softpipe_create_screen(winsys); + if(!screen) + st_softpipe_destroy(winsys); + + return screen; +} diff --git a/src/gallium/drivers/softpipe/sp_winsys.h b/src/gallium/drivers/softpipe/sp_winsys.h index f203ded29e..6e3920c49b 100644 --- a/src/gallium/drivers/softpipe/sp_winsys.h +++ b/src/gallium/drivers/softpipe/sp_winsys.h @@ -47,12 +47,18 @@ struct pipe_texture; struct pipe_buffer; -struct pipe_context *softpipe_create( struct pipe_screen * ); +/** + * Create a softpipe screen that uses the + * given winsys for allocating buffers. + */ +struct pipe_screen *softpipe_create_screen( struct pipe_winsys * ); -struct pipe_screen * -softpipe_create_screen(struct pipe_winsys *); - +/** + * Create a softpipe screen that uses + * regular malloc to create all its buffers. + */ +struct pipe_screen *softpipe_create_screen_malloc(void); boolean softpipe_get_texture_buffer( struct pipe_texture *texture, diff --git a/src/gallium/drivers/svga/svga_context.c b/src/gallium/drivers/svga/svga_context.c index af99c9de37..d499ae6acc 100644 --- a/src/gallium/drivers/svga/svga_context.c +++ b/src/gallium/drivers/svga/svga_context.c @@ -26,7 +26,7 @@ #include "svga_cmd.h" #include "pipe/p_defines.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_screen.h" #include "util/u_memory.h" #include "util/u_bitmask.h" @@ -126,7 +126,8 @@ svga_is_buffer_referenced( struct pipe_context *pipe, } -struct pipe_context *svga_context_create( struct pipe_screen *screen ) +struct pipe_context *svga_context_create( struct pipe_screen *screen, + void *priv ) { struct svga_screen *svgascreen = svga_screen(screen); struct svga_context *svga = NULL; @@ -138,6 +139,7 @@ struct pipe_context *svga_context_create( struct pipe_screen *screen ) svga->pipe.winsys = screen->winsys; svga->pipe.screen = screen; + svga->pipe.priv = priv; svga->pipe.destroy = svga_destroy; svga->pipe.clear = svga_clear; @@ -215,7 +217,6 @@ struct pipe_context *svga_context_create( struct pipe_screen *screen ) svga->state.hw_draw.num_views = 0; svga->dirty = ~0; - svga->state.white_fs_id = SVGA3D_INVALID_ID; LIST_INITHEAD(&svga->dirty_buffers); diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h index e2a96034d1..f9a641c6df 100644 --- a/src/gallium/drivers/svga/svga_context.h +++ b/src/gallium/drivers/svga/svga_context.h @@ -326,10 +326,6 @@ struct svga_context unsigned texture_timestamp; - /* Internally generated shaders: - */ - unsigned white_fs_id; - /* */ struct svga_sw_state sw; @@ -429,6 +425,10 @@ void svga_context_flush( struct svga_context *svga, void svga_hwtnl_flush_retry( struct svga_context *svga ); +struct pipe_context * +svga_context_create(struct pipe_screen *screen, + void *priv); + /*********************************************************************** * Inline conversion functions. These are better-typed than the diff --git a/src/gallium/drivers/svga/svga_draw.c b/src/gallium/drivers/svga/svga_draw.c index ca73cf9d5a..f4d2d8992c 100644 --- a/src/gallium/drivers/svga/svga_draw.c +++ b/src/gallium/drivers/svga/svga_draw.c @@ -24,7 +24,7 @@ **********************************************************/ #include "pipe/p_compiler.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_defines.h" #include "util/u_memory.h" #include "util/u_math.h" diff --git a/src/gallium/drivers/svga/svga_draw_arrays.c b/src/gallium/drivers/svga/svga_draw_arrays.c index 75492dffca..6192aa96b1 100644 --- a/src/gallium/drivers/svga/svga_draw_arrays.c +++ b/src/gallium/drivers/svga/svga_draw_arrays.c @@ -25,8 +25,7 @@ #include "svga_cmd.h" -#include "pipe/p_inlines.h" -#include "util/u_prim.h" +#include "util/u_inlines.h" #include "indices/u_indices.h" #include "svga_hw_reg.h" diff --git a/src/gallium/drivers/svga/svga_draw_elements.c b/src/gallium/drivers/svga/svga_draw_elements.c index 167d817831..e8097d82f1 100644 --- a/src/gallium/drivers/svga/svga_draw_elements.c +++ b/src/gallium/drivers/svga/svga_draw_elements.c @@ -23,8 +23,7 @@ * **********************************************************/ -#include "pipe/p_inlines.h" -#include "util/u_prim.h" +#include "util/u_inlines.h" #include "util/u_upload_mgr.h" #include "indices/u_indices.h" diff --git a/src/gallium/drivers/svga/svga_pipe_blend.c b/src/gallium/drivers/svga/svga_pipe_blend.c index 855d228755..9dd6fb068c 100644 --- a/src/gallium/drivers/svga/svga_pipe_blend.c +++ b/src/gallium/drivers/svga/svga_pipe_blend.c @@ -23,13 +23,12 @@ * **********************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_defines.h" #include "util/u_math.h" #include "util/u_memory.h" #include "svga_context.h" -#include "svga_state.h" #include "svga_hw_reg.h" @@ -182,15 +181,15 @@ svga_create_blend_state(struct pipe_context *pipe, } } else { - blend->rt[i].blend_enable = templ->blend_enable; + blend->rt[i].blend_enable = templ->rt[0].blend_enable; - if (templ->blend_enable) { - blend->rt[i].srcblend = svga_translate_blend_factor(templ->rgb_src_factor); - blend->rt[i].dstblend = svga_translate_blend_factor(templ->rgb_dst_factor); - blend->rt[i].blendeq = svga_translate_blend_func(templ->rgb_func); - blend->rt[i].srcblend_alpha = svga_translate_blend_factor(templ->alpha_src_factor); - blend->rt[i].dstblend_alpha = svga_translate_blend_factor(templ->alpha_dst_factor); - blend->rt[i].blendeq_alpha = svga_translate_blend_func(templ->alpha_func); + if (templ->rt[0].blend_enable) { + blend->rt[i].srcblend = svga_translate_blend_factor(templ->rt[0].rgb_src_factor); + blend->rt[i].dstblend = svga_translate_blend_factor(templ->rt[0].rgb_dst_factor); + blend->rt[i].blendeq = svga_translate_blend_func(templ->rt[0].rgb_func); + blend->rt[i].srcblend_alpha = svga_translate_blend_factor(templ->rt[0].alpha_src_factor); + blend->rt[i].dstblend_alpha = svga_translate_blend_factor(templ->rt[0].alpha_dst_factor); + blend->rt[i].blendeq_alpha = svga_translate_blend_func(templ->rt[0].alpha_func); if (blend->rt[i].srcblend_alpha != blend->rt[i].srcblend || blend->rt[i].dstblend_alpha != blend->rt[i].dstblend || @@ -201,7 +200,7 @@ svga_create_blend_state(struct pipe_context *pipe, } } - blend->rt[i].writemask = templ->colormask; + blend->rt[i].writemask = templ->rt[0].colormask; } return blend; diff --git a/src/gallium/drivers/svga/svga_pipe_constants.c b/src/gallium/drivers/svga/svga_pipe_constants.c index 10e7a12189..73a0cd6b3a 100644 --- a/src/gallium/drivers/svga/svga_pipe_constants.c +++ b/src/gallium/drivers/svga/svga_pipe_constants.c @@ -23,16 +23,12 @@ * **********************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_defines.h" #include "util/u_math.h" -#include "util/u_memory.h" #include "tgsi/tgsi_parse.h" #include "svga_context.h" -#include "svga_state.h" -#include "svga_hw_reg.h" -#include "svga_cmd.h" /*********************************************************************** * Constant buffers @@ -49,7 +45,7 @@ struct svga_constbuf static void svga_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, - const struct pipe_constant_buffer *buf) + struct pipe_buffer *buf) { struct svga_context *svga = svga_context(pipe); @@ -57,7 +53,7 @@ static void svga_set_constant_buffer(struct pipe_context *pipe, assert(index == 0); pipe_buffer_reference( &svga->curr.cb[shader], - buf->buffer ); + buf ); if (shader == PIPE_SHADER_FRAGMENT) svga->dirty |= SVGA_NEW_FS_CONST_BUFFER; diff --git a/src/gallium/drivers/svga/svga_pipe_depthstencil.c b/src/gallium/drivers/svga/svga_pipe_depthstencil.c index df636c08a0..12bbd233a5 100644 --- a/src/gallium/drivers/svga/svga_pipe_depthstencil.c +++ b/src/gallium/drivers/svga/svga_pipe_depthstencil.c @@ -23,13 +23,12 @@ * **********************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_defines.h" #include "util/u_math.h" #include "util/u_memory.h" #include "svga_context.h" -#include "svga_state.h" #include "svga_hw_reg.h" diff --git a/src/gallium/drivers/svga/svga_pipe_draw.c b/src/gallium/drivers/svga/svga_pipe_draw.c index 0f24ef4ee8..f00cf23935 100644 --- a/src/gallium/drivers/svga/svga_pipe_draw.c +++ b/src/gallium/drivers/svga/svga_pipe_draw.c @@ -25,7 +25,7 @@ #include "svga_cmd.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_prim.h" #include "util/u_time.h" #include "indices/u_indices.h" @@ -33,7 +33,6 @@ #include "svga_hw_reg.h" #include "svga_context.h" #include "svga_screen.h" -#include "svga_winsys.h" #include "svga_draw.h" #include "svga_state.h" #include "svga_swtnl.h" @@ -217,11 +216,6 @@ svga_draw_range_elements( struct pipe_context *pipe, } if (SVGA_DEBUG & DEBUG_FLUSH) { - static unsigned id; - debug_printf("%s %d\n", __FUNCTION__, id++); - if (id > 1300) - util_time_sleep( 2000 ); - svga_hwtnl_flush_retry( svga ); svga_context_flush(svga, NULL); } diff --git a/src/gallium/drivers/svga/svga_pipe_flush.c b/src/gallium/drivers/svga/svga_pipe_flush.c index 0becb0765a..7fa2205ae5 100644 --- a/src/gallium/drivers/svga/svga_pipe_flush.c +++ b/src/gallium/drivers/svga/svga_pipe_flush.c @@ -27,14 +27,8 @@ #include "svga_screen.h" #include "svga_screen_texture.h" #include "svga_context.h" -#include "svga_winsys.h" -#include "svga_draw.h" #include "svga_debug.h" -#include "svga_hw_reg.h" - - - static void svga_flush( struct pipe_context *pipe, unsigned flags, diff --git a/src/gallium/drivers/svga/svga_pipe_fs.c b/src/gallium/drivers/svga/svga_pipe_fs.c index 5f1213e46a..b71bc66552 100644 --- a/src/gallium/drivers/svga/svga_pipe_fs.c +++ b/src/gallium/drivers/svga/svga_pipe_fs.c @@ -23,20 +23,17 @@ * **********************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_bitmask.h" #include "tgsi/tgsi_parse.h" -#include "tgsi/tgsi_text.h" #include "svga_screen.h" #include "svga_context.h" -#include "svga_state.h" #include "svga_tgsi.h" #include "svga_hw_reg.h" #include "svga_cmd.h" -#include "svga_draw.h" #include "svga_debug.h" diff --git a/src/gallium/drivers/svga/svga_pipe_misc.c b/src/gallium/drivers/svga/svga_pipe_misc.c index 58cb1e6e23..49b43bebc2 100644 --- a/src/gallium/drivers/svga/svga_pipe_misc.c +++ b/src/gallium/drivers/svga/svga_pipe_misc.c @@ -25,14 +25,10 @@ #include "svga_cmd.h" +#include "util/u_inlines.h" + #include "svga_context.h" #include "svga_screen_texture.h" -#include "svga_state.h" -#include "svga_winsys.h" - -#include "svga_hw_reg.h" - - static void svga_set_scissor_state( struct pipe_context *pipe, diff --git a/src/gallium/drivers/svga/svga_pipe_query.c b/src/gallium/drivers/svga/svga_pipe_query.c index 01336b0a2c..08283e3731 100644 --- a/src/gallium/drivers/svga/svga_pipe_query.c +++ b/src/gallium/drivers/svga/svga_pipe_query.c @@ -32,7 +32,6 @@ #include "svga_screen.h" #include "svga_screen_buffer.h" #include "svga_winsys.h" -#include "svga_draw.h" #include "svga_debug.h" diff --git a/src/gallium/drivers/svga/svga_pipe_rasterizer.c b/src/gallium/drivers/svga/svga_pipe_rasterizer.c index 09ccb71884..3571778867 100644 --- a/src/gallium/drivers/svga/svga_pipe_rasterizer.c +++ b/src/gallium/drivers/svga/svga_pipe_rasterizer.c @@ -24,13 +24,12 @@ **********************************************************/ #include "draw/draw_context.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_defines.h" #include "util/u_math.h" #include "util/u_memory.h" #include "svga_context.h" -#include "svga_state.h" #include "svga_hw_reg.h" diff --git a/src/gallium/drivers/svga/svga_pipe_sampler.c b/src/gallium/drivers/svga/svga_pipe_sampler.c index 460a101f8c..b70081343d 100644 --- a/src/gallium/drivers/svga/svga_pipe_sampler.c +++ b/src/gallium/drivers/svga/svga_pipe_sampler.c @@ -23,7 +23,7 @@ * **********************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_defines.h" #include "util/u_math.h" #include "util/u_memory.h" @@ -32,9 +32,6 @@ #include "svga_context.h" #include "svga_screen_texture.h" -#include "svga_state.h" - -#include "svga_hw_reg.h" #include "svga_debug.h" diff --git a/src/gallium/drivers/svga/svga_pipe_vertex.c b/src/gallium/drivers/svga/svga_pipe_vertex.c index 42f290d162..ffc0f99565 100644 --- a/src/gallium/drivers/svga/svga_pipe_vertex.c +++ b/src/gallium/drivers/svga/svga_pipe_vertex.c @@ -23,19 +23,14 @@ * **********************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_defines.h" #include "util/u_math.h" -#include "util/u_memory.h" #include "tgsi/tgsi_parse.h" #include "svga_screen.h" #include "svga_screen_buffer.h" #include "svga_context.h" -#include "svga_state.h" -#include "svga_winsys.h" - -#include "svga_hw_reg.h" static void svga_set_vertex_buffers(struct pipe_context *pipe, diff --git a/src/gallium/drivers/svga/svga_pipe_vs.c b/src/gallium/drivers/svga/svga_pipe_vs.c index 7e6ab576ad..de8c919e12 100644 --- a/src/gallium/drivers/svga/svga_pipe_vs.c +++ b/src/gallium/drivers/svga/svga_pipe_vs.c @@ -24,7 +24,7 @@ **********************************************************/ #include "draw/draw_context.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_bitmask.h" @@ -33,7 +33,6 @@ #include "svga_screen.h" #include "svga_context.h" -#include "svga_state.h" #include "svga_tgsi.h" #include "svga_hw_reg.h" #include "svga_cmd.h" diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c index 45b5d85ae2..8143be5024 100644 --- a/src/gallium/drivers/svga/svga_screen.c +++ b/src/gallium/drivers/svga/svga_screen.c @@ -24,7 +24,7 @@ **********************************************************/ #include "util/u_memory.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_string.h" #include "util/u_math.h" @@ -33,10 +33,8 @@ #include "svga_screen.h" #include "svga_screen_texture.h" #include "svga_screen_buffer.h" -#include "svga_cmd.h" #include "svga_debug.h" -#include "svga_hw_reg.h" #include "svga3d_shaderdefs.h" @@ -146,6 +144,13 @@ svga_get_paramf(struct pipe_screen *screen, int param) case PIPE_CAP_BLEND_EQUATION_SEPARATE: /* req. for GL 1.5 */ return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER: + return 1; + case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT: + case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER: + return 0; + default: return 0; } @@ -361,6 +366,7 @@ svga_screen_create(struct svga_winsys_screen *sws) screen->get_param = svga_get_param; screen->get_paramf = svga_get_paramf; screen->is_format_supported = svga_is_format_supported; + screen->context_create = svga_context_create; screen->fence_reference = svga_fence_reference; screen->fence_signalled = svga_fence_signalled; screen->fence_finish = svga_fence_finish; @@ -393,8 +399,6 @@ svga_screen_create(struct svga_winsys_screen *sws) pipe_mutex_init(svgascreen->tex_mutex); pipe_mutex_init(svgascreen->swc_mutex); - LIST_INITHEAD(&svgascreen->cached_buffers); - svga_screen_cache_init(svgascreen); return screen; diff --git a/src/gallium/drivers/svga/svga_screen.h b/src/gallium/drivers/svga/svga_screen.h index b94ca7fc1c..9dc229b0a8 100644 --- a/src/gallium/drivers/svga/svga_screen.h +++ b/src/gallium/drivers/svga/svga_screen.h @@ -28,7 +28,7 @@ #include "pipe/p_screen.h" -#include "pipe/p_thread.h" +#include "os/os_thread.h" #include "util/u_double_list.h" @@ -68,12 +68,6 @@ struct svga_screen pipe_mutex tex_mutex; pipe_mutex swc_mutex; /* Protects the use of swc and dirty_buffers */ - /** - * List of buffers with cached GMR. Ordered from the most recently used to - * the least recently used - */ - struct list_head cached_buffers; - struct svga_host_surface_cache cache; }; diff --git a/src/gallium/drivers/svga/svga_screen_buffer.c b/src/gallium/drivers/svga/svga_screen_buffer.c index 58a1aba464..c9e9bef540 100644 --- a/src/gallium/drivers/svga/svga_screen_buffer.c +++ b/src/gallium/drivers/svga/svga_screen_buffer.c @@ -27,8 +27,8 @@ #include "pipe/p_state.h" #include "pipe/p_defines.h" -#include "pipe/p_inlines.h" -#include "pipe/p_thread.h" +#include "util/u_inlines.h" +#include "os/os_thread.h" #include "util/u_math.h" #include "util/u_memory.h" @@ -113,68 +113,9 @@ svga_buffer_destroy_hw_storage(struct svga_screen *ss, struct svga_buffer *sbuf) if(sbuf->hw.buf) { sws->buffer_destroy(sws, sbuf->hw.buf); sbuf->hw.buf = NULL; - assert(sbuf->head.prev && sbuf->head.next); - LIST_DEL(&sbuf->head); -#ifdef DEBUG - sbuf->head.next = sbuf->head.prev = NULL; -#endif } } -static INLINE enum pipe_error -svga_buffer_backup(struct svga_screen *ss, struct svga_buffer *sbuf) -{ - if (sbuf->hw.buf && sbuf->hw.num_ranges) { - void *src; - - if (!sbuf->swbuf) - sbuf->swbuf = align_malloc(sbuf->base.size, sbuf->base.alignment); - if (!sbuf->swbuf) - return PIPE_ERROR_OUT_OF_MEMORY; - - src = ss->sws->buffer_map(ss->sws, sbuf->hw.buf, - PIPE_BUFFER_USAGE_CPU_READ); - if (!src) - return PIPE_ERROR; - - memcpy(sbuf->swbuf, src, sbuf->base.size); - ss->sws->buffer_unmap(ss->sws, sbuf->hw.buf); - } - - return PIPE_OK; -} - -/** - * Try to make GMR space available by freeing the hardware storage of - * unmapped - */ -boolean -svga_buffer_free_cached_hw_storage(struct svga_screen *ss) -{ - struct list_head *curr; - struct svga_buffer *sbuf; - enum pipe_error ret = PIPE_OK; - - curr = ss->cached_buffers.prev; - - /* free the least recently used buffer's hw storage which is not mapped */ - do { - if(curr == &ss->cached_buffers) - return FALSE; - - sbuf = LIST_ENTRY(struct svga_buffer, curr, head); - - curr = curr->prev; - if (sbuf->map.count == 0) - ret = svga_buffer_backup(ss, sbuf); - - } while(sbuf->map.count != 0 || ret != PIPE_OK); - - svga_buffer_destroy_hw_storage(ss, sbuf); - - return TRUE; -} - struct svga_winsys_buffer * svga_winsys_buffer_create( struct svga_screen *ss, unsigned alignment, @@ -195,12 +136,6 @@ svga_winsys_buffer_create( struct svga_screen *ss, svga_screen_flush(ss, NULL); buf = sws->buffer_create(sws, alignment, usage, size); - SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "evicting buffers to find %d bytes GMR\n", - size); - - /* Try evicing all buffer storage */ - while(!buf && svga_buffer_free_cached_hw_storage(ss)) - buf = sws->buffer_create(sws, alignment, usage, size); } return buf; @@ -226,8 +161,6 @@ svga_buffer_create_hw_storage(struct svga_screen *ss, return PIPE_ERROR_OUT_OF_MEMORY; assert(!sbuf->needs_flush); - assert(!sbuf->head.prev && !sbuf->head.next); - LIST_ADD(&sbuf->head, &ss->cached_buffers); } return PIPE_OK; @@ -311,7 +244,6 @@ static void svga_buffer_upload_flush(struct svga_context *svga, struct svga_buffer *sbuf) { - struct svga_screen *ss = svga_screen(svga->pipe.screen); SVGA3dCopyBox *boxes; unsigned i; @@ -348,13 +280,16 @@ svga_buffer_upload_flush(struct svga_context *svga, assert(sbuf->head.prev && sbuf->head.next); LIST_DEL(&sbuf->head); +#ifdef DEBUG + sbuf->head.next = sbuf->head.prev = NULL; +#endif sbuf->needs_flush = FALSE; - /* XXX: do we care about cached_buffers any more ?*/ - LIST_ADD(&sbuf->head, &ss->cached_buffers); sbuf->hw.svga = NULL; sbuf->hw.boxes = NULL; + sbuf->host_written = TRUE; + /* Decrement reference count */ pipe_reference(&(sbuf->base.reference), NULL); sbuf = NULL; @@ -437,17 +372,17 @@ svga_buffer_map_range( struct pipe_screen *screen, } else { if(!sbuf->hw.buf) { - struct svga_winsys_surface *handle = sbuf->handle; - if(svga_buffer_create_hw_storage(ss, sbuf) != PIPE_OK) return NULL; /* Populate the hardware storage if the host surface pre-existed */ - if((usage & PIPE_BUFFER_USAGE_CPU_READ) && handle) { + if(sbuf->host_written) { SVGA3dSurfaceDMAFlags flags; enum pipe_error ret; struct pipe_fence_handle *fence = NULL; + assert(sbuf->handle); + SVGA_DBG(DEBUG_DMA|DEBUG_PERF, "dma from sid %p (buffer), bytes %u - %u\n", sbuf->handle, 0, sbuf->base.size); @@ -478,17 +413,6 @@ svga_buffer_map_range( struct pipe_screen *screen, sws->fence_reference(sws, &fence, NULL); } } - else { - if((usage & PIPE_BUFFER_USAGE_CPU_READ) && !sbuf->needs_flush) { - /* We already had the hardware storage but we would have to issue - * a download if we hadn't, so move the buffer to the begginning - * of the LRU list. - */ - assert(sbuf->head.prev && sbuf->head.next); - LIST_DEL(&sbuf->head); - LIST_ADD(&sbuf->head, &ss->cached_buffers); - } - } map = sws->buffer_map(sws, sbuf->hw.buf, usage); } @@ -572,10 +496,8 @@ svga_buffer_destroy( struct pipe_buffer *buf ) assert(!sbuf->needs_flush); - if(sbuf->handle) { - SVGA_DBG(DEBUG_DMA, "release sid %p sz %d\n", sbuf->handle, sbuf->base.size); - svga_screen_surface_destroy(ss, &sbuf->key, &sbuf->handle); - } + if(sbuf->handle) + svga_buffer_destroy_host_surface(ss, sbuf); if(sbuf->hw.buf) svga_buffer_destroy_hw_storage(ss, sbuf); @@ -595,6 +517,9 @@ svga_buffer_create(struct pipe_screen *screen, struct svga_screen *ss = svga_screen(screen); struct svga_buffer *sbuf; + assert(size); + assert(alignment); + sbuf = CALLOC_STRUCT(svga_buffer); if(!sbuf) goto error1; @@ -755,8 +680,7 @@ svga_buffer_handle(struct svga_context *svga, assert(sbuf->hw.svga == svga); sbuf->needs_flush = TRUE; - assert(sbuf->head.prev && sbuf->head.next); - LIST_DEL(&sbuf->head); + assert(!sbuf->head.prev && !sbuf->head.next); LIST_ADDTAIL(&sbuf->head, &svga->dirty_buffers); } diff --git a/src/gallium/drivers/svga/svga_screen_buffer.h b/src/gallium/drivers/svga/svga_screen_buffer.h index 5d7af5a7c5..448ac107c7 100644 --- a/src/gallium/drivers/svga/svga_screen_buffer.h +++ b/src/gallium/drivers/svga/svga_screen_buffer.h @@ -135,6 +135,11 @@ struct svga_buffer */ struct svga_winsys_surface *handle; + /** + * Whether the host has been ever written. + */ + boolean host_written; + struct { unsigned count; boolean writing; @@ -178,9 +183,6 @@ svga_buffer_handle(struct svga_context *svga, void svga_context_flush_buffers(struct svga_context *svga); -boolean -svga_buffer_free_cached_hw_storage(struct svga_screen *ss); - struct svga_winsys_buffer * svga_winsys_buffer_create(struct svga_screen *ss, unsigned alignment, diff --git a/src/gallium/drivers/svga/svga_screen_cache.h b/src/gallium/drivers/svga/svga_screen_cache.h index f5aa740d40..62156e3f52 100644 --- a/src/gallium/drivers/svga/svga_screen_cache.h +++ b/src/gallium/drivers/svga/svga_screen_cache.h @@ -31,7 +31,7 @@ #include "svga_reg.h" #include "svga3d_reg.h" -#include "pipe/p_thread.h" +#include "os/os_thread.h" #include "util/u_double_list.h" diff --git a/src/gallium/drivers/svga/svga_screen_texture.c b/src/gallium/drivers/svga/svga_screen_texture.c index 2224c2d394..12f3531a1d 100644 --- a/src/gallium/drivers/svga/svga_screen_texture.c +++ b/src/gallium/drivers/svga/svga_screen_texture.c @@ -27,8 +27,8 @@ #include "pipe/p_state.h" #include "pipe/p_defines.h" -#include "pipe/p_inlines.h" -#include "pipe/p_thread.h" +#include "util/u_inlines.h" +#include "os/os_thread.h" #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" @@ -205,7 +205,7 @@ svga_transfer_dma(struct svga_transfer *st, if(transfer == SVGA3D_READ_HOST_VRAM) { svga_screen_flush(screen, &fence); sws->fence_finish(sws, fence, 0); - //sws->fence_reference(sws, &fence, NULL); + sws->fence_reference(sws, &fence, NULL); } } else { @@ -235,7 +235,7 @@ svga_transfer_dma(struct svga_transfer *st, if(y) { svga_screen_flush(screen, &fence); sws->fence_finish(sws, fence, 0); - //sws->fence_reference(sws, &fence, NULL); + sws->fence_reference(sws, &fence, NULL); } hw = sws->buffer_map(sws, st->hwbuf, PIPE_BUFFER_USAGE_CPU_WRITE); @@ -306,11 +306,19 @@ svga_texture_create(struct pipe_screen *screen, tex->key.numFaces = 1; } + tex->key.cachable = 1; + if(templat->tex_usage & PIPE_TEXTURE_USAGE_SAMPLER) tex->key.flags |= SVGA3D_SURFACE_HINT_TEXTURE; - if(templat->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) + if(templat->tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) { + tex->key.cachable = 0; + } + + if(templat->tex_usage & PIPE_TEXTURE_USAGE_PRIMARY) { tex->key.flags |= SVGA3D_SURFACE_HINT_SCANOUT; + tex->key.cachable = 0; + } /* * XXX: Never pass the SVGA3D_SURFACE_HINT_RENDERTARGET hint. Mesa cannot @@ -333,8 +341,6 @@ svga_texture_create(struct pipe_screen *screen, if(tex->key.format == SVGA3D_FORMAT_INVALID) goto error2; - tex->key.cachable = 1; - SVGA_DBG(DEBUG_DMA, "surface_create for texture\n", tex->handle); tex->handle = svga_screen_surface_create(svgascreen, &tex->key); if (tex->handle) @@ -416,6 +422,62 @@ svga_texture_blanket(struct pipe_screen * screen, } +struct pipe_texture * +svga_screen_texture_wrap_surface(struct pipe_screen *screen, + struct pipe_texture *base, + enum SVGA3dSurfaceFormat format, + struct svga_winsys_surface *srf) +{ + struct svga_texture *tex; + assert(screen); + + /* Only supports one type */ + if (base->target != PIPE_TEXTURE_2D || + base->last_level != 0 || + base->depth0 != 1) { + return NULL; + } + + if (!srf) + return NULL; + + if (svga_translate_format(base->format) != format) { + unsigned f1 = svga_translate_format(base->format); + unsigned f2 = format; + + /* It's okay for XRGB and ARGB or depth with/out stencil to get mixed up */ + if ( !( (f1 == SVGA3D_X8R8G8B8 && f2 == SVGA3D_A8R8G8B8) || + (f1 == SVGA3D_A8R8G8B8 && f2 == SVGA3D_X8R8G8B8) || + (f1 == SVGA3D_Z_D24X8 && f2 == SVGA3D_Z_D24S8) ) ) { + debug_printf("%s wrong format %u != %u\n", __FUNCTION__, f1, f2); + return NULL; + } + } + + tex = CALLOC_STRUCT(svga_texture); + if (!tex) + return NULL; + + tex->base = *base; + + + if (format == 1) + tex->base.format = PIPE_FORMAT_X8R8G8B8_UNORM; + else if (format == 2) + tex->base.format = PIPE_FORMAT_A8R8G8B8_UNORM; + + pipe_reference_init(&tex->base.reference, 1); + tex->base.screen = screen; + + SVGA_DBG(DEBUG_DMA, "wrap surface sid %p\n", srf); + + tex->key.cachable = 0; + tex->handle = srf; + + return &tex->base; +} + + static void svga_texture_destroy(struct pipe_texture *pt) { diff --git a/src/gallium/drivers/svga/svga_screen_texture.h b/src/gallium/drivers/svga/svga_screen_texture.h index 89ae24219f..43853d48f8 100644 --- a/src/gallium/drivers/svga/svga_screen_texture.h +++ b/src/gallium/drivers/svga/svga_screen_texture.h @@ -29,6 +29,7 @@ #include "pipe/p_compiler.h" #include "pipe/p_state.h" +#include "util/u_inlines.h" #include "svga_screen_cache.h" struct pipe_context; diff --git a/src/gallium/drivers/svga/svga_state_constants.c b/src/gallium/drivers/svga/svga_state_constants.c index 6b0e511cec..bb92f818ea 100644 --- a/src/gallium/drivers/svga/svga_state_constants.c +++ b/src/gallium/drivers/svga/svga_state_constants.c @@ -23,7 +23,7 @@ * **********************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_defines.h" #include "svga_context.h" diff --git a/src/gallium/drivers/svga/svga_state_framebuffer.c b/src/gallium/drivers/svga/svga_state_framebuffer.c index cfdcae4ee4..b4cafb8f21 100644 --- a/src/gallium/drivers/svga/svga_state_framebuffer.c +++ b/src/gallium/drivers/svga/svga_state_framebuffer.c @@ -23,7 +23,7 @@ * **********************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_defines.h" #include "util/u_math.h" @@ -32,8 +32,6 @@ #include "svga_cmd.h" #include "svga_debug.h" -#include "svga_hw_reg.h" - /*********************************************************************** * Hardware state update diff --git a/src/gallium/drivers/svga/svga_state_fs.c b/src/gallium/drivers/svga/svga_state_fs.c index d29f3762d2..2973444d0a 100644 --- a/src/gallium/drivers/svga/svga_state_fs.c +++ b/src/gallium/drivers/svga/svga_state_fs.c @@ -23,7 +23,7 @@ * **********************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_defines.h" #include "util/u_math.h" #include "util/u_bitmask.h" @@ -81,8 +81,10 @@ static enum pipe_error compile_fs( struct svga_context *svga, } result->id = util_bitmask_add(svga->fs_bm); - if(result->id == UTIL_BITMASK_INVALID_INDEX) + if(result->id == UTIL_BITMASK_INVALID_INDEX) { + ret = PIPE_ERROR_OUT_OF_MEMORY; goto fail; + } ret = SVGA3D_DefineShader(svga->swc, result->id, @@ -106,70 +108,6 @@ fail: return ret; } -/* The blend workaround for simulating logicop xor behaviour requires - * that the incoming fragment color be white. This change achieves - * that by hooking up a hard-wired fragment shader that just emits - * color 1,1,1,1 - * - * This is a slightly incomplete solution as it assumes that the - * actual bound shader has no other effects beyond generating a - * fragment color. In particular shaders containing TEXKIL and/or - * depth-write will not have the correct behaviour, nor will those - * expecting to use alphatest. - * - * These are avoidable issues, but they are not much worse than the - * unavoidable ones associated with this technique, so it's not clear - * how much effort should be expended trying to resolve them - the - * ultimate result will still not be correct in most cases. - * - * Shader below was generated with: - * SVGA_DEBUG=tgsi ./mesa/progs/fp/fp-tri white.txt - */ -static int emit_white_fs( struct svga_context *svga ) -{ - int ret = PIPE_ERROR; - - /* ps_3_0 - * def c0, 1.000000, 0.000000, 0.000000, 1.000000 - * mov oC0, c0.x - * end - */ - static const unsigned white_tokens[] = { - 0xffff0300, - 0x05000051, - 0xa00f0000, - 0x3f800000, - 0x00000000, - 0x00000000, - 0x3f800000, - 0x02000001, - 0x800f0800, - 0xa0000000, - 0x0000ffff, - }; - - assert(SVGA3D_INVALID_ID == UTIL_BITMASK_INVALID_INDEX); - svga->state.white_fs_id = util_bitmask_add(svga->fs_bm); - if(svga->state.white_fs_id == SVGA3D_INVALID_ID) - goto no_fs_id; - - ret = SVGA3D_DefineShader(svga->swc, - svga->state.white_fs_id, - SVGA3D_SHADERTYPE_PS, - white_tokens, - sizeof(white_tokens)); - if (ret) - goto no_definition; - - return 0; - -no_definition: - util_bitmask_clear(svga->fs_bm, svga->state.white_fs_id); - svga->state.white_fs_id = SVGA3D_INVALID_ID; -no_fs_id: - return ret; -} - /* SVGA_NEW_TEXTURE_BINDING * SVGA_NEW_RAST @@ -197,6 +135,23 @@ static int make_fs_key( const struct svga_context *svga, PIPE_WINDING_CW); } + /* The blend workaround for simulating logicop xor behaviour + * requires that the incoming fragment color be white. This change + * achieves that by creating a varient of the current fragment + * shader that overrides all output colors with 1,1,1,1 + * + * This will work for most shaders, including those containing + * TEXKIL and/or depth-write. However, it will break on the + * combination of xor-logicop plus alphatest. + * + * Ultimately, we could implement alphatest in the shader using + * texkil prior to overriding the outgoing fragment color. + * + * SVGA_NEW_BLEND + */ + if (svga->curr.blend->need_white_fragments) { + key->white_fragments = 1; + } /* XXX: want to limit this to the textures that the shader actually * refers to. @@ -236,40 +191,29 @@ static int emit_hw_fs( struct svga_context *svga, unsigned id = SVGA3D_INVALID_ID; int ret = 0; + struct svga_fragment_shader *fs = svga->curr.fs; + struct svga_fs_compile_key key; + /* SVGA_NEW_BLEND + * SVGA_NEW_TEXTURE_BINDING + * SVGA_NEW_RAST + * SVGA_NEW_NEED_SWTNL + * SVGA_NEW_SAMPLER */ - if (svga->curr.blend->need_white_fragments) { - if (svga->state.white_fs_id == SVGA3D_INVALID_ID) { - ret = emit_white_fs( svga ); - if (ret) - return ret; - } - id = svga->state.white_fs_id; - } - else { - struct svga_fragment_shader *fs = svga->curr.fs; - struct svga_fs_compile_key key; - - /* SVGA_NEW_TEXTURE_BINDING - * SVGA_NEW_RAST - * SVGA_NEW_NEED_SWTNL - * SVGA_NEW_SAMPLER - */ - ret = make_fs_key( svga, &key ); + ret = make_fs_key( svga, &key ); + if (ret) + return ret; + + result = search_fs_key( fs, &key ); + if (!result) { + ret = compile_fs( svga, fs, &key, &result ); if (ret) return ret; - - result = search_fs_key( fs, &key ); - if (!result) { - ret = compile_fs( svga, fs, &key, &result ); - if (ret) - return ret; - } - - assert (result); - id = result->id; } + assert (result); + id = result->id; + assert(id != SVGA3D_INVALID_ID); if (result != svga->state.hw_draw.fs) { diff --git a/src/gallium/drivers/svga/svga_state_need_swtnl.c b/src/gallium/drivers/svga/svga_state_need_swtnl.c index 3c35a8579f..dd13a89d24 100644 --- a/src/gallium/drivers/svga/svga_state_need_swtnl.c +++ b/src/gallium/drivers/svga/svga_state_need_swtnl.c @@ -23,7 +23,7 @@ * **********************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_state.h" diff --git a/src/gallium/drivers/svga/svga_state_rss.c b/src/gallium/drivers/svga/svga_state_rss.c index c582e44524..5ce9b4ef4f 100644 --- a/src/gallium/drivers/svga/svga_state_rss.c +++ b/src/gallium/drivers/svga/svga_state_rss.c @@ -23,7 +23,7 @@ * **********************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_defines.h" #include "util/u_math.h" @@ -31,9 +31,6 @@ #include "svga_state.h" #include "svga_cmd.h" -#include "svga_hw_reg.h" - - struct rs_queue { unsigned rs_count; diff --git a/src/gallium/drivers/svga/svga_state_tss.c b/src/gallium/drivers/svga/svga_state_tss.c index b313794520..17b4785978 100644 --- a/src/gallium/drivers/svga/svga_state_tss.c +++ b/src/gallium/drivers/svga/svga_state_tss.c @@ -23,7 +23,7 @@ * **********************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_defines.h" #include "util/u_math.h" @@ -33,8 +33,6 @@ #include "svga_state.h" #include "svga_cmd.h" -#include "svga_hw_reg.h" - void svga_cleanup_tss_binding(struct svga_context *svga) { diff --git a/src/gallium/drivers/svga/svga_state_vdecl.c b/src/gallium/drivers/svga/svga_state_vdecl.c index c534308f50..d1066ce13b 100644 --- a/src/gallium/drivers/svga/svga_state_vdecl.c +++ b/src/gallium/drivers/svga/svga_state_vdecl.c @@ -23,7 +23,7 @@ * **********************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_defines.h" #include "util/u_math.h" #include "util/u_upload_mgr.h" diff --git a/src/gallium/drivers/svga/svga_state_vs.c b/src/gallium/drivers/svga/svga_state_vs.c index ae1e77e7d4..d7999fe53d 100644 --- a/src/gallium/drivers/svga/svga_state_vs.c +++ b/src/gallium/drivers/svga/svga_state_vs.c @@ -23,7 +23,7 @@ * **********************************************************/ -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_defines.h" #include "util/u_format.h" #include "util/u_math.h" @@ -71,7 +71,7 @@ static enum pipe_error compile_vs( struct svga_context *svga, struct svga_shader_result **out_result ) { struct svga_shader_result *result; - enum pipe_error ret = PIPE_OK; + enum pipe_error ret = PIPE_ERROR; result = svga_translate_vertex_program( vs, key ); if (result == NULL) { @@ -80,8 +80,10 @@ static enum pipe_error compile_vs( struct svga_context *svga, } result->id = util_bitmask_add(svga->vs_bm); - if(result->id == UTIL_BITMASK_INVALID_INDEX) + if(result->id == UTIL_BITMASK_INVALID_INDEX) { + ret = PIPE_ERROR_OUT_OF_MEMORY; goto fail; + } ret = SVGA3D_DefineShader(svga->swc, result->id, @@ -200,10 +202,12 @@ static int update_zero_stride( struct svga_context *svga, key.output_stride = 4 * sizeof(float); key.nr_elements = 1; + key.element[0].type = TRANSLATE_ELEMENT_NORMAL; key.element[0].input_format = vel->src_format; key.element[0].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; key.element[0].input_buffer = vel->vertex_buffer_index; key.element[0].input_offset = vel->src_offset; + key.element[0].instance_divisor = vel->instance_divisor; key.element[0].output_offset = const_idx * 4 * sizeof(float); translate_key_sanitize(&key); @@ -222,7 +226,7 @@ static int update_zero_stride( struct svga_context *svga, translate->set_buffer(translate, vel->vertex_buffer_index, mapped_buffer, vbuffer->stride); - translate->run(translate, 0, 1, + translate->run(translate, 0, 1, 0, svga->curr.zero_stride_constants); pipe_buffer_unmap(svga->pipe.screen, diff --git a/src/gallium/drivers/svga/svga_swtnl_backend.c b/src/gallium/drivers/svga/svga_swtnl_backend.c index b4f757a47a..e9d7942fb5 100644 --- a/src/gallium/drivers/svga/svga_swtnl_backend.c +++ b/src/gallium/drivers/svga/svga_swtnl_backend.c @@ -28,10 +28,9 @@ #include "draw/draw_vertex.h" #include "util/u_debug.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "util/u_math.h" #include "util/u_memory.h" -#include "util/u_simple_shaders.h" #include "svga_context.h" #include "svga_state.h" @@ -87,13 +86,13 @@ svga_vbuf_render_allocate_vertices( struct vbuf_render *render, if (!svga_render->vbuf) { svga_render->vbuf_size = MAX2(size, svga_render->vbuf_alloc_size); svga_render->vbuf = pipe_buffer_create(screen, - 0, + 16, PIPE_BUFFER_USAGE_VERTEX, svga_render->vbuf_size); if(!svga_render->vbuf) { svga_context_flush(svga, NULL); svga_render->vbuf = pipe_buffer_create(screen, - 0, + 16, PIPE_BUFFER_USAGE_VERTEX, svga_render->vbuf_size); assert(svga_render->vbuf); @@ -123,7 +122,9 @@ svga_vbuf_render_map_vertices( struct vbuf_render *render ) char *ptr = (char*)pipe_buffer_map(screen, svga_render->vbuf, PIPE_BUFFER_USAGE_CPU_WRITE | - PIPE_BUFFER_USAGE_FLUSH_EXPLICIT); + PIPE_BUFFER_USAGE_FLUSH_EXPLICIT | + PIPE_BUFFER_USAGE_DISCARD | + PIPE_BUFFER_USAGE_UNSYNCHRONIZED); return ptr + svga_render->vbuf_offset; } @@ -259,14 +260,14 @@ svga_vbuf_render_draw( struct vbuf_render *render, if (!svga_render->ibuf) { svga_render->ibuf_size = MAX2(size, svga_render->ibuf_alloc_size); svga_render->ibuf = pipe_buffer_create(screen, - 0, + 2, PIPE_BUFFER_USAGE_VERTEX, svga_render->ibuf_size); svga_render->ibuf_offset = 0; } - pipe_buffer_write(screen, svga_render->ibuf, - svga_render->ibuf_offset, 2 * nr_indices, indices); + pipe_buffer_write_nooverlap(screen, svga_render->ibuf, + svga_render->ibuf_offset, 2 * nr_indices, indices); /* off to hardware */ diff --git a/src/gallium/drivers/svga/svga_swtnl_draw.c b/src/gallium/drivers/svga/svga_swtnl_draw.c index 7655121bec..da15be155c 100644 --- a/src/gallium/drivers/svga/svga_swtnl_draw.c +++ b/src/gallium/drivers/svga/svga_swtnl_draw.c @@ -25,9 +25,8 @@ #include "draw/draw_context.h" #include "draw/draw_vbuf.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_state.h" -#include "util/u_memory.h" #include "svga_context.h" #include "svga_swtnl.h" @@ -90,7 +89,7 @@ svga_swtnl_draw_range_elements(struct svga_context *svga, PIPE_BUFFER_USAGE_CPU_READ); assert(map); draw_set_mapped_constant_buffer( - draw, PIPE_SHADER_VERTEX, + draw, PIPE_SHADER_VERTEX, 0, map, svga->curr.cb[PIPE_SHADER_VERTEX]->size); } diff --git a/src/gallium/drivers/svga/svga_swtnl_state.c b/src/gallium/drivers/svga/svga_swtnl_state.c index 94b6ccc62d..35f36a828f 100644 --- a/src/gallium/drivers/svga/svga_swtnl_state.c +++ b/src/gallium/drivers/svga/svga_swtnl_state.c @@ -25,9 +25,8 @@ #include "draw/draw_context.h" #include "draw/draw_vbuf.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_state.h" -#include "util/u_memory.h" #include "svga_context.h" #include "svga_swtnl.h" diff --git a/src/gallium/drivers/svga/svga_tgsi.h b/src/gallium/drivers/svga/svga_tgsi.h index 737a2213af..063c9cf422 100644 --- a/src/gallium/drivers/svga/svga_tgsi.h +++ b/src/gallium/drivers/svga/svga_tgsi.h @@ -49,6 +49,7 @@ struct svga_fs_compile_key { unsigned light_twoside:1; unsigned front_cw:1; + unsigned white_fragments:1; unsigned num_textures:8; unsigned num_unnormalized_coords:8; struct { diff --git a/src/gallium/drivers/svga/svga_tgsi_decl_sm20.c b/src/gallium/drivers/svga/svga_tgsi_decl_sm20.c index 23b3ace7f3..1ae9906761 100644 --- a/src/gallium/drivers/svga/svga_tgsi_decl_sm20.c +++ b/src/gallium/drivers/svga/svga_tgsi_decl_sm20.c @@ -29,9 +29,6 @@ #include "util/u_memory.h" #include "svga_tgsi_emit.h" -#include "svga_context.h" - - static boolean ps20_input( struct svga_shader_emitter *emit, diff --git a/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c b/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c index d1c7336dec..73102a72a8 100644 --- a/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c +++ b/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c @@ -29,7 +29,6 @@ #include "util/u_memory.h" #include "svga_tgsi_emit.h" -#include "svga_context.h" static boolean translate_vs_ps_semantic( struct tgsi_declaration_semantic semantic, unsigned *usage, @@ -195,8 +194,19 @@ static boolean ps30_output( struct svga_shader_emitter *emit, switch (semantic.Name) { case TGSI_SEMANTIC_COLOR: - emit->output_map[idx] = dst_register( SVGA3DREG_COLOROUT, - semantic.Index ); + if (emit->unit == PIPE_SHADER_FRAGMENT && + emit->key.fkey.white_fragments) { + + emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, + emit->nr_hw_temp++ ); + emit->temp_col[idx] = emit->output_map[idx]; + emit->true_col[idx] = dst_register( SVGA3DREG_COLOROUT, + semantic.Index ); + } + else { + emit->output_map[idx] = dst_register( SVGA3DREG_COLOROUT, + semantic.Index ); + } break; case TGSI_SEMANTIC_POSITION: emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, diff --git a/src/gallium/drivers/svga/svga_tgsi_emit.h b/src/gallium/drivers/svga/svga_tgsi_emit.h index 2557824293..e8f75485d5 100644 --- a/src/gallium/drivers/svga/svga_tgsi_emit.h +++ b/src/gallium/drivers/svga/svga_tgsi_emit.h @@ -79,6 +79,8 @@ struct svga_shader_emitter int ps30_input_count; + int dynamic_branching_level; + boolean in_main_func; boolean created_zero_immediate; @@ -199,6 +201,23 @@ static INLINE boolean emit_op3( struct svga_shader_emitter *emit, } +static INLINE boolean emit_op4( struct svga_shader_emitter *emit, + SVGA3dShaderInstToken inst, + SVGA3dShaderDestToken dest, + struct src_register src0, + struct src_register src1, + struct src_register src2, + struct src_register src3) +{ + return (emit_instruction( emit, inst ) && + emit_dst( emit, dest ) && + emit_src( emit, src0 ) && + emit_src( emit, src1 ) && + emit_src( emit, src2 ) && + emit_src( emit, src3 )); +} + + #define TRANSLATE_SWIZZLE(x,y,z,w) ((x) | ((y) << 2) | ((z) << 4) | ((w) << 6)) #define SWIZZLE_XYZW \ TRANSLATE_SWIZZLE(TGSI_SWIZZLE_X,TGSI_SWIZZLE_Y,TGSI_SWIZZLE_Z,TGSI_SWIZZLE_W) diff --git a/src/gallium/drivers/svga/svga_tgsi_insn.c b/src/gallium/drivers/svga/svga_tgsi_insn.c index dc5eb8fc60..be821e9821 100644 --- a/src/gallium/drivers/svga/svga_tgsi_insn.c +++ b/src/gallium/drivers/svga/svga_tgsi_insn.c @@ -46,8 +46,6 @@ translate_opcode( case TGSI_OPCODE_ABS: return SVGA3DOP_ABS; case TGSI_OPCODE_ADD: return SVGA3DOP_ADD; case TGSI_OPCODE_BREAKC: return SVGA3DOP_BREAKC; - case TGSI_OPCODE_DDX: return SVGA3DOP_DSX; - case TGSI_OPCODE_DDY: return SVGA3DOP_DSY; case TGSI_OPCODE_DP2A: return SVGA3DOP_DP2ADD; case TGSI_OPCODE_DP3: return SVGA3DOP_DP3; case TGSI_OPCODE_DP4: return SVGA3DOP_DP4; @@ -415,6 +413,88 @@ static boolean submit_op3( struct svga_shader_emitter *emit, } + + +/* SVGA shaders may not refer to >1 constant register in a single + * instruction. This function checks for that usage and inserts a + * move to temporary if detected. + */ +static boolean submit_op4( struct svga_shader_emitter *emit, + SVGA3dShaderInstToken inst, + SVGA3dShaderDestToken dest, + struct src_register src0, + struct src_register src1, + struct src_register src2, + struct src_register src3) +{ + SVGA3dShaderDestToken temp0; + SVGA3dShaderDestToken temp3; + boolean need_temp0 = FALSE; + boolean need_temp3 = FALSE; + SVGA3dShaderRegType type0, type1, type2, type3; + + temp0.value = 0; + temp3.value = 0; + type0 = SVGA3dShaderGetRegType( src0.base.value ); + type1 = SVGA3dShaderGetRegType( src1.base.value ); + type2 = SVGA3dShaderGetRegType( src2.base.value ); + type3 = SVGA3dShaderGetRegType( src2.base.value ); + + /* Make life a little easier - this is only used by the TXD + * instruction which is guaranteed not to have a constant/input reg + * in one slot at least: + */ + assert(type1 == SVGA3DREG_SAMPLER); + + if (type0 == SVGA3DREG_CONST && + ((type3 == SVGA3DREG_CONST && src0.base.num != src3.base.num) || + (type2 == SVGA3DREG_CONST && src0.base.num != src2.base.num))) + need_temp0 = TRUE; + + if (type3 == SVGA3DREG_CONST && + (type2 == SVGA3DREG_CONST && src3.base.num != src2.base.num)) + need_temp3 = TRUE; + + if (type0 == SVGA3DREG_INPUT && + ((type3 == SVGA3DREG_INPUT && src0.base.num != src3.base.num) || + (type2 == SVGA3DREG_INPUT && src0.base.num != src2.base.num))) + need_temp0 = TRUE; + + if (type3 == SVGA3DREG_INPUT && + (type2 == SVGA3DREG_INPUT && src3.base.num != src2.base.num)) + need_temp3 = TRUE; + + if (need_temp0) + { + temp0 = get_temp( emit ); + + if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp0, src0 )) + return FALSE; + + src0 = src( temp0 ); + } + + if (need_temp3) + { + temp3 = get_temp( emit ); + + if (!emit_op1( emit, inst_token( SVGA3DOP_MOV ), temp3, src3 )) + return FALSE; + + src3 = src( temp3 ); + } + + if (!emit_op4( emit, inst, dest, src0, src1, src2, src3 )) + return FALSE; + + if (need_temp3) + release_temp( emit, temp3 ); + if (need_temp0) + release_temp( emit, temp0 ); + return TRUE; +} + + static boolean emit_def_const( struct svga_shader_emitter *emit, SVGA3dShaderConstType type, unsigned idx, @@ -660,6 +740,8 @@ static boolean emit_if(struct svga_shader_emitter *emit, if_token.control = SVGA3DOPCOMPC_NE; zero = scalar(zero, TGSI_SWIZZLE_X); + emit->dynamic_branching_level++; + return (emit_instruction( emit, if_token ) && emit_src( emit, src ) && emit_src( emit, zero ) ); @@ -668,6 +750,8 @@ static boolean emit_if(struct svga_shader_emitter *emit, static boolean emit_endif(struct svga_shader_emitter *emit, const struct tgsi_full_instruction *insn) { + emit->dynamic_branching_level--; + return (emit_instruction( emit, inst_token( SVGA3DOP_ENDIF ))); } @@ -1011,10 +1095,10 @@ static boolean emit_kilp(struct svga_shader_emitter *emit, { SVGA3dShaderInstToken inst; SVGA3dShaderDestToken temp; - struct src_register one = get_zero_immediate( emit ); + struct src_register one = scalar( get_zero_immediate( emit ), + TGSI_SWIZZLE_W ); inst = inst_token( SVGA3DOP_TEXKILL ); - one = scalar( one, TGSI_SWIZZLE_W ); /* texkill doesn't allow negation on the operand so lets move * negation of {1} to a temp register */ @@ -1169,41 +1253,79 @@ static boolean emit_tex2(struct svga_shader_emitter *emit, SVGA3dShaderDestToken dst ) { SVGA3dShaderInstToken inst; - struct src_register src0; - struct src_register src1; - + struct src_register texcoord; + struct src_register sampler; + SVGA3dShaderDestToken tmp; + inst.value = 0; - inst.op = SVGA3DOP_TEX; switch (insn->Instruction.Opcode) { case TGSI_OPCODE_TEX: + inst.op = SVGA3DOP_TEX; break; case TGSI_OPCODE_TXP: + inst.op = SVGA3DOP_TEX; inst.control = SVGA3DOPCONT_PROJECT; break; case TGSI_OPCODE_TXB: + inst.op = SVGA3DOP_TEX; inst.control = SVGA3DOPCONT_BIAS; break; + case TGSI_OPCODE_TXL: + inst.op = SVGA3DOP_TEXLDL; + break; default: assert(0); return FALSE; } - src0 = translate_src_register( emit, &insn->Src[0] ); - src1 = translate_src_register( emit, &insn->Src[1] ); + texcoord = translate_src_register( emit, &insn->Src[0] ); + sampler = translate_src_register( emit, &insn->Src[1] ); - if (emit->key.fkey.tex[src1.base.num].unnormalized) { - struct src_register wh = get_tex_dimensions( emit, src1.base.num ); - SVGA3dShaderDestToken tmp = get_temp( emit ); + if (emit->key.fkey.tex[sampler.base.num].unnormalized || + emit->dynamic_branching_level > 0) + tmp = get_temp( emit ); + + /* Can't do mipmapping inside dynamic branch constructs. Force LOD + * zero in that case. + */ + if (emit->dynamic_branching_level > 0 && + inst.op == SVGA3DOP_TEX && + SVGA3dShaderGetRegType(texcoord.base.value) == SVGA3DREG_TEMP) { + struct src_register zero = get_zero_immediate( emit ); + + /* MOV tmp, texcoord */ + if (!submit_op1( emit, + inst_token( SVGA3DOP_MOV ), + tmp, + texcoord )) + return FALSE; + + /* MOV tmp.w, zero */ + if (!submit_op1( emit, + inst_token( SVGA3DOP_MOV ), + writemask( tmp, TGSI_WRITEMASK_W ), + scalar( zero, TGSI_SWIZZLE_X ))) + return FALSE; + + texcoord = src( tmp ); + inst.op = SVGA3DOP_TEXLDL; + } + + /* Explicit normalization of texcoords: + */ + if (emit->key.fkey.tex[sampler.base.num].unnormalized) { + struct src_register wh = get_tex_dimensions( emit, sampler.base.num ); /* MUL tmp, SRC0, WH */ if (!submit_op2( emit, inst_token( SVGA3DOP_MUL ), - tmp, src0, wh )) + tmp, texcoord, wh )) return FALSE; - src0 = src( tmp ); + + texcoord = src( tmp ); } - return submit_op2( emit, inst, dst, src0, src1 ); + return submit_op2( emit, inst, dst, texcoord, sampler ); } @@ -1211,31 +1333,33 @@ static boolean emit_tex2(struct svga_shader_emitter *emit, /* Translate texture instructions to SVGA3D representation. */ -static boolean emit_tex3(struct svga_shader_emitter *emit, +static boolean emit_tex4(struct svga_shader_emitter *emit, const struct tgsi_full_instruction *insn, SVGA3dShaderDestToken dst ) { SVGA3dShaderInstToken inst; - struct src_register src0; - struct src_register src1; - struct src_register src2; + struct src_register texcoord; + struct src_register ddx; + struct src_register ddy; + struct src_register sampler; + + texcoord = translate_src_register( emit, &insn->Src[0] ); + ddx = translate_src_register( emit, &insn->Src[1] ); + ddy = translate_src_register( emit, &insn->Src[2] ); + sampler = translate_src_register( emit, &insn->Src[3] ); inst.value = 0; switch (insn->Instruction.Opcode) { case TGSI_OPCODE_TXD: - inst.op = SVGA3DOP_TEXLDD; - break; - case TGSI_OPCODE_TXL: - inst.op = SVGA3DOP_TEXLDL; + inst.op = SVGA3DOP_TEXLDD; /* 4 args! */ break; + default: + assert(0); + return FALSE; } - src0 = translate_src_register( emit, &insn->Src[0] ); - src1 = translate_src_register( emit, &insn->Src[1] ); - src2 = translate_src_register( emit, &insn->Src[2] ); - - return submit_op3( emit, inst, dst, src0, src1, src2 ); + return submit_op4( emit, inst, dst, texcoord, sampler, ddx, ddy ); } @@ -1271,12 +1395,12 @@ static boolean emit_tex(struct svga_shader_emitter *emit, case TGSI_OPCODE_TEX: case TGSI_OPCODE_TXB: case TGSI_OPCODE_TXP: + case TGSI_OPCODE_TXL: if (!emit_tex2( emit, insn, tex_result )) return FALSE; break; - case TGSI_OPCODE_TXL: case TGSI_OPCODE_TXD: - if (!emit_tex3( emit, insn, tex_result )) + if (!emit_tex4( emit, insn, tex_result )) return FALSE; break; default: @@ -1330,6 +1454,8 @@ static boolean emit_bgnloop2( struct svga_shader_emitter *emit, struct src_register loop_reg = src_register( SVGA3DREG_LOOP, 0 ); struct src_register const_int = get_loop_const( emit ); + emit->dynamic_branching_level++; + return (emit_instruction( emit, inst ) && emit_src( emit, loop_reg ) && emit_src( emit, const_int ) ); @@ -1339,6 +1465,9 @@ static boolean emit_endloop2( struct svga_shader_emitter *emit, const struct tgsi_full_instruction *insn ) { SVGA3dShaderInstToken inst = inst_token( SVGA3DOP_ENDLOOP ); + + emit->dynamic_branching_level--; + return emit_instruction( emit, inst ); } @@ -1398,6 +1527,46 @@ static boolean emit_simple_instruction(struct svga_shader_emitter *emit, } } + +static boolean emit_deriv(struct svga_shader_emitter *emit, + const struct tgsi_full_instruction *insn ) +{ + if (emit->dynamic_branching_level > 0 && + insn->Src[0].Register.File == TGSI_FILE_TEMPORARY) + { + struct src_register zero = get_zero_immediate( emit ); + SVGA3dShaderDestToken dst = + translate_dst_register( emit, insn, 0 ); + + /* Deriv opcodes not valid inside dynamic branching, workaround + * by zeroing out the destination. + */ + if (!submit_op1(emit, + inst_token( SVGA3DOP_MOV ), + dst, + scalar(zero, TGSI_SWIZZLE_X))) + return FALSE; + + return TRUE; + } + else { + unsigned opcode; + + switch (insn->Instruction.Opcode) { + case TGSI_OPCODE_DDX: + opcode = SVGA3DOP_DSX; + break; + case TGSI_OPCODE_DDY: + opcode = SVGA3DOP_DSY; + break; + default: + return FALSE; + } + + return emit_simple_instruction( emit, opcode, insn ); + } +} + static boolean emit_arl(struct svga_shader_emitter *emit, const struct tgsi_full_instruction *insn) { @@ -2002,6 +2171,10 @@ static boolean svga_emit_instruction( struct svga_shader_emitter *emit, case TGSI_OPCODE_TXD: return emit_tex( emit, insn ); + case TGSI_OPCODE_DDX: + case TGSI_OPCODE_DDY: + return emit_deriv( emit, insn ); + case TGSI_OPCODE_BGNSUB: return emit_bgnsub( emit, position, insn ); @@ -2254,11 +2427,28 @@ static boolean emit_ps_postamble( struct svga_shader_emitter *emit ) for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { if (SVGA3dShaderGetRegType(emit->true_col[i].value) != 0) { - if (!submit_op1( emit, - inst_token(SVGA3DOP_MOV), - emit->true_col[i], - src(emit->temp_col[i]) )) - return FALSE; + /* Potentially override output colors with white for XOR + * logicop workaround. + */ + if (emit->unit == PIPE_SHADER_FRAGMENT && + emit->key.fkey.white_fragments) { + + struct src_register one = scalar( get_zero_immediate( emit ), + TGSI_SWIZZLE_W ); + + if (!submit_op1( emit, + inst_token(SVGA3DOP_MOV), + emit->true_col[i], + one )) + return FALSE; + } + else { + if (!submit_op1( emit, + inst_token(SVGA3DOP_MOV), + emit->true_col[i], + src(emit->temp_col[i]) )) + return FALSE; + } } } @@ -2467,6 +2657,9 @@ needs_to_create_zero( struct svga_shader_emitter *emit ) if (emit->key.fkey.light_twoside) return TRUE; + if (emit->key.fkey.white_fragments) + return TRUE; + if (emit->emit_frontface) return TRUE; @@ -2476,6 +2669,10 @@ needs_to_create_zero( struct svga_shader_emitter *emit ) } if (emit->info.opcode_count[TGSI_OPCODE_IF] >= 1 || + emit->info.opcode_count[TGSI_OPCODE_BGNLOOP] >= 1 || + emit->info.opcode_count[TGSI_OPCODE_BGNFOR] >= 1 || + emit->info.opcode_count[TGSI_OPCODE_DDX] >= 1 || + emit->info.opcode_count[TGSI_OPCODE_DDY] >= 1 || emit->info.opcode_count[TGSI_OPCODE_SGE] >= 1 || emit->info.opcode_count[TGSI_OPCODE_SGT] >= 1 || emit->info.opcode_count[TGSI_OPCODE_SLE] >= 1 || @@ -2702,6 +2899,8 @@ boolean svga_shader_emit_instructions( struct svga_shader_emitter *emit, goto done; } + assert(emit->dynamic_branching_level == 0); + /* Need to terminate the whole shader: */ ret = emit_instruction( emit, inst_token( SVGA3DOP_END ) ); diff --git a/src/gallium/drivers/svga/svga_winsys.h b/src/gallium/drivers/svga/svga_winsys.h index 59f299c185..b4e3af0eaf 100644 --- a/src/gallium/drivers/svga/svga_winsys.h +++ b/src/gallium/drivers/svga/svga_winsys.h @@ -272,9 +272,6 @@ struct svga_winsys_screen }; -struct pipe_context * -svga_context_create(struct pipe_screen *screen); - struct pipe_screen * svga_screen_create(struct svga_winsys_screen *sws); @@ -296,4 +293,10 @@ svga_screen_buffer_from_texture(struct pipe_texture *texture, struct pipe_buffer **buffer, unsigned *stride); +struct pipe_texture * +svga_screen_texture_wrap_surface(struct pipe_screen *screen, + struct pipe_texture *base, + enum SVGA3dSurfaceFormat format, + struct svga_winsys_surface *srf); + #endif /* SVGA_WINSYS_H_ */ diff --git a/src/gallium/drivers/trace/tr_buffer.c b/src/gallium/drivers/trace/tr_buffer.c index 4f0eff6a5a..fa2ac068eb 100644 --- a/src/gallium/drivers/trace/tr_buffer.c +++ b/src/gallium/drivers/trace/tr_buffer.c @@ -26,6 +26,7 @@ **************************************************************************/ +#include "util/u_inlines.h" #include "util/u_memory.h" #include "util/u_simple_list.h" diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c index 075e4f9a0b..34ceaa41c1 100644 --- a/src/gallium/drivers/trace/tr_context.c +++ b/src/gallium/drivers/trace/tr_context.c @@ -812,13 +812,13 @@ trace_context_set_clip_state(struct pipe_context *_pipe, static INLINE void trace_context_set_constant_buffer(struct pipe_context *_pipe, uint shader, uint index, - const struct pipe_constant_buffer *buffer) + struct pipe_buffer *buffer) { struct trace_context *tr_ctx = trace_context(_pipe); struct pipe_context *pipe = tr_ctx->pipe; if (buffer) - trace_screen_user_buffer_update(_pipe->screen, buffer->buffer); + trace_screen_user_buffer_update(_pipe->screen, buffer); trace_dump_call_begin("pipe_context", "set_constant_buffer"); @@ -827,10 +827,11 @@ trace_context_set_constant_buffer(struct pipe_context *_pipe, trace_dump_arg(uint, index); trace_dump_arg(constant_buffer, buffer); + /* XXX hmm? */ if (buffer) { - struct pipe_constant_buffer _buffer; - _buffer.buffer = trace_buffer_unwrap(tr_ctx, buffer->buffer); - pipe->set_constant_buffer(pipe, shader, index, &_buffer); + struct pipe_buffer *_buffer; + _buffer = trace_buffer_unwrap(tr_ctx, buffer); + pipe->set_constant_buffer(pipe, shader, index, _buffer); } else { pipe->set_constant_buffer(pipe, shader, index, buffer); } @@ -1235,12 +1236,10 @@ static const struct debug_named_value rbug_blocker_flags[] = { }; struct pipe_context * -trace_context_create(struct pipe_screen *_screen, +trace_context_create(struct trace_screen *tr_scr, struct pipe_context *pipe) { - struct trace_screen *tr_scr; struct trace_context *tr_ctx; - struct pipe_screen *screen; if(!pipe) goto error1; @@ -1248,13 +1247,13 @@ trace_context_create(struct pipe_screen *_screen, if(!trace_enabled()) goto error1; - tr_scr = trace_screen(_screen); - screen = tr_scr->screen; - tr_ctx = CALLOC_STRUCT(trace_context); if(!tr_ctx) goto error1; + tr_ctx->base.winsys = NULL; + tr_ctx->base.priv = pipe->priv; /* expose wrapped priv data */ + tr_ctx->base.screen = &tr_scr->base; tr_ctx->draw_blocker = debug_get_flags_option("RBUG_BLOCK", rbug_blocker_flags, 0); @@ -1263,8 +1262,6 @@ trace_context_create(struct pipe_screen *_screen, 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; tr_ctx->base.draw_arrays = trace_context_draw_arrays; tr_ctx->base.draw_elements = trace_context_draw_elements; @@ -1315,11 +1312,6 @@ trace_context_create(struct pipe_screen *_screen, tr_ctx->pipe = pipe; - trace_dump_call_begin("", "pipe_context_create"); - trace_dump_arg(ptr, screen); - trace_dump_ret(ptr, pipe); - trace_dump_call_end(); - trace_screen_add_to_list(tr_scr, contexts, tr_ctx); return &tr_ctx->base; diff --git a/src/gallium/drivers/trace/tr_context.h b/src/gallium/drivers/trace/tr_context.h index 852b480765..1428423248 100644 --- a/src/gallium/drivers/trace/tr_context.h +++ b/src/gallium/drivers/trace/tr_context.h @@ -40,6 +40,8 @@ extern "C" { #endif +struct trace_screen; + struct trace_context { struct pipe_context base; @@ -95,9 +97,8 @@ trace_context(struct pipe_context *pipe) } - struct pipe_context * -trace_context_create(struct pipe_screen *screen, +trace_context_create(struct trace_screen *tr_scr, struct pipe_context *pipe); void diff --git a/src/gallium/drivers/trace/tr_drm.c b/src/gallium/drivers/trace/tr_drm.c index 48d1c4051c..919dc1b309 100644 --- a/src/gallium/drivers/trace/tr_drm.c +++ b/src/gallium/drivers/trace/tr_drm.c @@ -65,24 +65,6 @@ trace_drm_create_screen(struct drm_api *_api, int fd, 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 struct pipe_texture * trace_drm_texture_from_shared_handle(struct drm_api *_api, @@ -173,8 +155,8 @@ trace_drm_create(struct drm_api *api) if (!tr_api) goto error; + tr_api->base.driver_name = api->driver_name; tr_api->base.create_screen = trace_drm_create_screen; - tr_api->base.create_context = trace_drm_create_context; tr_api->base.texture_from_shared_handle = trace_drm_texture_from_shared_handle; tr_api->base.shared_handle_from_texture = trace_drm_shared_handle_from_texture; tr_api->base.local_handle_from_texture = trace_drm_local_handle_from_texture; diff --git a/src/gallium/drivers/trace/tr_dump.c b/src/gallium/drivers/trace/tr_dump.c index 0f45e211a3..8de451c22c 100644 --- a/src/gallium/drivers/trace/tr_dump.c +++ b/src/gallium/drivers/trace/tr_dump.c @@ -45,11 +45,11 @@ #endif #include "pipe/p_compiler.h" -#include "pipe/p_thread.h" +#include "os/os_thread.h" +#include "os/os_stream.h" #include "util/u_debug.h" #include "util/u_memory.h" #include "util/u_string.h" -#include "util/u_stream.h" #include "tr_dump.h" #include "tr_screen.h" @@ -57,7 +57,7 @@ #include "tr_buffer.h" -static struct util_stream *stream = NULL; +static struct os_stream *stream = NULL; static unsigned refcount = 0; static pipe_mutex call_mutex; static long unsigned call_no = 0; @@ -69,7 +69,7 @@ static INLINE void trace_dump_write(const char *buf, size_t size) { if(stream) - util_stream_write(stream, buf, size); + os_stream_write(stream, buf, size); } @@ -220,7 +220,7 @@ trace_dump_trace_close(void) { if(stream) { trace_dump_writes("</trace>\n"); - util_stream_close(stream); + os_stream_close(stream); stream = NULL; refcount = 0; call_no = 0; @@ -250,7 +250,7 @@ boolean trace_dump_trace_begin() if(!stream) { - stream = util_stream_create(filename, 0); + stream = os_stream_create(filename, 0); if(!stream) return FALSE; @@ -367,7 +367,7 @@ void trace_dump_call_end_locked(void) trace_dump_indent(1); trace_dump_tag_end("call"); trace_dump_newline(); - util_stream_flush(stream); + os_stream_flush(stream); } void trace_dump_call_begin(const char *klass, const char *method) diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c index 720b6cd1ff..6648539a0f 100644 --- a/src/gallium/drivers/trace/tr_dump_state.c +++ b/src/gallium/drivers/trace/tr_dump_state.c @@ -49,7 +49,7 @@ static void trace_dump_reference(const struct pipe_reference *reference) return; trace_dump_struct_begin("pipe_reference"); - trace_dump_member(int, &reference->count, count); + trace_dump_member(int, reference, count); trace_dump_struct_end(); } @@ -227,7 +227,7 @@ 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_constant_buffer(const struct pipe_buffer *state) { if (!trace_dumping_enabled_locked()) return; @@ -239,7 +239,7 @@ void trace_dump_constant_buffer(const struct pipe_constant_buffer *state) trace_dump_struct_begin("pipe_constant_buffer"); - trace_dump_member(buffer_ptr, state, buffer); + trace_dump_reference(&state->reference); trace_dump_struct_end(); } @@ -321,9 +321,23 @@ void trace_dump_depth_stencil_alpha_state(const struct pipe_depth_stencil_alpha_ trace_dump_struct_end(); } +static void trace_dump_rt_blend_state(const struct pipe_rt_blend_state *state) +{ + 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(uint, state, colormask); + +} void trace_dump_blend_state(const struct pipe_blend_state *state) { + unsigned valid_entries = 1; if (!trace_dumping_enabled_locked()) return; @@ -334,21 +348,17 @@ void trace_dump_blend_state(const struct pipe_blend_state *state) 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, dither); 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_member(bool, state, independent_blend_enable); + + if (state->independent_blend_enable) + valid_entries = PIPE_MAX_COLOR_BUFS; + + trace_dump_struct_array(rt_blend_state, state->rt, valid_entries); trace_dump_struct_end(); } @@ -410,7 +420,6 @@ void trace_dump_sampler_state(const struct pipe_sampler_state *state) trace_dump_member(uint, 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); diff --git a/src/gallium/drivers/trace/tr_dump_state.h b/src/gallium/drivers/trace/tr_dump_state.h index 07ad6fbb20..c7860fd6e1 100644 --- a/src/gallium/drivers/trace/tr_dump_state.h +++ b/src/gallium/drivers/trace/tr_dump_state.h @@ -47,7 +47,7 @@ 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_constant_buffer(const struct pipe_buffer *state); void trace_dump_token(const struct tgsi_token *token); diff --git a/src/gallium/drivers/trace/tr_rbug.c b/src/gallium/drivers/trace/tr_rbug.c index 0546aad9b5..691b83c63f 100644 --- a/src/gallium/drivers/trace/tr_rbug.c +++ b/src/gallium/drivers/trace/tr_rbug.c @@ -26,11 +26,13 @@ **************************************************************************/ +#include "os/os_thread.h" #include "util/u_format.h" #include "util/u_string.h" #include "util/u_memory.h" #include "util/u_simple_list.h" #include "util/u_network.h" +#include "util/u_time.h" #include "tgsi/tgsi_parse.h" @@ -43,15 +45,6 @@ #include <errno.h> -#if defined(PIPE_SUBSYSTEM_WINDOWS_USER) -# define sleep Sleep -#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_APPLE) -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)) @@ -805,7 +798,7 @@ PIPE_THREAD_ROUTINE(trace_rbug_thread, void_tr_rbug) debug_printf("trace_rbug - remote debugging listening on port %u\n", --port); while(tr_rbug->running) { - sleep(1); + util_time_sleep(1); c = u_socket_accept(s); if (c < 0) diff --git a/src/gallium/drivers/trace/tr_screen.c b/src/gallium/drivers/trace/tr_screen.c index 117503aaff..388d83eb5c 100644 --- a/src/gallium/drivers/trace/tr_screen.c +++ b/src/gallium/drivers/trace/tr_screen.c @@ -33,9 +33,10 @@ #include "tr_dump.h" #include "tr_dump_state.h" #include "tr_texture.h" +#include "tr_context.h" #include "tr_screen.h" -#include "pipe/p_inlines.h" +#include "util/u_inlines.h" #include "pipe/p_format.h" @@ -159,6 +160,29 @@ trace_screen_is_format_supported(struct pipe_screen *_screen, } +static struct pipe_context * +trace_screen_context_create(struct pipe_screen *_screen, void *priv) +{ + struct trace_screen *tr_scr = trace_screen(_screen); + struct pipe_screen *screen = tr_scr->screen; + struct pipe_context *result; + + trace_dump_call_begin("pipe_screen", "context_create"); + + trace_dump_arg(ptr, screen); + + result = screen->context_create(screen, priv); + + trace_dump_ret(ptr, result); + + trace_dump_call_end(); + + result = trace_context_create(tr_scr, result); + + return result; +} + + static void trace_screen_flush_frontbuffer(struct pipe_screen *_screen, struct pipe_surface *_surface, @@ -904,6 +928,8 @@ trace_screen_create(struct pipe_screen *screen) tr_scr->base.get_param = trace_screen_get_param; tr_scr->base.get_paramf = trace_screen_get_paramf; tr_scr->base.is_format_supported = trace_screen_is_format_supported; + assert(screen->context_create); + tr_scr->base.context_create = trace_screen_context_create; tr_scr->base.texture_create = trace_screen_texture_create; tr_scr->base.texture_blanket = trace_screen_texture_blanket; tr_scr->base.texture_destroy = trace_screen_texture_destroy; diff --git a/src/gallium/drivers/trace/tr_screen.h b/src/gallium/drivers/trace/tr_screen.h index dba8cd7c65..fe5a0fa190 100644 --- a/src/gallium/drivers/trace/tr_screen.h +++ b/src/gallium/drivers/trace/tr_screen.h @@ -30,7 +30,7 @@ #include "pipe/p_screen.h" -#include "pipe/p_thread.h" +#include "os/os_thread.h" #ifdef __cplusplus diff --git a/src/gallium/drivers/trace/tr_texture.c b/src/gallium/drivers/trace/tr_texture.c index 1f25fe38d4..5321d68ec0 100644 --- a/src/gallium/drivers/trace/tr_texture.c +++ b/src/gallium/drivers/trace/tr_texture.c @@ -25,6 +25,7 @@ * **************************************************************************/ +#include "util/u_inlines.h" #include "util/u_hash_table.h" #include "util/u_memory.h" #include "util/u_simple_list.h" |