diff options
author | Christian König <[email protected]> | 2011-07-04 15:04:41 +0200 |
---|---|---|
committer | Christian König <[email protected]> | 2011-07-04 15:04:41 +0200 |
commit | c3b2230b71cb3a00a7f4c0987197d397bada650b (patch) | |
tree | 018f5df0f8b5976ddb56ef4f13e9466587838998 /src/gallium/drivers/i915 | |
parent | 003401f95c9b59471c22368b7da16fe7a951e490 (diff) | |
parent | 424b1210d951c206e7c2fb8f2778acbd384eb247 (diff) |
Merge remote-tracking branch 'origin/master' into pipe-video
Conflicts:
configure.ac
src/gallium/drivers/r600/r600_state_inlines.h
src/gallium/tests/trivial/Makefile
src/gallium/winsys/g3dvl/dri/XF86dri.c
src/gallium/winsys/g3dvl/dri/driclient.c
src/gallium/winsys/g3dvl/dri/driclient.h
src/gallium/winsys/g3dvl/dri/xf86dri.h
src/gallium/winsys/g3dvl/dri/xf86dristr.h
src/gallium/winsys/r600/drm/r600_bo.c
Diffstat (limited to 'src/gallium/drivers/i915')
23 files changed, 682 insertions, 168 deletions
diff --git a/src/gallium/drivers/i915/Makefile b/src/gallium/drivers/i915/Makefile index b3f387f9335..778124728bb 100644 --- a/src/gallium/drivers/i915/Makefile +++ b/src/gallium/drivers/i915/Makefile @@ -21,6 +21,7 @@ C_SOURCES = \ i915_screen.c \ i915_prim_emit.c \ i915_prim_vbuf.c \ + i915_query.c \ i915_resource.c \ i915_resource_texture.c \ i915_resource_buffer.c \ diff --git a/src/gallium/drivers/i915/SConscript b/src/gallium/drivers/i915/SConscript index 8f5deed64a9..98370601b7f 100644 --- a/src/gallium/drivers/i915/SConscript +++ b/src/gallium/drivers/i915/SConscript @@ -16,6 +16,7 @@ i915 = env.ConvenienceLibrary( 'i915_fpc_translate.c', 'i915_prim_emit.c', 'i915_prim_vbuf.c', + 'i915_query.c', 'i915_screen.c', 'i915_state.c', 'i915_state_derived.c', diff --git a/src/gallium/drivers/i915/TODO b/src/gallium/drivers/i915/TODO index fba180064c3..c26db198d20 100644 --- a/src/gallium/drivers/i915/TODO +++ b/src/gallium/drivers/i915/TODO @@ -26,5 +26,20 @@ Random list of problems with i915g: - src/xvmc/i915_structs.h in xf86-video-intel has a few more bits of various commands defined. Scavenge them and see what's useful. +- Do smarter remapping. Right now we send everything onto tex coords 0-7. + We could also use diffuse/specular and pack two sets of 2D coords in a single + 4D. Is it a big problem though? We're more limited by the # of texture + indirections and the # of instructions. + +- Leverage draw to enable more caps: + * PIPE_CAP_TGSI_INSTANCEID + * PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS + +- Finish front/back face. We need to add face support to lp_build_system_values_array and use it in draw_llvm.c. + +- Replace constants and immediates which are 0,1,-1 or a combination of those with a swizzle. + +- i915_delete_fs_state doesn't call draw_delete_fragment_shader. Why? + Other bugs can be found here: https://bugs.freedesktop.org/buglist.cgi?bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&component=Drivers/Gallium/i915g diff --git a/src/gallium/drivers/i915/i915_clear.c b/src/gallium/drivers/i915/i915_clear.c index 4a97746e981..fcb208d6dae 100644 --- a/src/gallium/drivers/i915/i915_clear.c +++ b/src/gallium/drivers/i915/i915_clear.c @@ -66,7 +66,7 @@ i915_clear_emit(struct pipe_context *pipe, unsigned buffers, const float *rgba, else clear_color = (u_color.ui & 0xffff) | (u_color.ui << 16); - util_pack_color(rgba, PIPE_FORMAT_B8G8R8A8_UNORM, &u_color); + util_pack_color(rgba, cbuf->format, &u_color); clear_color8888 = u_color.ui; } else clear_color = clear_color8888 = 0; diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c index 7a98ef73c1f..28ff40a2328 100644 --- a/src/gallium/drivers/i915/i915_context.c +++ b/src/gallium/drivers/i915/i915_context.c @@ -29,6 +29,7 @@ #include "i915_state.h" #include "i915_screen.h" #include "i915_surface.h" +#include "i915_query.h" #include "i915_batch.h" #include "i915_resource.h" @@ -53,13 +54,11 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) struct i915_context *i915 = i915_context(pipe); struct draw_context *draw = i915->draw; void *mapped_indices = NULL; - unsigned cbuf_dirty; /* * Ack vs contants here, helps ipers a lot. */ - cbuf_dirty = i915->dirty & I915_NEW_VS_CONSTANTS; i915->dirty &= ~I915_NEW_VS_CONSTANTS; if (i915->dirty) @@ -72,15 +71,13 @@ i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) mapped_indices = i915_buffer(i915->index_buffer.buffer)->data; draw_set_mapped_index_buffer(draw, mapped_indices); - if (cbuf_dirty) { - if (i915->constants[PIPE_SHADER_VERTEX]) - draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0, - i915_buffer(i915->constants[PIPE_SHADER_VERTEX])->data, - (i915->current.num_user_constants[PIPE_SHADER_VERTEX] * - 4 * sizeof(float))); - else - draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0, NULL, 0); - } + if (i915->constants[PIPE_SHADER_VERTEX]) + draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0, + i915_buffer(i915->constants[PIPE_SHADER_VERTEX])->data, + (i915->current.num_user_constants[PIPE_SHADER_VERTEX] * + 4 * sizeof(float))); + else + draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0, NULL, 0); /* * Do the drawing @@ -106,7 +103,7 @@ static void i915_destroy(struct pipe_context *pipe) if (i915->blitter) util_blitter_destroy(i915->blitter); - + if(i915->batch) i915->iws->batchbuffer_destroy(i915->batch); @@ -150,6 +147,8 @@ i915_create_context(struct pipe_screen *screen, void *priv) /* init this before draw */ util_slab_create(&i915->transfer_pool, sizeof(struct pipe_transfer), 16, UTIL_SLAB_SINGLETHREADED); + util_slab_create(&i915->texture_transfer_pool, sizeof(struct i915_transfer), + 16, UTIL_SLAB_SINGLETHREADED); /* Batch stream debugging is a bit hacked up at the moment: */ @@ -170,9 +169,11 @@ i915_create_context(struct pipe_screen *screen, void *priv) i915_init_state_functions(i915); i915_init_flush_functions(i915); i915_init_resource_functions(i915); + i915_init_query_functions(i915); draw_install_aaline_stage(i915->draw, &i915->base); draw_install_aapoint_stage(i915->draw, &i915->base); + draw_enable_point_sprites(i915->draw, TRUE); /* augmented draw pipeline clobbers state functions */ i915_init_fixup_state_functions(i915); diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h index 964948edc0e..c964208fedd 100644 --- a/src/gallium/drivers/i915/i915_context.h +++ b/src/gallium/drivers/i915/i915_context.h @@ -102,6 +102,8 @@ struct i915_fragment_shader struct tgsi_shader_info info; + struct draw_fragment_shader *draw_data; + uint *program; uint program_len; @@ -260,6 +262,7 @@ struct i915_context { int num_validation_buffers; struct util_slab_mempool transfer_pool; + struct util_slab_mempool texture_transfer_pool; /** blitter/hw-clear */ struct blitter_context* blitter; diff --git a/src/gallium/drivers/i915/i915_fpc.h b/src/gallium/drivers/i915/i915_fpc.h index 2f0f99d0468..509395cf1f5 100644 --- a/src/gallium/drivers/i915/i915_fpc.h +++ b/src/gallium/drivers/i915/i915_fpc.h @@ -37,6 +37,9 @@ #define I915_PROGRAM_SIZE 192 +/* Use those indices for pos/face routing, must be >= I915_TEX_UNITS */ +#define I915_SEMANTIC_POS 10 +#define I915_SEMANTIC_FACE 11 /** @@ -67,13 +70,13 @@ struct i915_fp_compile { uint temp_flag; /**< Tracks temporary regs which are in use */ uint utemp_flag; /**< Tracks TYPE_U temporary regs which are in use */ + uint register_phases[16]; uint nr_tex_indirect; uint nr_tex_insn; uint nr_alu_insn; uint nr_decl_insn; boolean error; /**< Set if i915_program_error() is called */ - uint wpos_tex; uint NumNativeInstructions; uint NumNativeAluInstructions; uint NumNativeTexInstructions; diff --git a/src/gallium/drivers/i915/i915_fpc_emit.c b/src/gallium/drivers/i915/i915_fpc_emit.c index 76c24d2b2fd..d28595e0fd3 100644 --- a/src/gallium/drivers/i915/i915_fpc_emit.c +++ b/src/gallium/drivers/i915/i915_fpc_emit.c @@ -67,7 +67,7 @@ i915_get_temp(struct i915_fp_compile *p) { int bit = ffs(~p->temp_flag); if (!bit) { - i915_program_error(p, "i915_get_temp: out of temporaries\n"); + i915_program_error(p, "i915_get_temp: out of temporaries"); return 0; } @@ -92,7 +92,7 @@ i915_get_utemp(struct i915_fp_compile * p) { int bit = ffs(~p->utemp_flag); if (!bit) { - i915_program_error(p, "i915_get_utemp: out of temporaries\n"); + i915_program_error(p, "i915_get_utemp: out of temporaries"); return 0; } @@ -128,9 +128,13 @@ i915_emit_decl(struct i915_fp_compile *p, else return reg; - *(p->decl++) = (D0_DCL | D0_DEST(reg) | d0_flags); - *(p->decl++) = D1_MBZ; - *(p->decl++) = D2_MBZ; + if (p->decl< p->declarations + I915_PROGRAM_SIZE) { + *(p->decl++) = (D0_DCL | D0_DEST(reg) | d0_flags); + *(p->decl++) = D1_MBZ; + *(p->decl++) = D2_MBZ; + } + else + i915_program_error(p, "Out of declarations"); p->nr_decl_insn++; return reg; @@ -187,9 +191,16 @@ i915_emit_arith(struct i915_fp_compile * p, p->utemp_flag = old_utemp_flag; /* restore */ } - *(p->csr++) = (op | A0_DEST(dest) | mask | saturate | A0_SRC0(src0)); - *(p->csr++) = (A1_SRC0(src0) | A1_SRC1(src1)); - *(p->csr++) = (A2_SRC1(src1) | A2_SRC2(src2)); + if (p->csr< p->program + I915_PROGRAM_SIZE) { + *(p->csr++) = (op | A0_DEST(dest) | mask | saturate | A0_SRC0(src0)); + *(p->csr++) = (A1_SRC0(src0) | A1_SRC1(src1)); + *(p->csr++) = (A2_SRC1(src1) | A2_SRC2(src2)); + } + else + i915_program_error(p, "Out of instructions"); + + if (GET_UREG_TYPE(dest) == REG_TYPE_R) + p->register_phases[GET_UREG_NR(dest)] = p->nr_tex_indirect; p->nr_alu_insn++; return dest; @@ -245,17 +256,31 @@ uint i915_emit_texld( struct i915_fp_compile *p, assert(GET_UREG_TYPE(dest) != REG_TYPE_CONST); assert(dest == UREG(GET_UREG_TYPE(dest), GET_UREG_NR(dest))); - /* is the sampler coord a texcoord input reg? */ - if (GET_UREG_TYPE(coord) != REG_TYPE_T) { - p->nr_tex_indirect++; - } + /* Output register being oC or oD defines a phase boundary */ + if (GET_UREG_TYPE(dest) == REG_TYPE_OC || + GET_UREG_TYPE(dest) == REG_TYPE_OD) + p->nr_tex_indirect++; - *(p->csr++) = (opcode | - T0_DEST( dest ) | - T0_SAMPLER( sampler )); + /* Reading from an r# register whose contents depend on output of the + * current phase defines a phase boundary. + */ + if (GET_UREG_TYPE(coord) == REG_TYPE_R && + p->register_phases[GET_UREG_NR(coord)] == p->nr_tex_indirect) + p->nr_tex_indirect++; + + if (p->csr< p->program + I915_PROGRAM_SIZE) { + *(p->csr++) = (opcode | + T0_DEST( dest ) | + T0_SAMPLER( sampler )); + + *(p->csr++) = T1_ADDRESS_REG( coord ); + *(p->csr++) = T2_MBZ; + } + else + i915_program_error(p, "Out of instructions"); - *(p->csr++) = T1_ADDRESS_REG( coord ); - *(p->csr++) = T2_MBZ; + if (GET_UREG_TYPE(dest) == REG_TYPE_R) + p->register_phases[GET_UREG_NR(dest)] = p->nr_tex_indirect; p->nr_tex_insn++; } @@ -293,7 +318,7 @@ i915_emit_const1f(struct i915_fp_compile * p, float c0) } } - i915_program_error(p, "i915_emit_const1f: out of constants\n"); + i915_program_error(p, "i915_emit_const1f: out of constants"); return 0; } @@ -313,6 +338,8 @@ i915_emit_const2f(struct i915_fp_compile * p, float c0, float c1) if (c1 == 1.0) return swizzle(i915_emit_const1f(p, c0), X, ONE, Z, W); + // XXX emit swizzle here for 0, 1, -1 and any combination thereof + // we can use swizzle + neg for that for (reg = 0; reg < I915_MAX_CONSTANT; reg++) { if (ifs->constant_flags[reg] == 0xf || ifs->constant_flags[reg] == I915_CONSTFLAG_USER) @@ -329,12 +356,10 @@ i915_emit_const2f(struct i915_fp_compile * p, float c0, float c1) } } - i915_program_error(p, "i915_emit_const2f: out of constants\n"); + i915_program_error(p, "i915_emit_const2f: out of constants"); return 0; } - - uint i915_emit_const4f(struct i915_fp_compile * p, float c0, float c1, float c2, float c3) @@ -342,6 +367,9 @@ i915_emit_const4f(struct i915_fp_compile * p, struct i915_fragment_shader *ifs = p->shader; unsigned reg; + // XXX emit swizzle here for 0, 1, -1 and any combination thereof + // we can use swizzle + neg for that + printf("const %f %f %f %f\n",c0,c1,c2,c3); for (reg = 0; reg < I915_MAX_CONSTANT; reg++) { if (ifs->constant_flags[reg] == 0xf && ifs->constants[reg][0] == c0 && @@ -363,7 +391,7 @@ i915_emit_const4f(struct i915_fp_compile * p, } } - i915_program_error(p, "i915_emit_const4f: out of constants\n"); + i915_program_error(p, "i915_emit_const4f: out of constants"); return 0; } diff --git a/src/gallium/drivers/i915/i915_fpc_translate.c b/src/gallium/drivers/i915/i915_fpc_translate.c index 27f100843bf..0cbd4f2d748 100644 --- a/src/gallium/drivers/i915/i915_fpc_translate.c +++ b/src/gallium/drivers/i915/i915_fpc_translate.c @@ -41,6 +41,9 @@ #include "draw/draw_vertex.h" +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif /** * Simple pass-through fragment shader to use when we don't have @@ -72,19 +75,33 @@ static unsigned passthrough[] = /* 1, -1/3!, 1/5!, -1/7! */ -static const float sin_constants[4] = { 1.0, +static const float scs_sin_constants[4] = { 1.0, -1.0f / (3 * 2 * 1), 1.0f / (5 * 4 * 3 * 2 * 1), -1.0f / (7 * 6 * 5 * 4 * 3 * 2 * 1) }; /* 1, -1/2!, 1/4!, -1/6! */ -static const float cos_constants[4] = { 1.0, +static const float scs_cos_constants[4] = { 1.0, -1.0f / (2 * 1), 1.0f / (4 * 3 * 2 * 1), -1.0f / (6 * 5 * 4 * 3 * 2 * 1) }; +/* 2*pi, -(2*pi)^3/3!, (2*pi)^5/5!, -(2*pi)^7/7! */ +static const float sin_constants[4] = { 2.0 * M_PI, + -8.0f * M_PI * M_PI * M_PI / (3 * 2 * 1), + 32.0f * M_PI * M_PI * M_PI * M_PI * M_PI / (5 * 4 * 3 * 2 * 1), + -128.0f * M_PI * M_PI * M_PI * M_PI * M_PI * M_PI * M_PI / (7 * 6 * 5 * 4 * 3 * 2 * 1) +}; + +/* 1, -(2*pi)^2/2!, (2*pi)^4/4!, -(2*pi)^6/6! */ +static const float cos_constants[4] = { 1.0, + -4.0f * M_PI * M_PI / (2 * 1), + 16.0f * M_PI * M_PI * M_PI * M_PI / (4 * 3 * 2 * 1), + -64.0f * M_PI * M_PI * M_PI * M_PI * M_PI * M_PI / (6 * 5 * 4 * 3 * 2 * 1) +}; + /** @@ -185,12 +202,12 @@ src_vector(struct i915_fp_compile *p, switch (sem_name) { case TGSI_SEMANTIC_POSITION: - debug_printf("SKIP SEM POS\n"); - /* - assert(p->wpos_tex != -1); - src = i915_emit_decl(p, REG_TYPE_T, p->wpos_tex, D0_CHANNEL_ALL); - */ - break; + { + /* for fragcoord */ + int real_tex_unit = get_mapping(fs, I915_SEMANTIC_POS); + src = i915_emit_decl(p, REG_TYPE_T, T_TEX0 + real_tex_unit, D0_CHANNEL_ALL); + break; + } case TGSI_SEMANTIC_COLOR: if (sem_ind == 0) { src = i915_emit_decl(p, REG_TYPE_T, T_DIFFUSE, D0_CHANNEL_ALL); @@ -212,6 +229,13 @@ src_vector(struct i915_fp_compile *p, src = i915_emit_decl(p, REG_TYPE_T, T_TEX0 + real_tex_unit, D0_CHANNEL_ALL); break; } + case TGSI_SEMANTIC_FACE: + { + /* for back/front faces */ + int real_tex_unit = get_mapping(fs, I915_SEMANTIC_FACE); + src = i915_emit_decl(p, REG_TYPE_T, T_TEX0 + real_tex_unit, D0_CHANNEL_X); + break; + } default: i915_program_error(p, "Bad source->Index"); return 0; @@ -237,7 +261,6 @@ src_vector(struct i915_fp_compile *p, source->Register.SwizzleZ, source->Register.SwizzleW); - /* There's both negate-all-components and per-component negation. * Try to handle both here. */ @@ -252,6 +275,9 @@ src_vector(struct i915_fp_compile *p, /* XXX enable these assertions, or fix things */ assert(!source->Register.Absolute); #endif + if (source->Register.Absolute) + debug_printf("Unhandled absolute value\n"); + return src; } @@ -419,11 +445,6 @@ emit_simple_arith_swap2(struct i915_fp_compile *p, emit_simple_arith(p, &inst2, opcode, numArgs, fs); } - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - /* * Translate TGSI instruction to i915 instruction. * @@ -477,13 +498,6 @@ i915_translate_instruction(struct i915_fp_compile *p, i915_emit_arith(p, A0_MOD, tmp, A0_DEST_CHANNEL_X, 0, tmp, 0, 0); - /* By choosing different taylor constants, could get rid of this mul: - */ - i915_emit_arith(p, - A0_MUL, - tmp, A0_DEST_CHANNEL_X, 0, - tmp, i915_emit_const1f(p, (float) (M_PI * 2.0)), 0); - /* * t0.xy = MUL x.xx11, x.x1111 ; x^2, x, 1, 1 * t0 = MUL t0.xyxy t0.xx11 ; x^4, x^3, x^2, 1 @@ -516,6 +530,18 @@ i915_translate_instruction(struct i915_fp_compile *p, i915_emit_const4fv(p, cos_constants), 0); break; + case TGSI_OPCODE_DDX: + case TGSI_OPCODE_DDY: + /* XXX We just output 0 here */ + debug_printf("Punting DDX/DDX\n"); + src0 = get_result_vector(p, &inst->Dst[0]); + i915_emit_arith(p, + A0_MOV, + get_result_vector(p, &inst->Dst[0]), + get_result_flags(inst), 0, + swizzle(src0, ZERO, ZERO, ZERO, ZERO), 0, 0); + break; + case TGSI_OPCODE_DP2: src0 = src_vector(p, &inst->Src[0], fs); src1 = src_vector(p, &inst->Src[1], fs); @@ -754,9 +780,9 @@ i915_translate_instruction(struct i915_fp_compile *p, * t0.xy = MUL x.xx11, x.x1111 ; x^2, x, 1, 1 * t0 = MUL t0.xyxy t0.xx11 ; x^4, x^3, x^2, x * t1 = MUL t0.xyyw t0.yz11 ; x^7 x^5 x^3 x - * scs.x = DP4 t1, sin_constants + * scs.x = DP4 t1, scs_sin_constants * t1 = MUL t0.xxz1 t0.z111 ; x^6 x^4 x^2 1 - * scs.y = DP4 t1, cos_constants + * scs.y = DP4 t1, scs_cos_constants */ i915_emit_arith(p, A0_MUL, @@ -791,7 +817,7 @@ i915_translate_instruction(struct i915_fp_compile *p, get_result_vector(p, &inst->Dst[0]), A0_DEST_CHANNEL_Y, 0, swizzle(tmp1, W, Z, Y, X), - i915_emit_const4fv(p, sin_constants), 0); + i915_emit_const4fv(p, scs_sin_constants), 0); } if (writemask & TGSI_WRITEMASK_X) { @@ -806,7 +832,7 @@ i915_translate_instruction(struct i915_fp_compile *p, get_result_vector(p, &inst->Dst[0]), A0_DEST_CHANNEL_X, 0, swizzle(tmp, ONE, Z, Y, X), - i915_emit_const4fv(p, cos_constants), 0); + i915_emit_const4fv(p, scs_cos_constants), 0); } break; @@ -853,13 +879,6 @@ i915_translate_instruction(struct i915_fp_compile *p, i915_emit_arith(p, A0_MOD, tmp, A0_DEST_CHANNEL_X, 0, tmp, 0, 0); - /* By choosing different taylor constants, could get rid of this mul: - */ - i915_emit_arith(p, - A0_MUL, - tmp, A0_DEST_CHANNEL_X, 0, - tmp, i915_emit_const1f(p, (float) (M_PI * 2.0)), 0); - /* * t0.xy = MUL x.xx11, x.x1111 ; x^2, x, 1, 1 * t0 = MUL t0.xyxy t0.xx11 ; x^4, x^3, x^2, x @@ -907,7 +926,7 @@ i915_translate_instruction(struct i915_fp_compile *p, break; case TGSI_OPCODE_SNE: - /* if we're neither < nor > then we're != */ + /* if we're < or > then we're != */ src0 = src_vector(p, &inst->Src[0], fs); src1 = src_vector(p, &inst->Src[1], fs); tmp = i915_get_utemp(p); @@ -1070,9 +1089,11 @@ i915_translate_instructions(struct i915_fp_compile *p, for (i = parse.FullToken.FullDeclaration.Range.First; i <= parse.FullToken.FullDeclaration.Range.Last; i++) { - assert(i < I915_MAX_TEMPORARY); - /* XXX just use shader->info->file_mask[TGSI_FILE_TEMPORARY] */ - p->temp_flag |= (1 << i); /* mark temp as used */ + if (i >= I915_MAX_TEMPORARY) + debug_printf("Too many temps (%d)\n",i); + else + /* XXX just use shader->info->file_mask[TGSI_FILE_TEMPORARY] */ + p->temp_flag |= (1 << i); /* mark temp as used */ } } break; @@ -1144,6 +1165,8 @@ i915_init_compile(struct i915_context *i915, ifs->num_constants = 0; memset(ifs->constant_flags, 0, sizeof(ifs->constant_flags)); + memset(&p->register_phases, 0, sizeof(p->register_phases)); + for (i = 0; i < I915_TEX_UNITS; i++) ifs->generic_mapping[i] = -1; @@ -1161,8 +1184,6 @@ i915_init_compile(struct i915_context *i915, p->temp_flag = ~0x0 << I915_MAX_TEMPORARY; p->utemp_flag = ~0x7; - p->wpos_tex = -1; - /* initialize the first program word */ *(p->decl++) = _3DSTATE_PIXEL_SHADER_PROGRAM; @@ -1181,7 +1202,7 @@ i915_fini_compile(struct i915_context *i915, struct i915_fp_compile *p) unsigned long decl_size = (unsigned long) (p->decl - p->declarations); if (p->nr_tex_indirect > I915_MAX_TEX_INDIRECT) - i915_program_error(p, "Exceeded max nr indirect texture lookups"); + debug_printf("Exceeded max nr indirect texture lookups\n"); if (p->nr_tex_insn > I915_MAX_TEX_INSN) i915_program_error(p, "Exceeded max TEX instructions"); @@ -1234,40 +1255,6 @@ i915_fini_compile(struct i915_context *i915, struct i915_fp_compile *p) } -/** - * Find an unused texture coordinate slot to use for fragment WPOS. - * Update p->fp->wpos_tex with the result (-1 if no used texcoord slot is found). - */ -static void -i915_find_wpos_space(struct i915_fp_compile *p) -{ -#if 0 - const uint inputs - = p->shader->inputs_read | (1 << TGSI_ATTRIB_POS); /*XXX hack*/ - uint i; - - p->wpos_tex = -1; - - if (inputs & (1 << TGSI_ATTRIB_POS)) { - for (i = 0; i < I915_TEX_UNITS; i++) { - if ((inputs & (1 << (TGSI_ATTRIB_TEX0 + i))) == 0) { - p->wpos_tex = i; - return; - } - } - - i915_program_error(p, "No free texcoord for wpos value"); - } -#else - if (p->shader->info.input_semantic_name[0] == TGSI_SEMANTIC_POSITION) { - /* frag shader using the fragment position input */ -#if 0 - assert(0); -#endif - } -#endif -} - @@ -1314,7 +1301,6 @@ i915_translate_fragment_program( struct i915_context *i915, } p = i915_init_compile(i915, fs); - i915_find_wpos_space(p); i915_translate_instructions(p, tokens, fs); i915_fixup_depth_write(p); diff --git a/src/gallium/drivers/i915/i915_query.c b/src/gallium/drivers/i915/i915_query.c new file mode 100644 index 00000000000..c886df74bad --- /dev/null +++ b/src/gallium/drivers/i915/i915_query.c @@ -0,0 +1,86 @@ +/************************************************************************** + * + * Copyright 2011 The Chromium OS authors. + * 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 GOOGLE 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. + * + **************************************************************************/ + +/* Fake occlusion queries which return 0, it's better than crashing */ + +#include "pipe/p_compiler.h" + +#include "util/u_memory.h" + +#include "i915_context.h" +#include "i915_query.h" + +struct i915_query +{ + unsigned query; +}; + +static struct pipe_query *i915_create_query(struct pipe_context *ctx, + unsigned query_type) +{ + struct i915_query *query = CALLOC_STRUCT( i915_query ); + + return (struct pipe_query *)query; +} + +static void i915_destroy_query(struct pipe_context *ctx, + struct pipe_query *query) +{ + FREE(query); +} + +static void i915_begin_query(struct pipe_context *ctx, + struct pipe_query *query) +{ +} + +static void i915_end_query(struct pipe_context *ctx, struct pipe_query *query) +{ +} + +static boolean i915_get_query_result(struct pipe_context *ctx, + struct pipe_query *query, + boolean wait, + void *vresult) +{ + uint64_t *result = (uint64_t*)vresult; + + /* 2* viewport Max */ + *result = 512*1024*1024; + return TRUE; +} + +void +i915_init_query_functions(struct i915_context *i915) +{ + i915->base.create_query = i915_create_query; + i915->base.destroy_query = i915_destroy_query; + i915->base.begin_query = i915_begin_query; + i915->base.end_query = i915_end_query; + i915->base.get_query_result = i915_get_query_result; +} + diff --git a/src/gallium/drivers/i915/i915_query.h b/src/gallium/drivers/i915/i915_query.h new file mode 100644 index 00000000000..2c689ea6b1c --- /dev/null +++ b/src/gallium/drivers/i915/i915_query.h @@ -0,0 +1,36 @@ +/************************************************************************** + * + * Copyright 2011 The Chromium OS authors. + * 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 GOOGLE 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 I915_QUERY_H +#define I915_QUERY_H + +struct i915_context; +struct pipe_context; + +void i915_init_query_functions( struct i915_context *i915 ); + +#endif /* I915_QUERY_H */ diff --git a/src/gallium/drivers/i915/i915_reg.h b/src/gallium/drivers/i915/i915_reg.h index 6fe032cdb6e..14e786d0f2a 100644 --- a/src/gallium/drivers/i915/i915_reg.h +++ b/src/gallium/drivers/i915/i915_reg.h @@ -170,6 +170,13 @@ #define COLOR_BUF_RGB555 (1<<8) #define COLOR_BUF_RGB565 (2<<8) #define COLOR_BUF_ARGB8888 (3<<8) +#define COLOR_BUF_YCRCB_SWAP (4<<8) +#define COLOR_BUF_YCRCB_NORMAL (5<<8) +#define COLOR_BUF_YCRCB_SWAPUV (6<<8) +#define COLOR_BUF_YCRCB_SWAPUVY (7<<8) +#define COLOR_BUF_ARGB4444 (8<<8) +#define COLOR_BUF_ARGB1555 (9<<8) +#define COLOR_BUF_ARGB2101010 (10<<8) #define DEPTH_FRMT_16_FIXED 0 #define DEPTH_FRMT_16_FLOAT (1<<2) #define DEPTH_FRMT_24_FIXED_8_OTHER (2<<2) diff --git a/src/gallium/drivers/i915/i915_resource.c b/src/gallium/drivers/i915/i915_resource.c index 7f52ba11d61..b4719af1fb6 100644 --- a/src/gallium/drivers/i915/i915_resource.c +++ b/src/gallium/drivers/i915/i915_resource.c @@ -7,12 +7,12 @@ static struct pipe_resource * i915_resource_create(struct pipe_screen *screen, - const struct pipe_resource *template) + const struct pipe_resource *template) { if (template->target == PIPE_BUFFER) return i915_buffer_create(screen, template); else - return i915_texture_create(screen, template); + return i915_texture_create(screen, template, FALSE); } diff --git a/src/gallium/drivers/i915/i915_resource.h b/src/gallium/drivers/i915/i915_resource.h index c15ecdfc22a..14eed2c4a79 100644 --- a/src/gallium/drivers/i915/i915_resource.h +++ b/src/gallium/drivers/i915/i915_resource.h @@ -45,6 +45,15 @@ struct i915_buffer { boolean free_on_destroy; }; + +/* Texture transfer. */ +struct i915_transfer { + /* Base class. */ + struct pipe_transfer b; + struct pipe_resource *staging_texture; +}; + + #define I915_MAX_TEXTURE_2D_LEVELS 12 /* max 2048x2048 */ #define I915_MAX_TEXTURE_3D_LEVELS 9 /* max 256x256x256 */ @@ -101,7 +110,8 @@ static INLINE struct i915_buffer *i915_buffer(struct pipe_resource *resource) struct pipe_resource * i915_texture_create(struct pipe_screen *screen, - const struct pipe_resource *template); + const struct pipe_resource *template, + boolean force_untiled); struct pipe_resource * i915_texture_from_handle(struct pipe_screen * screen, diff --git a/src/gallium/drivers/i915/i915_resource_texture.c b/src/gallium/drivers/i915/i915_resource_texture.c index b74b19d0fe4..0b6424f8d16 100644 --- a/src/gallium/drivers/i915/i915_resource_texture.c +++ b/src/gallium/drivers/i915/i915_resource_texture.c @@ -37,6 +37,7 @@ #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_rect.h" #include "i915_context.h" #include "i915_resource.h" @@ -710,7 +711,7 @@ i915_texture_destroy(struct pipe_screen *screen, FREE(tex); } -static struct pipe_transfer * +static struct pipe_transfer * i915_texture_get_transfer(struct pipe_context *pipe, struct pipe_resource *resource, unsigned level, @@ -719,19 +720,45 @@ i915_texture_get_transfer(struct pipe_context *pipe, { struct i915_context *i915 = i915_context(pipe); struct i915_texture *tex = i915_texture(resource); - struct pipe_transfer *transfer = util_slab_alloc(&i915->transfer_pool); + struct i915_transfer *transfer = util_slab_alloc(&i915->texture_transfer_pool); + boolean use_staging_texture = FALSE; if (transfer == NULL) return NULL; - transfer->resource = resource; - transfer->level = level; - transfer->usage = usage; - transfer->box = *box; - transfer->stride = tex->stride; - /* FIXME: layer_stride */ + transfer->b.resource = resource; + transfer->b.level = level; + transfer->b.usage = usage; + transfer->b.box = *box; + transfer->b.stride = tex->stride; + transfer->staging_texture = NULL; + /* XXX: handle depth textures everyhwere*/ + transfer->b.layer_stride = 0; + transfer->b.data = NULL; + + /* if we use staging transfers, only support textures we can render to, + * because we need that for u_blitter */ + if (i915->blitter && + i915_is_format_supported(NULL, /* screen */ + transfer->b.resource->format, + 0, /* target */ + 1, /* sample count */ + PIPE_BIND_RENDER_TARGET) && + (usage & PIPE_TRANSFER_WRITE) && + !(usage & (PIPE_TRANSFER_READ | PIPE_TRANSFER_DONTBLOCK | PIPE_TRANSFER_UNSYNCHRONIZED))) + use_staging_texture = TRUE; + + use_staging_texture = FALSE; + + if (use_staging_texture) { + /* + * Allocate the untiled staging texture. + * If the alloc fails, transfer->staging_texture is NULL and we fallback to a map() + */ + transfer->staging_texture = i915_texture_create(pipe->screen, resource, TRUE); + } - return transfer; + return (struct pipe_transfer*)transfer; } static void @@ -739,17 +766,33 @@ i915_transfer_destroy(struct pipe_context *pipe, struct pipe_transfer *transfer) { struct i915_context *i915 = i915_context(pipe); - util_slab_free(&i915->transfer_pool, transfer); + struct i915_transfer *itransfer = (struct i915_transfer*)transfer; + + if ((itransfer->staging_texture) && + (transfer->usage & PIPE_TRANSFER_WRITE)) { + struct pipe_box sbox; + + u_box_origin_2d(itransfer->b.box.width, itransfer->b.box.height, &sbox); + pipe->resource_copy_region(pipe, itransfer->b.resource, itransfer->b.level, + itransfer->b.box.x, itransfer->b.box.y, itransfer->b.box.z, + itransfer->staging_texture, + 0, &sbox); + pipe->flush(pipe, NULL); + pipe_resource_reference(&itransfer->staging_texture, NULL); + } + + util_slab_free(&i915->texture_transfer_pool, itransfer); } static void * i915_texture_transfer_map(struct pipe_context *pipe, struct pipe_transfer *transfer) { - struct pipe_resource *resource = transfer->resource; - struct i915_texture *tex = i915_texture(resource); + struct i915_transfer *itransfer = (struct i915_transfer*)transfer; + struct pipe_resource *resource = itransfer->b.resource; + struct i915_texture *tex = NULL; struct i915_winsys *iws = i915_screen(pipe->screen)->iws; - struct pipe_box *box = &transfer->box; + struct pipe_box *box = &itransfer->b.box; enum pipe_format format = resource->format; unsigned offset; char *map; @@ -757,18 +800,25 @@ i915_texture_transfer_map(struct pipe_context *pipe, if (resource->target != PIPE_TEXTURE_3D && resource->target != PIPE_TEXTURE_CUBE) assert(box->z == 0); - offset = i915_texture_offset(tex, transfer->level, box->z); - /* TODO this is a sledgehammer */ - pipe->flush(pipe, NULL); + if (itransfer->staging_texture) { + tex = i915_texture(itransfer->staging_texture); + } else { + /* TODO this is a sledgehammer */ + tex = i915_texture(resource); + pipe->flush(pipe, NULL); + } + + offset = i915_texture_offset(tex, itransfer->b.level, box->z); map = iws->buffer_map(iws, tex->buffer, - (transfer->usage & PIPE_TRANSFER_WRITE) ? TRUE : FALSE); - if (map == NULL) + (itransfer->b.usage & PIPE_TRANSFER_WRITE) ? TRUE : FALSE); + if (map == NULL) { return NULL; + } return map + offset + - box->y / util_format_get_blockheight(format) * transfer->stride + + box->y / util_format_get_blockheight(format) * itransfer->b.stride + box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); } @@ -776,14 +826,106 @@ static void i915_texture_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *transfer) { - struct i915_texture *tex = i915_texture(transfer->resource); + struct i915_transfer *itransfer = (struct i915_transfer*)transfer; + struct i915_texture *tex = i915_texture(itransfer->b.resource); struct i915_winsys *iws = i915_screen(tex->b.b.screen)->iws; + + if (itransfer->staging_texture) + tex = i915_texture(itransfer->staging_texture); + iws->buffer_unmap(iws, tex->buffer); } +static void i915_transfer_inline_write( struct pipe_context *pipe, + struct pipe_resource *resource, + unsigned level, + unsigned usage, + const struct pipe_box *box, + const void *data, + unsigned stride, + unsigned layer_stride) +{ + struct pipe_transfer *transfer = NULL; + struct i915_transfer *itransfer = NULL; + const uint8_t *src_data = data; + unsigned i; + + transfer = pipe->get_transfer(pipe, + resource, + level, + usage, + box ); + if (transfer == NULL) + goto out; + + itransfer = (struct i915_transfer*)transfer; + + if (itransfer->staging_texture) { + struct i915_texture *tex = i915_texture(itransfer->staging_texture); + enum pipe_format format = tex->b.b.format; + struct i915_winsys *iws = i915_screen(tex->b.b.screen)->iws; + size_t offset; + size_t size; + + offset = i915_texture_offset(tex, transfer->level, transfer->box.z); + + for (i = 0; i < box->depth; i++) { + if (!tex->b.b.last_level && + tex->b.b.width0 == transfer->box.width) { + unsigned nby = util_format_get_nblocksy(format, transfer->box.y); + assert(!offset); + assert(!transfer->box.x); + assert(tex->stride == transfer->stride); + + offset += tex->stride * nby; + size = util_format_get_2d_size(format, transfer->stride, + transfer->box.height); + iws->buffer_write(iws, tex->buffer, offset, size, transfer->data); + + } else { + unsigned nby = util_format_get_nblocksy(format, transfer->box.y); + int i; + offset += util_format_get_stride(format, transfer->box.x); + size = transfer->stride; + + for (i = 0; i < nby; i++) { + iws->buffer_write(iws, tex->buffer, offset, size, transfer->data); + offset += tex->stride; + } + } + offset += layer_stride; + } + } else { + uint8_t *map = pipe_transfer_map(pipe, &itransfer->b); + if (map == NULL) + goto nomap; + + for (i = 0; i < box->depth; i++) { + util_copy_rect(map, + resource->format, + itransfer->b.stride, /* bytes */ + 0, 0, + box->width, + box->height, + src_data, + stride, /* bytes */ + 0, 0); + map += itransfer->b.layer_stride; + src_data += layer_stride; + } +nomap: + if (map) + pipe_transfer_unmap(pipe, &itransfer->b); + } + +out: + if (itransfer) + pipe_transfer_destroy(pipe, &itransfer->b); +} -struct u_resource_vtbl i915_texture_vtbl = + +struct u_resource_vtbl i915_texture_vtbl = { i915_texture_get_handle, /* get_handle */ i915_texture_destroy, /* resource_destroy */ @@ -792,7 +934,7 @@ struct u_resource_vtbl i915_texture_vtbl = i915_texture_transfer_map, /* transfer_map */ u_default_transfer_flush_region, /* transfer_flush_region */ i915_texture_transfer_unmap, /* transfer_unmap */ - u_default_transfer_inline_write /* transfer_inline_write */ + i915_transfer_inline_write /* transfer_inline_write */ }; @@ -800,7 +942,8 @@ struct u_resource_vtbl i915_texture_vtbl = struct pipe_resource * i915_texture_create(struct pipe_screen *screen, - const struct pipe_resource *template) + const struct pipe_resource *template, + boolean force_untiled) { struct i915_screen *is = i915_screen(screen); struct i915_winsys *iws = is->iws; @@ -815,7 +958,10 @@ i915_texture_create(struct pipe_screen *screen, pipe_reference_init(&tex->b.b.reference, 1); tex->b.b.screen = screen; - tex->tiling = i915_texture_tiling(is, tex); + if (force_untiled) + tex->tiling = I915_TILE_NONE; + else + tex->tiling = i915_texture_tiling(is, tex); if (is->is_i945) { if (!i945_texture_layout(tex)) @@ -836,7 +982,7 @@ i915_texture_create(struct pipe_screen *screen, buf_usage = I915_NEW_TEXTURE; tex->buffer = iws->buffer_create_tiled(iws, &tex->stride, tex->total_nblocksy, - &tex->tiling, buf_usage); + &tex->tiling, buf_usage); if (!tex->buffer) goto fail; diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c index c86baa58b28..e743f6031eb 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -109,17 +109,17 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap cap) case PIPE_CAP_ANISOTROPIC_FILTER: case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: case PIPE_CAP_NPOT_TEXTURES: + case PIPE_CAP_POINT_SPRITE: case PIPE_CAP_PRIMITIVE_RESTART: /* draw module */ case PIPE_CAP_TEXTURE_MIRROR_REPEAT: case PIPE_CAP_TEXTURE_SHADOW_MAP: case PIPE_CAP_TWO_SIDED_STENCIL: + case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: return 1; /* Features that should be supported (boolean caps). */ /* XXX: Just test the code */ case PIPE_CAP_BLEND_EQUATION_SEPARATE: - /* XXX: No code but hw supports it */ - case PIPE_CAP_POINT_SPRITE: /* Also lie about these when asked to (needed for GLSL / GL 2.0) */ return is->debug.lie ? 1 : 0; @@ -129,7 +129,6 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap cap) case PIPE_CAP_INDEP_BLEND_ENABLE: case PIPE_CAP_INDEP_BLEND_FUNC: case PIPE_CAP_TGSI_INSTANCEID: - case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: case PIPE_CAP_SHADER_STENCIL_EXPORT: case PIPE_CAP_TEXTURE_MIRROR_CLAMP: case PIPE_CAP_TEXTURE_SWIZZLE: @@ -254,7 +253,7 @@ i915_get_paramf(struct pipe_screen *screen, enum pipe_cap cap) } } -static boolean +boolean i915_is_format_supported(struct pipe_screen *screen, enum pipe_format format, enum pipe_texture_target target, @@ -264,7 +263,10 @@ i915_is_format_supported(struct pipe_screen *screen, static const enum pipe_format tex_supported[] = { PIPE_FORMAT_B8G8R8A8_UNORM, PIPE_FORMAT_B8G8R8X8_UNORM, + PIPE_FORMAT_R8G8B8A8_UNORM, + PIPE_FORMAT_R8G8B8X8_UNORM, PIPE_FORMAT_B5G6R5_UNORM, + PIPE_FORMAT_B10G10R10A2_UNORM, PIPE_FORMAT_L8_UNORM, PIPE_FORMAT_A8_UNORM, PIPE_FORMAT_I8_UNORM, @@ -283,7 +285,12 @@ i915_is_format_supported(struct pipe_screen *screen, }; static const enum pipe_format render_supported[] = { PIPE_FORMAT_B8G8R8A8_UNORM, + PIPE_FORMAT_R8G8B8A8_UNORM, PIPE_FORMAT_B5G6R5_UNORM, + PIPE_FORMAT_B10G10R10A2_UNORM, + PIPE_FORMAT_L8_UNORM, + PIPE_FORMAT_A8_UNORM, + PIPE_FORMAT_I8_UNORM, PIPE_FORMAT_NONE /* list terminator */ }; static const enum pipe_format depth_supported[] = { diff --git a/src/gallium/drivers/i915/i915_screen.h b/src/gallium/drivers/i915/i915_screen.h index cfc585b5350..9f2004eb942 100644 --- a/src/gallium/drivers/i915/i915_screen.h +++ b/src/gallium/drivers/i915/i915_screen.h @@ -65,5 +65,11 @@ i915_screen(struct pipe_screen *pscreen) return (struct i915_screen *) pscreen; } +boolean +i915_is_format_supported(struct pipe_screen *screen, + enum pipe_format format, + enum pipe_texture_target target, + unsigned sample_count, + unsigned tex_usage); #endif /* I915_SCREEN_H */ diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c index 1b57c5776f2..f412626955d 100644 --- a/src/gallium/drivers/i915/i915_state.c +++ b/src/gallium/drivers/i915/i915_state.c @@ -146,6 +146,7 @@ i915_create_blend_state(struct pipe_context *pipe, if (blend->dither) cso_data->LIS5 |= S5_COLOR_DITHER_ENABLE; + /* XXX here take the target fixup into account */ if ((blend->rt[0].colormask & PIPE_MASK_R) == 0) cso_data->LIS5 |= S5_WRITEDISABLE_RED; @@ -246,7 +247,7 @@ i915_create_sampler_state(struct pipe_context *pipe, if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { cso->state[0] |= (SS2_SHADOW_ENABLE | - i915_translate_compare_func(sampler->compare_func)); + i915_translate_shadow_compare_func(sampler->compare_func)); minFilt = FILTER_4X4_FLAT; magFilt = FILTER_4X4_FLAT; @@ -466,6 +467,7 @@ i915_create_fs_state(struct pipe_context *pipe, if (!ifs) return NULL; + ifs->draw_data = draw_create_fragment_shader(i915->draw, templ); ifs->state.tokens = tgsi_dup_tokens(templ->tokens); tgsi_scan_shader(templ->tokens, &ifs->info); @@ -495,6 +497,8 @@ i915_bind_fs_state(struct pipe_context *pipe, void *shader) i915->fs = (struct i915_fragment_shader*) shader; + draw_bind_fragment_shader(i915->draw, (i915->fs ? i915->fs->draw_data : NULL)); + i915->dirty |= I915_NEW_FS; } @@ -503,12 +507,14 @@ void i915_delete_fs_state(struct pipe_context *pipe, void *shader) { struct i915_fragment_shader *ifs = (struct i915_fragment_shader *) shader; - if (ifs->program) + if (ifs->program) { FREE(ifs->program); + ifs->program = NULL; + FREE((struct tgsi_token *)ifs->state.tokens); + ifs->state.tokens = NULL; + } ifs->program_len = 0; - FREE((struct tgsi_token *)ifs->state.tokens); - FREE(ifs); } diff --git a/src/gallium/drivers/i915/i915_state_derived.c b/src/gallium/drivers/i915/i915_state_derived.c index bf6b30a4530..e01f16e715c 100644 --- a/src/gallium/drivers/i915/i915_state_derived.c +++ b/src/gallium/drivers/i915/i915_state_derived.c @@ -33,9 +33,10 @@ #include "i915_context.h" #include "i915_state.h" #include "i915_debug.h" +#include "i915_fpc.h" #include "i915_reg.h" -static uint find_mapping(struct i915_fragment_shader* fs, int unit) +static uint find_mapping(const struct i915_fragment_shader* fs, int unit) { int i; for (i = 0; i < I915_TEX_UNITS ; i++) @@ -58,12 +59,12 @@ static void calculate_vertex_layout(struct i915_context *i915) const struct i915_fragment_shader *fs = i915->fs; const enum interp_mode colorInterp = i915->rasterizer->color_interp; struct vertex_info vinfo; - boolean texCoords[I915_TEX_UNITS], colors[2], fog, needW; + boolean texCoords[I915_TEX_UNITS], colors[2], fog, needW, face; uint i; int src; memset(texCoords, 0, sizeof(texCoords)); - colors[0] = colors[1] = fog = needW = FALSE; + colors[0] = colors[1] = fog = needW = face = FALSE; memset(&vinfo, 0, sizeof(vinfo)); /* Determine which fragment program inputs are needed. Setup HW vertex @@ -72,6 +73,10 @@ static void calculate_vertex_layout(struct i915_context *i915) for (i = 0; i < fs->info.num_inputs; i++) { switch (fs->info.input_semantic_name[i]) { case TGSI_SEMANTIC_POSITION: + { + uint unit = I915_SEMANTIC_POS; + texCoords[find_mapping(fs, unit)] = TRUE; + } break; case TGSI_SEMANTIC_COLOR: assert(fs->info.input_semantic_index[i] < 2); @@ -80,7 +85,6 @@ static void calculate_vertex_layout(struct i915_context *i915) case TGSI_SEMANTIC_GENERIC: { /* texcoords/varyings/other generic */ - /* XXX handle back/front face and point size */ uint unit = fs->info.input_semantic_index[i]; texCoords[find_mapping(fs, unit)] = TRUE; @@ -90,7 +94,11 @@ static void calculate_vertex_layout(struct i915_context *i915) case TGSI_SEMANTIC_FOG: fog = TRUE; break; + case TGSI_SEMANTIC_FACE: + face = TRUE; + break; default: + debug_printf("Unknown input type %d\n", fs->info.input_semantic_name[i]); assert(0); } } @@ -147,6 +155,20 @@ static void calculate_vertex_layout(struct i915_context *i915) vinfo.hwfmt[1] |= hwtc << (i * 4); } + /* front/back face */ + if (face) { + uint slot = find_mapping(fs, I915_SEMANTIC_FACE); + debug_printf("Front/back face is broken\n"); + /* XXX Because of limitations in the draw module, currently src will be 0 + * for SEMANTIC_FACE, so this aliases to POS. We need to fix in the draw + * module by adding an extra shader output. + */ + src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_FACE, 0); + draw_emit_vertex_attr(&vinfo, EMIT_1F, INTERP_CONSTANT, src); + vinfo.hwfmt[1] &= ~(TEXCOORDFMT_NOT_PRESENT << (slot * 4)); + vinfo.hwfmt[1] |= TEXCOORDFMT_1D << (slot * 4); + } + draw_compute_vertex_size(&vinfo); if (memcmp(&i915->current.vertex_info, &vinfo, sizeof(vinfo))) { diff --git a/src/gallium/drivers/i915/i915_state_emit.c b/src/gallium/drivers/i915/i915_state_emit.c index 0155cd83510..39fb13aec7e 100644 --- a/src/gallium/drivers/i915/i915_state_emit.c +++ b/src/gallium/drivers/i915/i915_state_emit.c @@ -34,7 +34,9 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" +#include "pipe/p_format.h" +#include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" @@ -128,7 +130,7 @@ validate_immediate(struct i915_context *i915, unsigned *batch_space) static void emit_immediate(struct i915_context *i915) { - /* remove unwatned bits and S7 */ + /* remove unwanted bits and S7 */ unsigned dirty = (1 << I915_IMMEDIATE_S0 | 1 << I915_IMMEDIATE_S1 | 1 << I915_IMMEDIATE_S2 | 1 << I915_IMMEDIATE_S3 | 1 << I915_IMMEDIATE_S3 | 1 << I915_IMMEDIATE_S4 | @@ -341,6 +343,59 @@ emit_constants(struct i915_context *i915) } } +static const struct +{ + enum pipe_format format; + uint hw_shift_R; + uint hw_shift_G; + uint hw_shift_B; + uint hw_shift_A; +} fixup_formats[] = { + { PIPE_FORMAT_R8G8B8A8_UNORM, 20, 24, 28, 16 /* BGRA */}, + { PIPE_FORMAT_L8_UNORM, 28, 28, 28, 16 /* RRRA */}, + { PIPE_FORMAT_I8_UNORM, 28, 28, 28, 16 /* RRRA */}, + { PIPE_FORMAT_A8_UNORM, 16, 16, 16, 16 /* AAAA */}, + { PIPE_FORMAT_NONE, 0, 0, 0, 0}, +}; + +static boolean need_fixup(struct pipe_surface* p) +{ + enum pipe_format f; + + /* if we don't have a surface bound yet, we don't need to fixup the shader */ + if (!p) + return FALSE; + + f = p->format; + for(int i=0; fixup_formats[i].format != PIPE_FORMAT_NONE; i++) + if (fixup_formats[i].format == f) + return TRUE; + + return FALSE; +} + +static uint fixup_swizzle(enum pipe_format f, uint v) +{ + int i; + + for(i=0; fixup_formats[i].format != PIPE_FORMAT_NONE; i++) + if (fixup_formats[i].format == f) + break; + + if (fixup_formats[i].format == PIPE_FORMAT_NONE) + return v; + + uint rgba = v & 0xFFFF0000; + + v &= 0xFFFF; + v |= ((rgba >> fixup_formats[i].hw_shift_R) & 0xF) << 28; + v |= ((rgba >> fixup_formats[i].hw_shift_G) & 0xF) << 24; + v |= ((rgba >> fixup_formats[i].hw_shift_B) & 0xF) << 20; + v |= ((rgba >> fixup_formats[i].hw_shift_A) & 0xF) << 16; + + return v; +} + static void validate_program(struct i915_context *i915, unsigned *batch_space) { @@ -350,12 +405,39 @@ validate_program(struct i915_context *i915, unsigned *batch_space) static void emit_program(struct i915_context *i915) { - uint i; - /* we should always have, at least, a pass-through program */ - assert(i915->fs->program_len > 0); - for (i = 0; i < i915->fs->program_len; i++) { - OUT_BATCH(i915->fs->program[i]); + struct pipe_surface *cbuf_surface = i915->framebuffer.cbufs[0]; + boolean need_format_fixup = need_fixup(cbuf_surface); + int i; + int fixup_offset = -1; + + /* we should always have, at least, a pass-through program */ + assert(i915->fs->program_len > 0); + + if (need_format_fixup) { + /* Find where we emit the output color */ + for (i = i915->fs->program_len - 3; i>0; i-=3) { + uint instr = i915->fs->program[i]; + if ((instr & (REG_NR_MASK << A0_DEST_TYPE_SHIFT)) == + (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) ) { + /* Found it! */ + fixup_offset = i + 1; + break; + } + } + if (fixup_offset == -1) { + need_format_fixup = FALSE; + debug_printf("couldn't find fixup offset\n"); } + } + + /* emit the program to the hw */ + for (i = 0; i < i915->fs->program_len; i++) { + if (need_format_fixup && (i == fixup_offset) ) { + uint v = fixup_swizzle(cbuf_surface->format, i915->fs->program[i]); + OUT_BATCH(v); + } else + OUT_BATCH(i915->fs->program[i]); + } } static void diff --git a/src/gallium/drivers/i915/i915_state_inlines.h b/src/gallium/drivers/i915/i915_state_inlines.h index b589117fbfe..aa992f75c51 100644 --- a/src/gallium/drivers/i915/i915_state_inlines.h +++ b/src/gallium/drivers/i915/i915_state_inlines.h @@ -60,6 +60,31 @@ i915_translate_compare_func(unsigned func) } static INLINE unsigned +i915_translate_shadow_compare_func(unsigned func) +{ + switch (func) { + case PIPE_FUNC_NEVER: + return COMPAREFUNC_ALWAYS; + case PIPE_FUNC_LESS: + return COMPAREFUNC_LEQUAL; + case PIPE_FUNC_LEQUAL: + return COMPAREFUNC_LESS; + case PIPE_FUNC_GREATER: + return COMPAREFUNC_GEQUAL; + case PIPE_FUNC_GEQUAL: + return COMPAREFUNC_GREATER; + case PIPE_FUNC_NOTEQUAL: + return COMPAREFUNC_EQUAL; + case PIPE_FUNC_EQUAL: + return COMPAREFUNC_NOTEQUAL; + case PIPE_FUNC_ALWAYS: + return COMPAREFUNC_NEVER; + default: + return COMPAREFUNC_NEVER; + } +} + +static INLINE unsigned i915_translate_stencil_op(unsigned op) { switch (op) { diff --git a/src/gallium/drivers/i915/i915_state_sampler.c b/src/gallium/drivers/i915/i915_state_sampler.c index be70e7a92c9..0103f7c3530 100644 --- a/src/gallium/drivers/i915/i915_state_sampler.c +++ b/src/gallium/drivers/i915/i915_state_sampler.c @@ -62,6 +62,7 @@ static void update_map(struct i915_context *i915, uint unit, const struct i915_texture *tex, const struct i915_sampler_state *sampler, + const struct pipe_sampler_view* view, uint state[2]); @@ -161,9 +162,10 @@ static void update_samplers(struct i915_context *i915) i915->current.sampler[unit]); /* the result */ update_map(i915, unit, - texture, /* texture */ - i915->sampler[unit], /* sampler state */ - i915->current.texbuffer[unit]); /* the result */ + texture, /* texture */ + i915->sampler[unit], /* sampler state */ + i915->fragment_sampler_views[unit], /* sampler view */ + i915->current.texbuffer[unit]); /* the result */ i915->current.sampler_enable_nr++; i915->current.sampler_enable_flags |= (1 << unit); @@ -180,13 +182,21 @@ struct i915_tracked_state i915_hw_samplers = { }; - /*********************************************************************** * Sampler views */ -static uint translate_texture_format(enum pipe_format pipeFormat) +static uint translate_texture_format(enum pipe_format pipeFormat, + const struct pipe_sampler_view* view) { + if ( (view->swizzle_r != PIPE_SWIZZLE_RED || + view->swizzle_g != PIPE_SWIZZLE_GREEN || + view->swizzle_b != PIPE_SWIZZLE_BLUE || + view->swizzle_a != PIPE_SWIZZLE_ALPHA ) && + pipeFormat != PIPE_FORMAT_Z24_UNORM_S8_USCALED && + pipeFormat != PIPE_FORMAT_Z24X8_UNORM ) + debug_printf("i915: unsupported texture swizzle for format %d\n", pipeFormat); + switch (pipeFormat) { case PIPE_FORMAT_L8_UNORM: return MAPSURF_8BIT | MT_8BIT_L8; @@ -202,16 +212,16 @@ static uint translate_texture_format(enum pipe_format pipeFormat) return MAPSURF_16BIT | MT_16BIT_ARGB1555; case PIPE_FORMAT_B4G4R4A4_UNORM: return MAPSURF_16BIT | MT_16BIT_ARGB4444; + case PIPE_FORMAT_B10G10R10A2_UNORM: + return MAPSURF_32BIT | MT_32BIT_ARGB2101010; case PIPE_FORMAT_B8G8R8A8_UNORM: return MAPSURF_32BIT | MT_32BIT_ARGB8888; case PIPE_FORMAT_B8G8R8X8_UNORM: return MAPSURF_32BIT | MT_32BIT_XRGB8888; case PIPE_FORMAT_R8G8B8A8_UNORM: return MAPSURF_32BIT | MT_32BIT_ABGR8888; -#if 0 case PIPE_FORMAT_R8G8B8X8_UNORM: return MAPSURF_32BIT | MT_32BIT_XBGR8888; -#endif case PIPE_FORMAT_YUYV: return (MAPSURF_422 | MT_422_YCRCB_NORMAL); case PIPE_FORMAT_UYVY: @@ -232,7 +242,25 @@ static uint translate_texture_format(enum pipe_format pipeFormat) return (MAPSURF_COMPRESSED | MT_COMPRESS_DXT4_5); case PIPE_FORMAT_Z24_UNORM_S8_USCALED: case PIPE_FORMAT_Z24X8_UNORM: - return (MAPSURF_32BIT | MT_32BIT_xI824); + { + if ( view->swizzle_r == PIPE_SWIZZLE_RED && + view->swizzle_g == PIPE_SWIZZLE_RED && + view->swizzle_b == PIPE_SWIZZLE_RED && + view->swizzle_a == PIPE_SWIZZLE_ONE) + return (MAPSURF_32BIT | MT_32BIT_xA824); + if ( view->swizzle_r == PIPE_SWIZZLE_RED && + view->swizzle_g == PIPE_SWIZZLE_RED && + view->swizzle_b == PIPE_SWIZZLE_RED && + view->swizzle_a == PIPE_SWIZZLE_RED) + return (MAPSURF_32BIT | MT_32BIT_xI824); + if ( view->swizzle_r == PIPE_SWIZZLE_ZERO && + view->swizzle_g == PIPE_SWIZZLE_ZERO && + view->swizzle_b == PIPE_SWIZZLE_ZERO && + view->swizzle_a == PIPE_SWIZZLE_RED) + return (MAPSURF_32BIT | MT_32BIT_xL824); + debug_printf("i915: unsupported depth swizzle\n"); + return (MAPSURF_32BIT | MT_32BIT_xL824); + } default: debug_printf("i915: translate_texture_format() bad image format %x\n", pipeFormat); @@ -262,6 +290,7 @@ static void update_map(struct i915_context *i915, uint unit, const struct i915_texture *tex, const struct i915_sampler_state *sampler, + const struct pipe_sampler_view* view, uint state[2]) { const struct pipe_resource *pt = &tex->b.b; @@ -275,7 +304,7 @@ static void update_map(struct i915_context *i915, assert(height); assert(depth); - format = translate_texture_format(pt->format); + format = translate_texture_format(pt->format, view); pitch = tex->stride; assert(format); @@ -318,8 +347,9 @@ static void update_maps(struct i915_context *i915) update_map(i915, unit, - texture, /* texture */ - i915->sampler[unit], /* sampler state */ + texture, /* texture */ + i915->sampler[unit], /* sampler state */ + i915->fragment_sampler_views[unit], /* sampler view */ i915->current.texbuffer[unit]); } } diff --git a/src/gallium/drivers/i915/i915_state_static.c b/src/gallium/drivers/i915/i915_state_static.c index 2865298318c..0e4000bc2ab 100644 --- a/src/gallium/drivers/i915/i915_state_static.c +++ b/src/gallium/drivers/i915/i915_state_static.c @@ -42,6 +42,18 @@ static unsigned translate_format(enum pipe_format format) return COLOR_BUF_ARGB8888; case PIPE_FORMAT_B5G6R5_UNORM: return COLOR_BUF_RGB565; + case PIPE_FORMAT_B5G5R5A1_UNORM: + return COLOR_BUF_ARGB1555; + case PIPE_FORMAT_R8G8B8A8_UNORM: + return COLOR_BUF_ARGB8888; + case PIPE_FORMAT_B4G4R4A4_UNORM: + return COLOR_BUF_ARGB4444; + case PIPE_FORMAT_B10G10R10A2_UNORM: + return COLOR_BUF_ARGB2101010; + case PIPE_FORMAT_L8_UNORM: + case PIPE_FORMAT_A8_UNORM: + case PIPE_FORMAT_I8_UNORM: + return COLOR_BUF_8BIT; default: assert(0); return 0; @@ -137,7 +149,8 @@ static void update_framebuffer(struct i915_context *i915) i915->static_dirty |= I915_DST_RECT; } - i915->hardware_dirty |= I915_HW_STATIC; + /* we also send a new program to make sure the fixup for RGBA surfaces happens */ + i915->hardware_dirty |= I915_HW_STATIC | I915_HW_PROGRAM; /* flush the cache in case we sample from the old renderbuffers */ i915_set_flush_dirty(i915, I915_FLUSH_CACHE); |