diff options
author | Christian König <[email protected]> | 2010-12-22 21:12:24 +0100 |
---|---|---|
committer | Christian König <[email protected]> | 2010-12-22 21:12:24 +0100 |
commit | e179a8bf34022c200deee92d328cb1bae3c3aa4a (patch) | |
tree | 4c67616380e7c0efa2d7ff0fe67fd18af2fa11ad /src/mesa | |
parent | 1b03996b1269fb8b2f89e0a013d8427da660ff83 (diff) | |
parent | 38c8b034e2775640c588711290c244632dcc2475 (diff) |
Merge remote branch 'origin/master' into pipe-video
Diffstat (limited to 'src/mesa')
66 files changed, 1702 insertions, 1119 deletions
diff --git a/src/mesa/drivers/dri/common/spantmp2.h b/src/mesa/drivers/dri/common/spantmp2.h index abd79562f98..f436d1398c2 100644 --- a/src/mesa/drivers/dri/common/spantmp2.h +++ b/src/mesa/drivers/dri/common/spantmp2.h @@ -48,6 +48,15 @@ #define HW_WRITE_CLIPLOOP() HW_CLIPLOOP() #endif +#ifdef SPANTMP_MESA_FMT +#define SPANTMP_PIXEL_FMT GL_NONE +#define SPANTMP_PIXEL_TYPE GL_NONE +#endif + +#ifndef SPANTMP_MESA_FMT +#define SPANTMP_MESA_FMT MESA_FORMAT_COUNT +#endif + #if (SPANTMP_PIXEL_FMT == GL_RGB) && (SPANTMP_PIXEL_TYPE == GL_UNSIGNED_SHORT_5_6_5) /** @@ -445,6 +454,118 @@ rgba[3] = p; \ } while (0) +#elif (SPANTMP_MESA_FMT == MESA_FORMAT_R8) + +#ifndef GET_VALUE +#ifndef GET_PTR +#define GET_PTR(_x, _y) ( buf + (_x) + (_y) * pitch) +#endif + +#define GET_VALUE(_x, _y) *(volatile GLubyte *)(GET_PTR(_x, _y)) +#define PUT_VALUE(_x, _y, _v) *(volatile GLubyte *)(GET_PTR(_x, _y)) = (_v) +#endif /* GET_VALUE */ + +# define INIT_MONO_PIXEL(p, color) \ + p = color[0] + +# define WRITE_RGBA(_x, _y, r, g, b, a) \ + PUT_VALUE(_x, _y, r) + +#define WRITE_PIXEL(_x, _y, p) PUT_VALUE(_x, _y, p) + +#define READ_RGBA( rgba, _x, _y ) \ + do { \ + GLubyte p = GET_VALUE(_x, _y); \ + rgba[0] = p; \ + rgba[1] = 0; \ + rgba[2] = 0; \ + rgba[3] = 0; \ + } while (0) + +#elif (SPANTMP_MESA_FMT == MESA_FORMAT_RG88) + +#ifndef GET_VALUE +#ifndef GET_PTR +#define GET_PTR(_x, _y) ( buf + (_x) * 2 + (_y) * pitch) +#endif + +#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y)) +#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v) +#endif /* GET_VALUE */ + +# define INIT_MONO_PIXEL(p, color) \ + PACK_COLOR_8888(color[0], color[1], 0, 0) + +# define WRITE_RGBA(_x, _y, r, g, b, a) \ + PUT_VALUE(_x, _y, r) + +#define WRITE_PIXEL(_x, _y, p) PUT_VALUE(_x, _y, p) + +#define READ_RGBA( rgba, _x, _y ) \ + do { \ + GLushort p = GET_VALUE(_x, _y); \ + rgba[0] = p & 0xff; \ + rgba[1] = (p >> 8) & 0xff; \ + rgba[2] = 0; \ + rgba[3] = 0; \ + } while (0) + +#elif (SPANTMP_MESA_FMT == MESA_FORMAT_R16) + +#ifndef GET_VALUE +#ifndef GET_PTR +#define GET_PTR(_x, _y) ( buf + (_x) * 2 + (_y) * pitch) +#endif + +#define GET_VALUE(_x, _y) *(volatile GLushort *)(GET_PTR(_x, _y)) +#define PUT_VALUE(_x, _y, _v) *(volatile GLushort *)(GET_PTR(_x, _y)) = (_v) +#endif /* GET_VALUE */ + +# define INIT_MONO_PIXEL(p, color) \ + p = color[0] + +# define WRITE_RGBA(_x, _y, r, g, b, a) \ + PUT_VALUE(_x, _y, r) + +#define WRITE_PIXEL(_x, _y, p) PUT_VALUE(_x, _y, p) + +#define READ_RGBA( rgba, _x, _y ) \ + do { \ + GLushort p = GET_VALUE(_x, _y); \ + rgba[0] = p; \ + rgba[1] = 0; \ + rgba[2] = 0; \ + rgba[3] = 0; \ + } while (0) + +#elif (SPANTMP_MESA_FMT == MESA_FORMAT_RG1616) + +#ifndef GET_VALUE +#ifndef GET_PTR +#define GET_PTR(_x, _y) ( buf + (_x) * 4 + (_y) * pitch) +#endif + +#define GET_VALUE(_x, _y) *(volatile GLuint *)(GET_PTR(_x, _y)) +#define PUT_VALUE(_x, _y, _v) *(volatile GLuint *)(GET_PTR(_x, _y)) = (_v) +#endif /* GET_VALUE */ + +# define INIT_MONO_PIXEL(p, color) \ + ((color[1] << 16) | (color[0])) + +# define WRITE_RGBA(_x, _y, r, g, b, a) \ + PUT_VALUE(_x, _y, r) + +#define WRITE_PIXEL(_x, _y, p) PUT_VALUE(_x, _y, p) + +#define READ_RGBA( rgba, _x, _y ) \ + do { \ + GLuint p = GET_VALUE(_x, _y); \ + rgba[0] = p & 0xffff; \ + rgba[1] = (p >> 16) & 0xffff; \ + rgba[2] = 0; \ + rgba[3] = 0; \ + } while (0) + #else #error SPANTMP_PIXEL_FMT must be set to a valid value! #endif @@ -914,3 +1035,4 @@ static void TAG(InitPointers)(struct gl_renderbuffer *rb) #undef GET_PTR #undef SPANTMP_PIXEL_FMT #undef SPANTMP_PIXEL_TYPE +#undef SPANTMP_MESA_FMT diff --git a/src/mesa/drivers/dri/i915/i830_vtbl.c b/src/mesa/drivers/dri/i915/i830_vtbl.c index f7fdb78d059..1621c9544ac 100644 --- a/src/mesa/drivers/dri/i915/i830_vtbl.c +++ b/src/mesa/drivers/dri/i915/i830_vtbl.c @@ -364,7 +364,7 @@ i830_emit_invarient_state(struct intel_context *intel) #define emit( intel, state, size ) \ - intel_batchbuffer_data(intel->batch, state, size ) + intel_batchbuffer_data(intel->batch, state, size, false) static GLuint get_dirty(struct i830_hw_state *state) @@ -429,7 +429,8 @@ i830_emit_state(struct intel_context *intel) * batchbuffer fills up. */ intel_batchbuffer_require_space(intel->batch, - get_state_size(state) + INTEL_PRIM_EMIT_SIZE); + get_state_size(state) + INTEL_PRIM_EMIT_SIZE, + false); count = 0; again: aper_count = 0; diff --git a/src/mesa/drivers/dri/i915/i915_fragprog.c b/src/mesa/drivers/dri/i915/i915_fragprog.c index 7a9fb7f088b..1c6e9845172 100644 --- a/src/mesa/drivers/dri/i915/i915_fragprog.c +++ b/src/mesa/drivers/dri/i915/i915_fragprog.c @@ -1162,11 +1162,6 @@ translate_program(struct i915_fragment_program *p) fixup_depth_write(p); i915_fini_program(p); - if (INTEL_DEBUG & DEBUG_WM) { - printf("i915:\n"); - i915_disassemble_program(i915->state.Program, i915->state.ProgramSize); - } - p->translated = 1; } @@ -1427,6 +1422,11 @@ i915ValidateFragmentProgram(struct i915_context *i915) if (!p->on_hardware) i915_upload_program(i915, p); + + if (INTEL_DEBUG & DEBUG_WM) { + printf("i915:\n"); + i915_disassemble_program(i915->state.Program, i915->state.ProgramSize); + } } void diff --git a/src/mesa/drivers/dri/i915/i915_vtbl.c b/src/mesa/drivers/dri/i915/i915_vtbl.c index 59dfe085632..8d9020f5ef3 100644 --- a/src/mesa/drivers/dri/i915/i915_vtbl.c +++ b/src/mesa/drivers/dri/i915/i915_vtbl.c @@ -217,7 +217,7 @@ i915_emit_invarient_state(struct intel_context *intel) #define emit(intel, state, size ) \ - intel_batchbuffer_data(intel->batch, state, size) + intel_batchbuffer_data(intel->batch, state, size, false) static GLuint get_dirty(struct i915_hw_state *state) @@ -300,7 +300,8 @@ i915_emit_state(struct intel_context *intel) * batchbuffer fills up. */ intel_batchbuffer_require_space(intel->batch, - get_state_size(state) + INTEL_PRIM_EMIT_SIZE); + get_state_size(state) + INTEL_PRIM_EMIT_SIZE, + false); count = 0; again: aper_count = 0; diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h index 7f3e4986808..b48a30d6be9 100644 --- a/src/mesa/drivers/dri/i965/brw_defines.h +++ b/src/mesa/drivers/dri/i965/brw_defines.h @@ -906,6 +906,8 @@ # define GEN6_VS_VECTOR_MASK_ENABLE (1 << 30) # define GEN6_VS_SAMPLER_COUNT_SHIFT 27 # define GEN6_VS_BINDING_TABLE_ENTRY_COUNT_SHIFT 18 +# define GEN6_VS_FLOATING_POINT_MODE_IEEE_754 (0 << 16) +# define GEN6_VS_FLOATING_POINT_MODE_ALT (1 << 16) /* DW4 */ # define GEN6_VS_DISPATCH_START_GRF_SHIFT 20 # define GEN6_VS_URB_READ_LENGTH_SHIFT 11 @@ -1048,6 +1050,8 @@ # define GEN6_WM_VECTOR_MASK_ENABLE (1 << 30) # define GEN6_WM_SAMPLER_COUNT_SHIFT 27 # define GEN6_WM_BINDING_TABLE_ENTRY_COUNT_SHIFT 18 +# define GEN6_WM_FLOATING_POINT_MODE_IEEE_754 (0 << 16) +# define GEN6_WM_FLOATING_POINT_MODE_ALT (1 << 16) /* DW3: scratch space */ /* DW4 */ # define GEN6_WM_STATISTICS_ENABLE (1 << 31) diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c index a1f403ca4e6..7eb16b71f4a 100644 --- a/src/mesa/drivers/dri/i965/brw_draw.c +++ b/src/mesa/drivers/dri/i965/brw_draw.c @@ -159,7 +159,7 @@ static void brw_emit_prim(struct brw_context *brw, } if (prim_packet.verts_per_instance) { intel_batchbuffer_data( brw->intel.batch, &prim_packet, - sizeof(prim_packet)); + sizeof(prim_packet), false); } if (intel->always_flush_cache) { intel_batchbuffer_emit_mi_flush(intel->batch); @@ -351,7 +351,8 @@ static GLboolean brw_try_draw_prims( struct gl_context *ctx, * an upper bound of how much we might emit in a single * brw_try_draw_prims(). */ - intel_batchbuffer_require_space(intel->batch, intel->batch->size / 4); + intel_batchbuffer_require_space(intel->batch, intel->batch->size / 4, + false); hw_prim = brw_set_prim(brw, &prim[i]); diff --git a/src/mesa/drivers/dri/i965/brw_eu.h b/src/mesa/drivers/dri/i965/brw_eu.h index 4dbdc522100..119ffc72370 100644 --- a/src/mesa/drivers/dri/i965/brw_eu.h +++ b/src/mesa/drivers/dri/i965/brw_eu.h @@ -861,7 +861,8 @@ void brw_fb_WRITE(struct brw_compile *p, GLuint binding_table_index, GLuint msg_length, GLuint response_length, - GLboolean eot); + GLboolean eot, + GLboolean header_present); void brw_SAMPLE(struct brw_compile *p, struct brw_reg dest, diff --git a/src/mesa/drivers/dri/i965/brw_eu_emit.c b/src/mesa/drivers/dri/i965/brw_eu_emit.c index 9c764fe779d..6d48ca0e46d 100644 --- a/src/mesa/drivers/dri/i965/brw_eu_emit.c +++ b/src/mesa/drivers/dri/i965/brw_eu_emit.c @@ -1812,12 +1812,12 @@ void brw_fb_WRITE(struct brw_compile *p, GLuint binding_table_index, GLuint msg_length, GLuint response_length, - GLboolean eot) + GLboolean eot, + GLboolean header_present) { struct intel_context *intel = &p->brw->intel; struct brw_instruction *insn; GLuint msg_control, msg_type; - GLboolean header_present = GL_TRUE; if (intel->gen >= 6 && binding_table_index == 0) { insn = next_insn(p, BRW_OPCODE_SENDC); @@ -1829,9 +1829,6 @@ void brw_fb_WRITE(struct brw_compile *p, insn->header.compression_control = BRW_COMPRESSION_NONE; if (intel->gen >= 6) { - if (msg_length == 4) - header_present = GL_FALSE; - /* headerless version, just submit color payload */ src0 = brw_message_reg(msg_reg_nr); @@ -1936,7 +1933,8 @@ void brw_SAMPLE(struct brw_compile *p, brw_set_compression_control(p, BRW_COMPRESSION_NONE); brw_set_mask_control(p, BRW_MASK_DISABLE); - brw_MOV(p, m1, brw_vec8_grf(0,0)); + brw_MOV(p, retype(m1, BRW_REGISTER_TYPE_UD), + retype(brw_vec8_grf(0,0), BRW_REGISTER_TYPE_UD)); brw_MOV(p, get_element_ud(m1, 2), brw_imm_ud(newmask << 12)); brw_pop_insn_state(p); @@ -1997,7 +1995,8 @@ void brw_SAMPLE(struct brw_compile *p, */ brw_push_insn_state(p); brw_set_compression_control(p, BRW_COMPRESSION_NONE); - brw_MOV(p, reg, reg); + brw_MOV(p, retype(reg, BRW_REGISTER_TYPE_UD), + retype(reg, BRW_REGISTER_TYPE_UD)); brw_pop_insn_state(p); } @@ -2029,7 +2028,8 @@ void brw_urb_WRITE(struct brw_compile *p, if (intel->gen >= 6) { brw_push_insn_state(p); brw_set_mask_control( p, BRW_MASK_DISABLE ); - brw_MOV(p, brw_message_reg(msg_reg_nr), src0); + brw_MOV(p, retype(brw_message_reg(msg_reg_nr), BRW_REGISTER_TYPE_UD), + retype(src0, BRW_REGISTER_TYPE_UD)); brw_pop_insn_state(p); src0 = brw_message_reg(msg_reg_nr); } diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index c3cbe0df618..2de81b28371 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -474,8 +474,13 @@ fs_visitor::emit_fragcoord_interpolation(ir_variable *ir) wpos.reg_offset++; /* gl_FragCoord.z */ - emit(fs_inst(FS_OPCODE_LINTERP, wpos, this->delta_x, this->delta_y, - interp_reg(FRAG_ATTRIB_WPOS, 2))); + if (intel->gen >= 6) { + emit(fs_inst(BRW_OPCODE_MOV, wpos, + fs_reg(brw_vec8_grf(c->source_depth_reg, 0)))); + } else { + emit(fs_inst(FS_OPCODE_LINTERP, wpos, this->delta_x, this->delta_y, + interp_reg(FRAG_ATTRIB_WPOS, 2))); + } wpos.reg_offset++; /* gl_FragCoord.w: Already set up in emit_interpolation */ @@ -2158,7 +2163,8 @@ fs_visitor::generate_fb_write(fs_inst *inst) inst->target, inst->mlen, 0, - eot); + eot, + inst->header_present); } void diff --git a/src/mesa/drivers/dri/i965/brw_state.h b/src/mesa/drivers/dri/i965/brw_state.h index 3beed16945b..4bb93e73369 100644 --- a/src/mesa/drivers/dri/i965/brw_state.h +++ b/src/mesa/drivers/dri/i965/brw_state.h @@ -164,7 +164,8 @@ void brw_destroy_caches( struct brw_context *brw ); /*********************************************************************** * brw_state_batch.c */ -#define BRW_BATCH_STRUCT(brw, s) intel_batchbuffer_data( brw->intel.batch, (s), sizeof(*(s))) +#define BRW_BATCH_STRUCT(brw, s) intel_batchbuffer_data(brw->intel.batch, (s), \ + sizeof(*(s)), false) #define BRW_CACHED_BATCH_STRUCT(brw, s) brw_cached_batch_struct( brw, (s), sizeof(*(s)) ) GLboolean brw_cached_batch_struct( struct brw_context *brw, diff --git a/src/mesa/drivers/dri/i965/brw_state_batch.c b/src/mesa/drivers/dri/i965/brw_state_batch.c index be3989eb7db..a21af13caa3 100644 --- a/src/mesa/drivers/dri/i965/brw_state_batch.c +++ b/src/mesa/drivers/dri/i965/brw_state_batch.c @@ -48,7 +48,7 @@ GLboolean brw_cached_batch_struct( struct brw_context *brw, struct header *newheader = (struct header *)data; if (brw->emit_state_always) { - intel_batchbuffer_data(brw->intel.batch, data, sz); + intel_batchbuffer_data(brw->intel.batch, data, sz, false); return GL_TRUE; } @@ -75,7 +75,7 @@ GLboolean brw_cached_batch_struct( struct brw_context *brw, emit: memcpy(item->header, newheader, sz); - intel_batchbuffer_data(brw->intel.batch, data, sz); + intel_batchbuffer_data(brw->intel.batch, data, sz, false); return GL_TRUE; } diff --git a/src/mesa/drivers/dri/i965/brw_vs_emit.c b/src/mesa/drivers/dri/i965/brw_vs_emit.c index 09887dae95d..326bb1e562f 100644 --- a/src/mesa/drivers/dri/i965/brw_vs_emit.c +++ b/src/mesa/drivers/dri/i965/brw_vs_emit.c @@ -658,6 +658,22 @@ static void emit_min( struct brw_compile *p, } } +static void emit_arl(struct brw_compile *p, + struct brw_reg dst, + struct brw_reg src) +{ + struct intel_context *intel = &p->brw->intel; + + if (intel->gen >= 6) { + struct brw_reg dst_f = retype(dst, BRW_REGISTER_TYPE_F); + + brw_RNDD(p, dst_f, src); + brw_MOV(p, dst, dst_f); + } else { + brw_RNDD(p, dst, src); + } +} + static void emit_math1_gen4(struct brw_vs_compile *c, GLuint function, struct brw_reg dst, @@ -1963,7 +1979,7 @@ void brw_vs_emit(struct brw_vs_compile *c ) emit_math1(c, BRW_MATH_FUNCTION_EXP, dst, args[0], BRW_MATH_PRECISION_FULL); break; case OPCODE_ARL: - brw_RNDD(p, dst, args[0]); + emit_arl(p, dst, args[0]); break; case OPCODE_FLR: brw_RNDD(p, dst, args[0]); diff --git a/src/mesa/drivers/dri/i965/brw_wm_emit.c b/src/mesa/drivers/dri/i965/brw_wm_emit.c index a0e86034e1e..56725c0d471 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_emit.c +++ b/src/mesa/drivers/dri/i965/brw_wm_emit.c @@ -219,43 +219,45 @@ void emit_wpos_xy(struct brw_wm_compile *c, const struct brw_reg *arg0) { struct brw_compile *p = &c->func; + struct intel_context *intel = &p->brw->intel; + struct brw_reg delta_x = retype(arg0[0], BRW_REGISTER_TYPE_W); + struct brw_reg delta_y = retype(arg0[1], BRW_REGISTER_TYPE_W); if (mask & WRITEMASK_X) { + if (intel->gen >= 6) { + struct brw_reg delta_x_f = retype(delta_x, BRW_REGISTER_TYPE_F); + brw_MOV(p, delta_x_f, delta_x); + delta_x = delta_x_f; + } + if (c->fp->program.PixelCenterInteger) { /* X' = X */ - brw_MOV(p, - dst[0], - retype(arg0[0], BRW_REGISTER_TYPE_W)); + brw_MOV(p, dst[0], delta_x); } else { /* X' = X + 0.5 */ - brw_ADD(p, - dst[0], - retype(arg0[0], BRW_REGISTER_TYPE_W), - brw_imm_f(0.5)); + brw_ADD(p, dst[0], delta_x, brw_imm_f(0.5)); } } if (mask & WRITEMASK_Y) { + if (intel->gen >= 6) { + struct brw_reg delta_y_f = retype(delta_y, BRW_REGISTER_TYPE_F); + brw_MOV(p, delta_y_f, delta_y); + delta_y = delta_y_f; + } + if (c->fp->program.OriginUpperLeft) { if (c->fp->program.PixelCenterInteger) { /* Y' = Y */ - brw_MOV(p, - dst[1], - retype(arg0[1], BRW_REGISTER_TYPE_W)); + brw_MOV(p, dst[1], delta_y); } else { - /* Y' = Y + 0.5 */ - brw_ADD(p, - dst[1], - retype(arg0[1], BRW_REGISTER_TYPE_W), - brw_imm_f(0.5)); + brw_ADD(p, dst[1], delta_y, brw_imm_f(0.5)); } } else { float center_offset = c->fp->program.PixelCenterInteger ? 0.0 : 0.5; /* Y' = (height - 1) - Y + center */ - brw_ADD(p, - dst[1], - negate(retype(arg0[1], BRW_REGISTER_TYPE_W)), + brw_ADD(p, dst[1], negate(delta_y), brw_imm_f(c->key.drawable_height - 1 + center_offset)); } } @@ -971,34 +973,23 @@ void emit_math2(struct brw_wm_compile *c, struct brw_reg temp_dst = dst[dst_chan]; if (arg0[0].hstride == BRW_HORIZONTAL_STRIDE_0) { - if (arg1[0].hstride == BRW_HORIZONTAL_STRIDE_0) { - /* Both scalar arguments. Do scalar calc. */ - src0.hstride = BRW_HORIZONTAL_STRIDE_1; - src1.hstride = BRW_HORIZONTAL_STRIDE_1; - temp_dst.hstride = BRW_HORIZONTAL_STRIDE_1; - temp_dst.width = BRW_WIDTH_1; - - if (arg0[0].subnr != 0) { - brw_MOV(p, temp_dst, src0); - src0 = temp_dst; - - /* Ouch. We've used the temp as a dst, and we still - * need a temp to store arg1 in, because src and dst - * offsets have to be equal. Leaving this up to - * glsl2-965 to handle correctly. - */ - assert(arg1[0].subnr == 0); - } else if (arg1[0].subnr != 0) { - brw_MOV(p, temp_dst, src1); - src1 = temp_dst; - } - } else { - brw_MOV(p, temp_dst, src0); - src0 = temp_dst; - } - } else if (arg1[0].hstride == BRW_HORIZONTAL_STRIDE_0) { - brw_MOV(p, temp_dst, src1); - src1 = temp_dst; + brw_MOV(p, temp_dst, src0); + src0 = temp_dst; + } + + if (arg1[0].hstride == BRW_HORIZONTAL_STRIDE_0) { + /* This is a heinous hack to get a temporary register for use + * in case both arg0 and arg1 are constants. Why you're + * doing exponentiation on constant values in the shader, we + * don't know. + * + * max_wm_grf is almost surely less than the maximum GRF, and + * gen6 doesn't care about the number of GRFs used in a + * shader like pre-gen6 did. + */ + struct brw_reg temp = brw_vec8_grf(c->max_wm_grf, 0); + brw_MOV(p, temp, src1); + src1 = temp; } brw_set_saturate(p, (mask & SATURATE) ? 1 : 0); @@ -1016,14 +1007,6 @@ void emit_math2(struct brw_wm_compile *c, sechalf(src0), sechalf(src1)); } - - /* Splat a scalar result into all the channels. */ - if (arg0[0].hstride == BRW_HORIZONTAL_STRIDE_0 && - arg1[0].hstride == BRW_HORIZONTAL_STRIDE_0) { - temp_dst.hstride = BRW_HORIZONTAL_STRIDE_0; - temp_dst.vstride = BRW_VERTICAL_STRIDE_0; - brw_MOV(p, dst[dst_chan], temp_dst); - } } else { GLuint saturate = ((mask & SATURATE) ? BRW_MATH_SATURATE_SATURATE : @@ -1373,7 +1356,8 @@ static void fire_fb_write( struct brw_wm_compile *c, target, nr, 0, - eot); + eot, + GL_TRUE); } @@ -1518,7 +1502,8 @@ void emit_fb_write(struct brw_wm_compile *c, */ brw_push_insn_state(p); brw_set_mask_control(p, BRW_MASK_DISABLE); - brw_MOV(p, brw_message_reg(0), brw_vec8_grf(0, 0)); + brw_MOV(p, retype(brw_message_reg(0), BRW_REGISTER_TYPE_UD), + retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UD)); brw_pop_insn_state(p); if (target != 0) { diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c index ad744044c70..1cd736a1119 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c @@ -68,71 +68,43 @@ static GLuint translate_tex_target( GLenum target ) } } +static uint32_t brw_format_for_mesa_format[MESA_FORMAT_COUNT] = +{ + [MESA_FORMAT_L8] = BRW_SURFACEFORMAT_L8_UNORM, + [MESA_FORMAT_I8] = BRW_SURFACEFORMAT_I8_UNORM, + [MESA_FORMAT_A8] = BRW_SURFACEFORMAT_A8_UNORM, + [MESA_FORMAT_AL88] = BRW_SURFACEFORMAT_L8A8_UNORM, + [MESA_FORMAT_AL1616] = BRW_SURFACEFORMAT_L16A16_UNORM, + [MESA_FORMAT_R8] = BRW_SURFACEFORMAT_R8_UNORM, + [MESA_FORMAT_R16] = BRW_SURFACEFORMAT_R16_UNORM, + [MESA_FORMAT_RG88] = BRW_SURFACEFORMAT_R8G8_UNORM, + [MESA_FORMAT_RG1616] = BRW_SURFACEFORMAT_R16G16_UNORM, + [MESA_FORMAT_ARGB8888] = BRW_SURFACEFORMAT_B8G8R8A8_UNORM, + [MESA_FORMAT_XRGB8888] = BRW_SURFACEFORMAT_B8G8R8X8_UNORM, + [MESA_FORMAT_RGB565] = BRW_SURFACEFORMAT_B5G6R5_UNORM, + [MESA_FORMAT_ARGB1555] = BRW_SURFACEFORMAT_B5G5R5A1_UNORM, + [MESA_FORMAT_ARGB4444] = BRW_SURFACEFORMAT_B4G4R4A4_UNORM, + [MESA_FORMAT_YCBCR_REV] = BRW_SURFACEFORMAT_YCRCB_NORMAL, + [MESA_FORMAT_YCBCR] = BRW_SURFACEFORMAT_YCRCB_SWAPUVY, + [MESA_FORMAT_RGB_FXT1] = BRW_SURFACEFORMAT_FXT1, + [MESA_FORMAT_RGBA_FXT1] = BRW_SURFACEFORMAT_FXT1, + [MESA_FORMAT_RGB_DXT1] = BRW_SURFACEFORMAT_DXT1_RGB, + [MESA_FORMAT_RGBA_DXT1] = BRW_SURFACEFORMAT_BC1_UNORM, + [MESA_FORMAT_RGBA_DXT3] = BRW_SURFACEFORMAT_BC2_UNORM, + [MESA_FORMAT_RGBA_DXT5] = BRW_SURFACEFORMAT_BC3_UNORM, + [MESA_FORMAT_SRGB_DXT1] = BRW_SURFACEFORMAT_BC1_UNORM_SRGB, + [MESA_FORMAT_SARGB8] = BRW_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB, + [MESA_FORMAT_SLA8] = BRW_SURFACEFORMAT_L8A8_UNORM_SRGB, + [MESA_FORMAT_SL8] = BRW_SURFACEFORMAT_L8_UNORM_SRGB, + [MESA_FORMAT_DUDV8] = BRW_SURFACEFORMAT_R8G8_SNORM, + [MESA_FORMAT_SIGNED_RGBA8888_REV] = BRW_SURFACEFORMAT_R8G8B8A8_SNORM, +}; static GLuint translate_tex_format( gl_format mesa_format, GLenum internal_format, GLenum depth_mode ) { switch( mesa_format ) { - case MESA_FORMAT_L8: - return BRW_SURFACEFORMAT_L8_UNORM; - - case MESA_FORMAT_I8: - return BRW_SURFACEFORMAT_I8_UNORM; - - case MESA_FORMAT_A8: - return BRW_SURFACEFORMAT_A8_UNORM; - - case MESA_FORMAT_AL88: - return BRW_SURFACEFORMAT_L8A8_UNORM; - - case MESA_FORMAT_AL1616: - return BRW_SURFACEFORMAT_L16A16_UNORM; - - case MESA_FORMAT_R8: - return BRW_SURFACEFORMAT_R8_UNORM; - - case MESA_FORMAT_R16: - return BRW_SURFACEFORMAT_R16_UNORM; - - case MESA_FORMAT_RG88: - return BRW_SURFACEFORMAT_R8G8_UNORM; - - case MESA_FORMAT_RG1616: - return BRW_SURFACEFORMAT_R16G16_UNORM; - - case MESA_FORMAT_RGB888: - assert(0); /* not supported for sampling */ - return BRW_SURFACEFORMAT_R8G8B8_UNORM; - - case MESA_FORMAT_ARGB8888: - return BRW_SURFACEFORMAT_B8G8R8A8_UNORM; - - case MESA_FORMAT_XRGB8888: - return BRW_SURFACEFORMAT_B8G8R8X8_UNORM; - - case MESA_FORMAT_RGBA8888_REV: - _mesa_problem(NULL, "unexpected format in i965:translate_tex_format()"); - return BRW_SURFACEFORMAT_R8G8B8A8_UNORM; - - case MESA_FORMAT_RGB565: - return BRW_SURFACEFORMAT_B5G6R5_UNORM; - - case MESA_FORMAT_ARGB1555: - return BRW_SURFACEFORMAT_B5G5R5A1_UNORM; - - case MESA_FORMAT_ARGB4444: - return BRW_SURFACEFORMAT_B4G4R4A4_UNORM; - - case MESA_FORMAT_YCBCR_REV: - return BRW_SURFACEFORMAT_YCRCB_NORMAL; - - case MESA_FORMAT_YCBCR: - return BRW_SURFACEFORMAT_YCRCB_SWAPUVY; - - case MESA_FORMAT_RGB_FXT1: - case MESA_FORMAT_RGBA_FXT1: - return BRW_SURFACEFORMAT_FXT1; case MESA_FORMAT_Z16: if (depth_mode == GL_INTENSITY) @@ -144,30 +116,6 @@ static GLuint translate_tex_format( gl_format mesa_format, else return BRW_SURFACEFORMAT_L16_UNORM; - case MESA_FORMAT_RGB_DXT1: - return BRW_SURFACEFORMAT_DXT1_RGB; - - case MESA_FORMAT_RGBA_DXT1: - return BRW_SURFACEFORMAT_BC1_UNORM; - - case MESA_FORMAT_RGBA_DXT3: - return BRW_SURFACEFORMAT_BC2_UNORM; - - case MESA_FORMAT_RGBA_DXT5: - return BRW_SURFACEFORMAT_BC3_UNORM; - - case MESA_FORMAT_SARGB8: - return BRW_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB; - - case MESA_FORMAT_SLA8: - return BRW_SURFACEFORMAT_L8A8_UNORM_SRGB; - - case MESA_FORMAT_SL8: - return BRW_SURFACEFORMAT_L8_UNORM_SRGB; - - case MESA_FORMAT_SRGB_DXT1: - return BRW_SURFACEFORMAT_BC1_UNORM_SRGB; - case MESA_FORMAT_S8_Z24: /* XXX: these different surface formats don't seem to * make any difference for shadow sampler/compares. @@ -181,15 +129,9 @@ static GLuint translate_tex_format( gl_format mesa_format, else return BRW_SURFACEFORMAT_L24X8_UNORM; - case MESA_FORMAT_DUDV8: - return BRW_SURFACEFORMAT_R8G8_SNORM; - - case MESA_FORMAT_SIGNED_RGBA8888_REV: - return BRW_SURFACEFORMAT_R8G8B8A8_SNORM; - default: - assert(0); - return 0; + assert(brw_format_for_mesa_format[mesa_format] != 0); + return brw_format_for_mesa_format[mesa_format]; } } @@ -448,45 +390,19 @@ brw_update_renderbuffer_surface(struct brw_context *brw, key.surface_type = BRW_SURFACE_2D; switch (irb->Base.Format) { - /* XRGB and ARGB are treated the same here because the chips in this - * family cannot render to XRGB targets. This means that we have to - * mask writes to alpha (ala glColorMask) and reconfigure the alpha - * blending hardware to use GL_ONE (or GL_ZERO) for cases where - * GL_DST_ALPHA (or GL_ONE_MINUS_DST_ALPHA) is used. - */ - case MESA_FORMAT_ARGB8888: case MESA_FORMAT_XRGB8888: + /* XRGB is handled as ARGB because the chips in this family + * cannot render to XRGB targets. This means that we have to + * mask writes to alpha (ala glColorMask) and reconfigure the + * alpha blending hardware to use GL_ONE (or GL_ZERO) for + * cases where GL_DST_ALPHA (or GL_ONE_MINUS_DST_ALPHA) is + * used. + */ key.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM; break; - case MESA_FORMAT_SARGB8: - key.surface_format = BRW_SURFACEFORMAT_B8G8R8A8_UNORM_SRGB; - break; - case MESA_FORMAT_RGB565: - key.surface_format = BRW_SURFACEFORMAT_B5G6R5_UNORM; - break; - case MESA_FORMAT_ARGB1555: - key.surface_format = BRW_SURFACEFORMAT_B5G5R5A1_UNORM; - break; - case MESA_FORMAT_ARGB4444: - key.surface_format = BRW_SURFACEFORMAT_B4G4R4A4_UNORM; - break; - case MESA_FORMAT_A8: - key.surface_format = BRW_SURFACEFORMAT_A8_UNORM; - break; - case MESA_FORMAT_R8: - key.surface_format = BRW_SURFACEFORMAT_R8_UNORM; - break; - case MESA_FORMAT_R16: - key.surface_format = BRW_SURFACEFORMAT_R16_UNORM; - break; - case MESA_FORMAT_RG88: - key.surface_format = BRW_SURFACEFORMAT_R8G8_UNORM; - break; - case MESA_FORMAT_RG1616: - key.surface_format = BRW_SURFACEFORMAT_R16G16_UNORM; - break; default: - _mesa_problem(ctx, "Bad renderbuffer format: %d\n", irb->Base.Format); + key.surface_format = brw_format_for_mesa_format[irb->Base.Format]; + assert(key.surface_format != 0); } key.tiling = region->tiling; key.width = rb->Width; diff --git a/src/mesa/drivers/dri/i965/gen6_vs_state.c b/src/mesa/drivers/dri/i965/gen6_vs_state.c index 4ef9e2e6072..ed132bdbd93 100644 --- a/src/mesa/drivers/dri/i965/gen6_vs_state.c +++ b/src/mesa/drivers/dri/i965/gen6_vs_state.c @@ -130,6 +130,7 @@ upload_vs_state(struct brw_context *brw) OUT_BATCH(CMD_3D_VS_STATE << 16 | (6 - 2)); OUT_RELOC(brw->vs.prog_bo, I915_GEM_DOMAIN_INSTRUCTION, 0, 0); OUT_BATCH((0 << GEN6_VS_SAMPLER_COUNT_SHIFT) | + GEN6_VS_FLOATING_POINT_MODE_ALT | (brw->vs.nr_surfaces << GEN6_VS_BINDING_TABLE_ENTRY_COUNT_SHIFT)); OUT_BATCH(0); /* scratch space base offset */ OUT_BATCH((1 << GEN6_VS_DISPATCH_START_GRF_SHIFT) | diff --git a/src/mesa/drivers/dri/i965/gen6_wm_state.c b/src/mesa/drivers/dri/i965/gen6_wm_state.c index d80df4e254b..2ae0c093ebe 100644 --- a/src/mesa/drivers/dri/i965/gen6_wm_state.c +++ b/src/mesa/drivers/dri/i965/gen6_wm_state.c @@ -133,6 +133,9 @@ upload_wm_state(struct brw_context *brw) dw5 |= GEN6_WM_LINE_AA_WIDTH_1_0; dw5 |= GEN6_WM_LINE_END_CAP_AA_WIDTH_0_5; + /* OpenGL non-ieee floating point mode */ + dw2 |= GEN6_WM_FLOATING_POINT_MODE_ALT; + /* BRW_NEW_NR_WM_SURFACES */ dw2 |= brw->wm.nr_surfaces << GEN6_WM_BINDING_TABLE_ENTRY_COUNT_SHIFT; diff --git a/src/mesa/drivers/dri/intel/intel_batchbuffer.c b/src/mesa/drivers/dri/intel/intel_batchbuffer.c index 21fc9ece886..20574ab5462 100644 --- a/src/mesa/drivers/dri/intel/intel_batchbuffer.c +++ b/src/mesa/drivers/dri/intel/intel_batchbuffer.c @@ -93,8 +93,16 @@ do_flush_locked(struct intel_batchbuffer *batch, GLuint used) batch->ptr = NULL; if (!intel->intelScreen->no_hw) { - drm_intel_bo_exec(batch->buf, used, NULL, 0, - (x_off & 0xffff) | (y_off << 16)); + int ring; + + if (intel->gen < 6 || !intel->batch->is_blit) { + ring = I915_EXEC_RENDER; + } else { + ring = I915_EXEC_BLT; + } + + drm_intel_bo_mrb_exec(batch->buf, used, NULL, 0, + (x_off & 0xffff) | (y_off << 16), ring); } if (unlikely(INTEL_DEBUG & DEBUG_BATCH)) { @@ -242,10 +250,10 @@ intel_batchbuffer_emit_reloc_fenced(struct intel_batchbuffer *batch, void intel_batchbuffer_data(struct intel_batchbuffer *batch, - const void *data, GLuint bytes) + const void *data, GLuint bytes, bool is_blit) { assert((bytes & 3) == 0); - intel_batchbuffer_require_space(batch, bytes); + intel_batchbuffer_require_space(batch, bytes, is_blit); __memcpy(batch->ptr, data, bytes); batch->ptr += bytes; } @@ -262,22 +270,29 @@ intel_batchbuffer_emit_mi_flush(struct intel_batchbuffer *batch) struct intel_context *intel = batch->intel; if (intel->gen >= 6) { - BEGIN_BATCH(8); - - /* XXX workaround: issue any post sync != 0 before write cache flush = 1 */ - OUT_BATCH(_3DSTATE_PIPE_CONTROL); - OUT_BATCH(PIPE_CONTROL_WRITE_IMMEDIATE); - OUT_BATCH(0); /* write address */ - OUT_BATCH(0); /* write data */ - - OUT_BATCH(_3DSTATE_PIPE_CONTROL); - OUT_BATCH(PIPE_CONTROL_INSTRUCTION_FLUSH | - PIPE_CONTROL_WRITE_FLUSH | - PIPE_CONTROL_DEPTH_CACHE_FLUSH | - PIPE_CONTROL_NO_WRITE); - OUT_BATCH(0); /* write address */ - OUT_BATCH(0); /* write data */ - ADVANCE_BATCH(); + if (intel->batch->is_blit) { + BEGIN_BATCH_BLT(1); + OUT_BATCH(MI_FLUSH); + ADVANCE_BATCH(); + } else { + BEGIN_BATCH(8); + /* XXX workaround: issue any post sync != 0 before write + * cache flush = 1 + */ + OUT_BATCH(_3DSTATE_PIPE_CONTROL); + OUT_BATCH(PIPE_CONTROL_WRITE_IMMEDIATE); + OUT_BATCH(0); /* write address */ + OUT_BATCH(0); /* write data */ + + OUT_BATCH(_3DSTATE_PIPE_CONTROL); + OUT_BATCH(PIPE_CONTROL_INSTRUCTION_FLUSH | + PIPE_CONTROL_WRITE_FLUSH | + PIPE_CONTROL_DEPTH_CACHE_FLUSH | + PIPE_CONTROL_NO_WRITE); + OUT_BATCH(0); /* write address */ + OUT_BATCH(0); /* write data */ + ADVANCE_BATCH(); + } } else if (intel->gen >= 4) { BEGIN_BATCH(4); OUT_BATCH(_3DSTATE_PIPE_CONTROL | diff --git a/src/mesa/drivers/dri/intel/intel_batchbuffer.h b/src/mesa/drivers/dri/intel/intel_batchbuffer.h index 428c027c2f1..635708587a6 100644 --- a/src/mesa/drivers/dri/intel/intel_batchbuffer.h +++ b/src/mesa/drivers/dri/intel/intel_batchbuffer.h @@ -31,6 +31,7 @@ struct intel_batchbuffer } emit; #endif + bool is_blit; GLuint dirty_state; GLuint reserved_space; }; @@ -55,7 +56,7 @@ void intel_batchbuffer_reset(struct intel_batchbuffer *batch); * intel_buffer_dword() calls. */ void intel_batchbuffer_data(struct intel_batchbuffer *batch, - const void *data, GLuint bytes); + const void *data, GLuint bytes, bool is_blit); void intel_batchbuffer_release_space(struct intel_batchbuffer *batch, GLuint bytes); @@ -114,8 +115,16 @@ intel_batchbuffer_emit_float(struct intel_batchbuffer *batch, float f) static INLINE void intel_batchbuffer_require_space(struct intel_batchbuffer *batch, - GLuint sz) + GLuint sz, int is_blit) { + + if (batch->intel->gen >= 6 && batch->is_blit != is_blit && + batch->ptr != batch->map) { + intel_batchbuffer_flush(batch); + } + + batch->is_blit = is_blit; + #ifdef DEBUG assert(sz < batch->size - 8); #endif @@ -124,9 +133,10 @@ intel_batchbuffer_require_space(struct intel_batchbuffer *batch, } static INLINE void -intel_batchbuffer_begin(struct intel_batchbuffer *batch, int n) +intel_batchbuffer_begin(struct intel_batchbuffer *batch, int n, bool is_blit) { - intel_batchbuffer_require_space(batch, n * 4); + intel_batchbuffer_require_space(batch, n * 4, is_blit); + #ifdef DEBUG assert(batch->map); assert(batch->emit.start_ptr == NULL); @@ -154,7 +164,8 @@ intel_batchbuffer_advance(struct intel_batchbuffer *batch) */ #define BATCH_LOCALS -#define BEGIN_BATCH(n) intel_batchbuffer_begin(intel->batch, n) +#define BEGIN_BATCH(n) intel_batchbuffer_begin(intel->batch, n, false) +#define BEGIN_BATCH_BLT(n) intel_batchbuffer_begin(intel->batch, n, true) #define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel->batch, d) #define OUT_BATCH_F(f) intel_batchbuffer_emit_float(intel->batch,f) #define OUT_RELOC(buf, read_domains, write_domain, delta) do { \ diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c index c2917e9b07e..a2822b11d96 100644 --- a/src/mesa/drivers/dri/intel/intel_blit.c +++ b/src/mesa/drivers/dri/intel/intel_blit.c @@ -38,6 +38,8 @@ #include "intel_reg.h" #include "intel_regions.h" #include "intel_batchbuffer.h" +#include "intel_tex.h" +#include "intel_mipmap_tree.h" #define FILE_DEBUG_FLAG DEBUG_BLIT @@ -107,10 +109,6 @@ intelEmitCopyBlit(struct intel_context *intel, drm_intel_bo *aper_array[3]; BATCH_LOCALS; - /* Blits are in a different ringbuffer so we don't use them. */ - if (intel->gen >= 6) - return GL_FALSE; - if (dst_tiling != I915_TILING_NONE) { if (dst_offset & 4095) return GL_FALSE; @@ -140,7 +138,7 @@ intelEmitCopyBlit(struct intel_context *intel, if (pass >= 2) return GL_FALSE; - intel_batchbuffer_require_space(intel->batch, 8 * 4); + intel_batchbuffer_require_space(intel->batch, 8 * 4, true); DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", __FUNCTION__, src_buffer, src_pitch, src_offset, src_x, src_y, @@ -181,7 +179,7 @@ intelEmitCopyBlit(struct intel_context *intel, assert(dst_x < dst_x2); assert(dst_y < dst_y2); - BEGIN_BATCH(8); + BEGIN_BATCH_BLT(8); OUT_BATCH(CMD); OUT_BATCH(BR13 | (uint16_t)dst_pitch); OUT_BATCH((dst_y << 16) | dst_x); @@ -219,9 +217,6 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask) GLint cx, cy, cw, ch; BATCH_LOCALS; - /* Blits are in a different ringbuffer so we don't use them. */ - assert(intel->gen < 6); - /* * Compute values for clearing the buffers. */ @@ -356,7 +351,7 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask) intel_batchbuffer_flush(intel->batch); } - BEGIN_BATCH(6); + BEGIN_BATCH_BLT(6); OUT_BATCH(CMD); OUT_BATCH(BR13); OUT_BATCH((y1 << 16) | x1); @@ -393,10 +388,6 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel, int dwords = ALIGN(src_size, 8) / 4; uint32_t opcode, br13, blit_cmd; - /* Blits are in a different ringbuffer so we don't use them. */ - if (intel->gen >= 6) - return GL_FALSE; - if (dst_tiling != I915_TILING_NONE) { if (dst_offset & 4095) return GL_FALSE; @@ -420,7 +411,7 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel, intel_batchbuffer_require_space( intel->batch, (8 * 4) + (3 * 4) + - dwords * 4 ); + dwords * 4, true); opcode = XY_SETUP_BLT_CMD; if (cpp == 4) @@ -439,7 +430,7 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel, if (dst_tiling != I915_TILING_NONE) blit_cmd |= XY_DST_TILED; - BEGIN_BATCH(8 + 3); + BEGIN_BATCH_BLT(8 + 3); OUT_BATCH(opcode); OUT_BATCH(br13); OUT_BATCH((0 << 16) | 0); /* clip x1, y1 */ @@ -456,9 +447,9 @@ intelEmitImmediateColorExpandBlit(struct intel_context *intel, OUT_BATCH(((y + h) << 16) | (x + w)); ADVANCE_BATCH(); - intel_batchbuffer_data( intel->batch, - src_bits, - dwords * 4 ); + intel_batchbuffer_data(intel->batch, + src_bits, + dwords * 4, true); intel_batchbuffer_emit_mi_flush(intel->batch); @@ -480,9 +471,6 @@ intel_emit_linear_blit(struct intel_context *intel, GLuint pitch, height; GLboolean ok; - /* Blits are in a different ringbuffer so we don't use them. */ - assert(intel->gen < 6); - /* The pitch given to the GPU must be DWORD aligned, and * we want width to match pitch. Max width is (1 << 15 - 1), * rounding that down to the nearest DWORD is 1 << 15 - 4 @@ -514,3 +502,81 @@ intel_emit_linear_blit(struct intel_context *intel, assert(ok); } } + +/** + * Used to initialize the alpha value of an ARGB8888 teximage after + * loading it from an XRGB8888 source. + * + * This is very common with glCopyTexImage2D(). + */ +void +intel_set_teximage_alpha_to_one(struct gl_context *ctx, + struct intel_texture_image *intel_image) +{ + struct intel_context *intel = intel_context(ctx); + unsigned int image_x, image_y; + uint32_t x1, y1, x2, y2; + uint32_t BR13, CMD; + int pitch, cpp; + drm_intel_bo *aper_array[2]; + struct intel_region *region = intel_image->mt->region; + BATCH_LOCALS; + + assert(intel_image->base.TexFormat == MESA_FORMAT_ARGB8888); + + /* get dest x/y in destination texture */ + intel_miptree_get_image_offset(intel_image->mt, + intel_image->level, + intel_image->face, + 0, + &image_x, &image_y); + + x1 = image_x; + y1 = image_y; + x2 = image_x + intel_image->base.Width; + y2 = image_y + intel_image->base.Height; + + pitch = region->pitch; + cpp = region->cpp; + + DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n", + __FUNCTION__, + intel_image->mt->region->buffer, (pitch * region->cpp), + x1, y1, x2 - x1, y2 - y1); + + BR13 = br13_for_cpp(region->cpp) | 0xf0 << 16; + CMD = XY_COLOR_BLT_CMD; + CMD |= XY_BLT_WRITE_ALPHA; + + assert(region->tiling != I915_TILING_Y); + +#ifndef I915 + if (region->tiling != I915_TILING_NONE) { + CMD |= XY_DST_TILED; + pitch /= 4; + } +#endif + BR13 |= (pitch * region->cpp); + + /* do space check before going any further */ + aper_array[0] = intel->batch->buf; + aper_array[1] = region->buffer; + + if (drm_intel_bufmgr_check_aperture_space(aper_array, + ARRAY_SIZE(aper_array)) != 0) { + intel_batchbuffer_flush(intel->batch); + } + + BEGIN_BATCH_BLT(6); + OUT_BATCH(CMD); + OUT_BATCH(BR13); + OUT_BATCH((y1 << 16) | x1); + OUT_BATCH((y2 << 16) | x2); + OUT_RELOC_FENCED(region->buffer, + I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, + 0); + OUT_BATCH(0xffffffff); /* white, but only alpha gets written */ + ADVANCE_BATCH(); + + intel_batchbuffer_emit_mi_flush(intel->batch); +} diff --git a/src/mesa/drivers/dri/intel/intel_blit.h b/src/mesa/drivers/dri/intel/intel_blit.h index 01631465735..ff69e4f8f8f 100644 --- a/src/mesa/drivers/dri/intel/intel_blit.h +++ b/src/mesa/drivers/dri/intel/intel_blit.h @@ -69,5 +69,7 @@ void intel_emit_linear_blit(struct intel_context *intel, drm_intel_bo *src_bo, unsigned int src_offset, unsigned int size); +void intel_set_teximage_alpha_to_one(struct gl_context *ctx, + struct intel_texture_image *intel_image); #endif diff --git a/src/mesa/drivers/dri/intel/intel_context.h b/src/mesa/drivers/dri/intel/intel_context.h index 96493c0f2bb..53a11ba9a7e 100644 --- a/src/mesa/drivers/dri/intel/intel_context.h +++ b/src/mesa/drivers/dri/intel/intel_context.h @@ -29,7 +29,7 @@ #define INTELCONTEXT_INC - +#include <stdbool.h> #include "main/mtypes.h" #include "main/mm.h" #include "dri_metaops.h" diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index 18e796a1186..c3f528c2ae5 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -42,6 +42,8 @@ #include "intel_fbo.h" #include "intel_mipmap_tree.h" #include "intel_regions.h" +#include "intel_tex.h" +#include "intel_span.h" #define FILE_DEBUG_FLAG DEBUG_FBO @@ -107,79 +109,27 @@ intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer ASSERT(rb->Name != 0); switch (internalFormat) { - case GL_RED: - case GL_R8: - rb->Format = MESA_FORMAT_R8; - rb->DataType = GL_UNSIGNED_BYTE; - break; - case GL_R16: - rb->Format = MESA_FORMAT_R16; - rb->DataType = GL_UNSIGNED_SHORT; - break; - case GL_RG: - case GL_RG8: - rb->Format = MESA_FORMAT_RG88; - rb->DataType = GL_UNSIGNED_BYTE; - break; - case GL_RG16: - rb->Format = MESA_FORMAT_RG1616; - rb->DataType = GL_UNSIGNED_SHORT; - break; - case GL_R3_G3_B2: - case GL_RGB4: - case GL_RGB5: - rb->Format = MESA_FORMAT_RGB565; - rb->DataType = GL_UNSIGNED_BYTE; - break; - case GL_RGB: - case GL_RGB8: - case GL_RGB10: - case GL_RGB12: - case GL_RGB16: - rb->Format = MESA_FORMAT_XRGB8888; - rb->DataType = GL_UNSIGNED_BYTE; - break; - case GL_RGBA: - case GL_RGBA2: - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGBA8: - case GL_RGB10_A2: - case GL_RGBA12: - case GL_RGBA16: - rb->Format = MESA_FORMAT_ARGB8888; - rb->DataType = GL_UNSIGNED_BYTE; - break; - case GL_ALPHA: - case GL_ALPHA8: - rb->Format = MESA_FORMAT_A8; - rb->DataType = GL_UNSIGNED_BYTE; - break; - case GL_DEPTH_COMPONENT16: - rb->Format = MESA_FORMAT_Z16; - rb->DataType = GL_UNSIGNED_SHORT; + default: + /* Use the same format-choice logic as for textures. + * Renderbuffers aren't any different from textures for us, + * except they're less useful because you can't texture with + * them. + */ + rb->Format = intelChooseTextureFormat(ctx, internalFormat, + GL_NONE, GL_NONE); break; case GL_STENCIL_INDEX: case GL_STENCIL_INDEX1_EXT: case GL_STENCIL_INDEX4_EXT: case GL_STENCIL_INDEX8_EXT: case GL_STENCIL_INDEX16_EXT: - case GL_DEPTH_COMPONENT: - case GL_DEPTH_COMPONENT24: - case GL_DEPTH_COMPONENT32: - case GL_DEPTH_STENCIL_EXT: - case GL_DEPTH24_STENCIL8_EXT: - /* alloc a depth+stencil buffer */ + /* These aren't actual texture formats, so force them here. */ rb->Format = MESA_FORMAT_S8_Z24; - rb->DataType = GL_UNSIGNED_INT_24_8_EXT; break; - default: - _mesa_problem(ctx, - "Unexpected format in intel_alloc_renderbuffer_storage"); - return GL_FALSE; } rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); + rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format); cpp = _mesa_get_format_bytes(rb->Format); intel_flush(ctx); @@ -338,39 +288,30 @@ intel_create_renderbuffer(gl_format format) switch (format) { case MESA_FORMAT_RGB565: irb->Base._BaseFormat = GL_RGB; - irb->Base.DataType = GL_UNSIGNED_BYTE; break; case MESA_FORMAT_XRGB8888: irb->Base._BaseFormat = GL_RGB; - irb->Base.DataType = GL_UNSIGNED_BYTE; break; case MESA_FORMAT_ARGB8888: irb->Base._BaseFormat = GL_RGBA; - irb->Base.DataType = GL_UNSIGNED_BYTE; break; case MESA_FORMAT_Z16: irb->Base._BaseFormat = GL_DEPTH_COMPONENT; - irb->Base.DataType = GL_UNSIGNED_SHORT; break; case MESA_FORMAT_X8_Z24: irb->Base._BaseFormat = GL_DEPTH_COMPONENT; - irb->Base.DataType = GL_UNSIGNED_INT; break; case MESA_FORMAT_S8_Z24: irb->Base._BaseFormat = GL_DEPTH_STENCIL; - irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT; break; case MESA_FORMAT_A8: irb->Base._BaseFormat = GL_ALPHA; - irb->Base.DataType = GL_UNSIGNED_BYTE; break; case MESA_FORMAT_R8: irb->Base._BaseFormat = GL_RED; - irb->Base.DataType = GL_UNSIGNED_BYTE; break; case MESA_FORMAT_RG88: irb->Base._BaseFormat = GL_RG; - irb->Base.DataType = GL_UNSIGNED_BYTE; break; default: _mesa_problem(NULL, @@ -381,6 +322,7 @@ intel_create_renderbuffer(gl_format format) irb->Base.Format = format; irb->Base.InternalFormat = irb->Base._BaseFormat; + irb->Base.DataType = intel_mesa_format_to_rb_datatype(format); /* intel-specific methods */ irb->Base.Delete = intel_delete_renderbuffer; @@ -457,70 +399,16 @@ static GLboolean intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb, struct gl_texture_image *texImage) { - if (texImage->TexFormat == MESA_FORMAT_ARGB8888) { - irb->Base.DataType = GL_UNSIGNED_BYTE; - DBG("Render to RGBA8 texture OK\n"); - } - else if (texImage->TexFormat == MESA_FORMAT_XRGB8888) { - irb->Base.DataType = GL_UNSIGNED_BYTE; - DBG("Render to XGBA8 texture OK\n"); - } -#ifndef I915 - else if (texImage->TexFormat == MESA_FORMAT_SARGB8) { - irb->Base.DataType = GL_UNSIGNED_BYTE; - DBG("Render to SARGB8 texture OK\n"); - } -#endif - else if (texImage->TexFormat == MESA_FORMAT_RGB565) { - irb->Base.DataType = GL_UNSIGNED_BYTE; - DBG("Render to RGB5 texture OK\n"); - } - else if (texImage->TexFormat == MESA_FORMAT_ARGB1555) { - irb->Base.DataType = GL_UNSIGNED_BYTE; - DBG("Render to ARGB1555 texture OK\n"); - } - else if (texImage->TexFormat == MESA_FORMAT_ARGB4444) { - irb->Base.DataType = GL_UNSIGNED_BYTE; - DBG("Render to ARGB4444 texture OK\n"); - } -#ifndef I915 - else if (texImage->TexFormat == MESA_FORMAT_A8) { - irb->Base.DataType = GL_UNSIGNED_BYTE; - DBG("Render to A8 texture OK\n"); - } - else if (texImage->TexFormat == MESA_FORMAT_R8) { - irb->Base.DataType = GL_UNSIGNED_BYTE; - DBG("Render to R8 texture OK\n"); - } - else if (texImage->TexFormat == MESA_FORMAT_RG88) { - irb->Base.DataType = GL_UNSIGNED_BYTE; - DBG("Render to RG88 texture OK\n"); - } - else if (texImage->TexFormat == MESA_FORMAT_R16) { - irb->Base.DataType = GL_UNSIGNED_SHORT; - DBG("Render to R8 texture OK\n"); - } - else if (texImage->TexFormat == MESA_FORMAT_RG1616) { - irb->Base.DataType = GL_UNSIGNED_SHORT; - DBG("Render to RG88 texture OK\n"); - } -#endif - else if (texImage->TexFormat == MESA_FORMAT_Z16) { - irb->Base.DataType = GL_UNSIGNED_SHORT; - DBG("Render to DEPTH16 texture OK\n"); - } - else if (texImage->TexFormat == MESA_FORMAT_S8_Z24) { - irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT; - DBG("Render to DEPTH_STENCIL texture OK\n"); - } - else { + if (!intel_span_supports_format(texImage->TexFormat)) { DBG("Render to texture BAD FORMAT %s\n", _mesa_get_format_name(texImage->TexFormat)); return GL_FALSE; + } else { + DBG("Render to texture %s\n", _mesa_get_format_name(texImage->TexFormat)); } irb->Base.Format = texImage->TexFormat; - + irb->Base.DataType = intel_mesa_format_to_rb_datatype(texImage->TexFormat); irb->Base.InternalFormat = texImage->InternalFormat; irb->Base._BaseFormat = _mesa_base_fbo_format(ctx, irb->Base.InternalFormat); irb->Base.Width = texImage->Width; @@ -659,7 +547,8 @@ intel_finish_render_texture(struct gl_context * ctx, _glthread_GetID(), att->Texture->Name); /* Flag that this image may now be validated into the object's miptree. */ - intel_image->used_as_render_target = GL_FALSE; + if (intel_image) + intel_image->used_as_render_target = GL_FALSE; /* Since we've (probably) rendered to the texture and will (likely) use * it in the texture domain later on in this batchbuffer, flush the @@ -711,22 +600,9 @@ intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) continue; } - switch (irb->Base.Format) { - case MESA_FORMAT_ARGB8888: - case MESA_FORMAT_XRGB8888: - case MESA_FORMAT_RGB565: - case MESA_FORMAT_ARGB1555: - case MESA_FORMAT_ARGB4444: -#ifndef I915 - case MESA_FORMAT_SARGB8: - case MESA_FORMAT_A8: - case MESA_FORMAT_R8: - case MESA_FORMAT_R16: - case MESA_FORMAT_RG88: - case MESA_FORMAT_RG1616: -#endif - break; - default: + if (!intel_span_supports_format(irb->Base.Format)) { + DBG("Unsupported texture/renderbuffer format attached: %s\n", + _mesa_get_format_name(irb->Base.Format)); fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; } } diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index 3f13589a214..d683e675328 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -35,19 +35,6 @@ #include "utils.h" #include "xmlpool.h" -#include "intel_batchbuffer.h" -#include "intel_buffers.h" -#include "intel_bufmgr.h" -#include "intel_chipset.h" -#include "intel_fbo.h" -#include "intel_screen.h" -#include "intel_tex.h" -#include "intel_regions.h" - -#include "i915_drm.h" - -#define DRI_CONF_TEXTURE_TILING(def) \ - PUBLIC const char __driConfigOptions[] = DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE @@ -92,6 +79,17 @@ DRI_CONF_END; const GLuint __driNConfigOptions = 11; +#include "intel_batchbuffer.h" +#include "intel_buffers.h" +#include "intel_bufmgr.h" +#include "intel_chipset.h" +#include "intel_fbo.h" +#include "intel_screen.h" +#include "intel_tex.h" +#include "intel_regions.h" + +#include "i915_drm.h" + #ifdef USE_NEW_INTERFACE static PFNGLXCREATECONTEXTMODES create_context_modes = NULL; #endif /*USE_NEW_INTERFACE */ diff --git a/src/mesa/drivers/dri/intel/intel_span.c b/src/mesa/drivers/dri/intel/intel_span.c index 104cadf0f9e..1f41518535c 100644 --- a/src/mesa/drivers/dri/intel/intel_span.c +++ b/src/mesa/drivers/dri/intel/intel_span.c @@ -25,6 +25,7 @@ * **************************************************************************/ +#include <stdbool.h> #include "main/glheader.h" #include "main/macros.h" #include "main/mtypes.h" @@ -113,6 +114,26 @@ intel_set_span_functions(struct intel_context *intel, #define TAG2(x,y) intel_##x##y##_A8 #include "spantmp2.h" +#define SPANTMP_MESA_FMT MESA_FORMAT_R8 +#define TAG(x) intel_##x##_R8 +#define TAG2(x,y) intel_##x##y##_R8 +#include "spantmp2.h" + +#define SPANTMP_MESA_FMT MESA_FORMAT_RG88 +#define TAG(x) intel_##x##_RG88 +#define TAG2(x,y) intel_##x##y##_RG88 +#include "spantmp2.h" + +#define SPANTMP_MESA_FMT MESA_FORMAT_R16 +#define TAG(x) intel_##x##_R16 +#define TAG2(x,y) intel_##x##y##_R16 +#include "spantmp2.h" + +#define SPANTMP_MESA_FMT MESA_FORMAT_RG1616 +#define TAG(x) intel_##x##_RG1616 +#define TAG2(x,y) intel_##x##y##_RG1616 +#include "spantmp2.h" + #define LOCAL_DEPTH_VARS \ struct intel_renderbuffer *irb = intel_renderbuffer(rb); \ const GLint yScale = rb->Name ? 1 : -1; \ @@ -339,6 +360,32 @@ intel_unmap_vertex_shader_textures(struct gl_context *ctx) } } +typedef void (*span_init_func)(struct gl_renderbuffer *rb); + +static span_init_func intel_span_init_funcs[MESA_FORMAT_COUNT] = +{ + [MESA_FORMAT_A8] = intel_InitPointers_A8, + [MESA_FORMAT_RGB565] = intel_InitPointers_RGB565, + [MESA_FORMAT_ARGB4444] = intel_InitPointers_ARGB4444, + [MESA_FORMAT_ARGB1555] = intel_InitPointers_ARGB1555, + [MESA_FORMAT_XRGB8888] = intel_InitPointers_xRGB8888, + [MESA_FORMAT_ARGB8888] = intel_InitPointers_ARGB8888, + [MESA_FORMAT_SARGB8] = intel_InitPointers_ARGB8888, + [MESA_FORMAT_Z16] = intel_InitDepthPointers_z16, + [MESA_FORMAT_X8_Z24] = intel_InitDepthPointers_z24_s8, + [MESA_FORMAT_S8_Z24] = intel_InitDepthPointers_z24_s8, + [MESA_FORMAT_R8] = intel_InitPointers_R8, + [MESA_FORMAT_RG88] = intel_InitPointers_RG88, + [MESA_FORMAT_R16] = intel_InitPointers_R16, + [MESA_FORMAT_RG1616] = intel_InitPointers_RG1616, +}; + +bool +intel_span_supports_format(gl_format format) +{ + return intel_span_init_funcs[format] != NULL; +} + /** * Plug in appropriate span read/write functions for the given renderbuffer. * These are used for the software fallbacks. @@ -349,37 +396,6 @@ intel_set_span_functions(struct intel_context *intel, { struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb; - switch (irb->Base.Format) { - case MESA_FORMAT_A8: - intel_InitPointers_A8(rb); - break; - case MESA_FORMAT_RGB565: - intel_InitPointers_RGB565(rb); - break; - case MESA_FORMAT_ARGB4444: - intel_InitPointers_ARGB4444(rb); - break; - case MESA_FORMAT_ARGB1555: - intel_InitPointers_ARGB1555(rb); - break; - case MESA_FORMAT_XRGB8888: - intel_InitPointers_xRGB8888(rb); - break; - case MESA_FORMAT_ARGB8888: - case MESA_FORMAT_SARGB8: - intel_InitPointers_ARGB8888(rb); - break; - case MESA_FORMAT_Z16: - intel_InitDepthPointers_z16(rb); - break; - case MESA_FORMAT_X8_Z24: - case MESA_FORMAT_S8_Z24: - intel_InitDepthPointers_z24_s8(rb); - break; - default: - _mesa_problem(NULL, - "Unexpected MesaFormat %d in intelSetSpanFunctions", - irb->Base.Format); - break; - } + assert(intel_span_init_funcs[irb->Base.Format]); + intel_span_init_funcs[irb->Base.Format](rb); } diff --git a/src/mesa/drivers/dri/intel/intel_span.h b/src/mesa/drivers/dri/intel/intel_span.h index aa8d08e843a..5a4c4e8e52a 100644 --- a/src/mesa/drivers/dri/intel/intel_span.h +++ b/src/mesa/drivers/dri/intel/intel_span.h @@ -28,6 +28,9 @@ #ifndef _INTEL_SPAN_H #define _INTEL_SPAN_H +#include "main/formats.h" +#include <stdbool.h> + extern void intelInitSpanFuncs(struct gl_context * ctx); extern void intelSpanRenderFinish(struct gl_context * ctx); @@ -38,5 +41,6 @@ void intel_renderbuffer_unmap(struct intel_context *intel, struct gl_renderbuffer *rb); void intel_map_vertex_shader_textures(struct gl_context *ctx); void intel_unmap_vertex_shader_textures(struct gl_context *ctx); +bool intel_span_supports_format(gl_format format); #endif diff --git a/src/mesa/drivers/dri/intel/intel_tex.h b/src/mesa/drivers/dri/intel/intel_tex.h index 7906554e453..b638628c711 100644 --- a/src/mesa/drivers/dri/intel/intel_tex.h +++ b/src/mesa/drivers/dri/intel/intel_tex.h @@ -42,6 +42,7 @@ void intelInitTextureCopyImageFuncs(struct dd_function_table *functions); gl_format intelChooseTextureFormat(struct gl_context *ctx, GLint internalFormat, GLenum format, GLenum type); +GLenum intel_mesa_format_to_rb_datatype(gl_format format); void intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *pDraw); diff --git a/src/mesa/drivers/dri/intel/intel_tex_copy.c b/src/mesa/drivers/dri/intel/intel_tex_copy.c index 87b31bf078c..c6bc3d962ab 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_copy.c +++ b/src/mesa/drivers/dri/intel/intel_tex_copy.c @@ -50,44 +50,20 @@ * Do the best we can using the blitter. A future project is to use * the texture engine and fragment programs for these copies. */ -static const struct intel_region * -get_teximage_source(struct intel_context *intel, GLenum internalFormat) +static struct intel_renderbuffer * +get_teximage_readbuffer(struct intel_context *intel, GLenum internalFormat) { - struct intel_renderbuffer *irb; - DBG("%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(internalFormat)); switch (internalFormat) { case GL_DEPTH_COMPONENT: case GL_DEPTH_COMPONENT16: - irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH); - if (irb && irb->region && irb->region->cpp == 2) - return irb->region; - return NULL; case GL_DEPTH24_STENCIL8_EXT: case GL_DEPTH_STENCIL_EXT: - irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH); - if (irb && irb->region && irb->region->cpp == 4) - return irb->region; - return NULL; - case 4: - case GL_RGBA: - case GL_RGBA8: - irb = intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer); - /* We're required to set alpha to 1.0 in this case, but we can't - * do that with the blitter, so fall back. We could use the 3D - * engine or do two passes with the blitter, but it doesn't seem - * worth it for this case. */ - if (irb->Base._BaseFormat == GL_RGB) - return NULL; - return irb->region; - case 3: - case GL_RGB: - case GL_RGB8: - return intel_readbuf_region(intel); + return intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH); default: - return NULL; + return intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer); } } @@ -101,23 +77,34 @@ do_copy_texsubimage(struct intel_context *intel, GLint x, GLint y, GLsizei width, GLsizei height) { struct gl_context *ctx = &intel->ctx; - const struct intel_region *src = get_teximage_source(intel, internalFormat); + struct intel_renderbuffer *irb; + bool copy_supported_with_alpha_override = false; + + intel_prepare_render(intel); - if (!intelImage->mt || !src || !src->buffer) { + irb = get_teximage_readbuffer(intel, internalFormat); + if (!intelImage->mt || !irb || !irb->region) { if (unlikely(INTEL_DEBUG & DEBUG_FALLBACKS)) fprintf(stderr, "%s fail %p %p (0x%08x)\n", - __FUNCTION__, intelImage->mt, src, internalFormat); + __FUNCTION__, intelImage->mt, irb, internalFormat); return GL_FALSE; } - if (intelImage->mt->cpp != src->cpp) { - fallback_debug("%s fail %d vs %d cpp\n", - __FUNCTION__, intelImage->mt->cpp, src->cpp); + if (irb->Base.Format == MESA_FORMAT_XRGB8888 && + intelImage->base.TexFormat == MESA_FORMAT_ARGB8888) { + copy_supported_with_alpha_override = true; + } + + if (intelImage->base.TexFormat != irb->Base.Format && + !copy_supported_with_alpha_override) { + if (unlikely(INTEL_DEBUG & DEBUG_FALLBACKS)) + fprintf(stderr, "%s mismatched formats %s, %s\n", + __FUNCTION__, + _mesa_get_format_name(intelImage->base.TexFormat), + _mesa_get_format_name(irb->Base.Format)); return GL_FALSE; } - /* intel_flush(ctx); */ - intel_prepare_render(intel); { drm_intel_bo *dst_bo = intel_region_buffer(intel, intelImage->mt->region, @@ -140,24 +127,24 @@ do_copy_texsubimage(struct intel_context *intel, if (ctx->ReadBuffer->Name == 0) { /* Flip vertical orientation for system framebuffers */ y = ctx->ReadBuffer->Height - (y + height); - src_pitch = -src->pitch; + src_pitch = -irb->region->pitch; } else { /* reading from a FBO, y is already oriented the way we like */ - src_pitch = src->pitch; + src_pitch = irb->region->pitch; } /* blit from src buffer to texture */ if (!intelEmitCopyBlit(intel, intelImage->mt->cpp, src_pitch, - src->buffer, + irb->region->buffer, 0, - src->tiling, + irb->region->tiling, intelImage->mt->region->pitch, dst_bo, 0, intelImage->mt->region->tiling, - src->draw_x + x, src->draw_y + y, + irb->region->draw_x + x, irb->region->draw_y + y, image_x + dstx, image_y + dsty, width, height, GL_COPY)) { @@ -165,6 +152,9 @@ do_copy_texsubimage(struct intel_context *intel, } } + if (copy_supported_with_alpha_override) + intel_set_teximage_alpha_to_one(ctx, intelImage); + return GL_TRUE; } diff --git a/src/mesa/drivers/dri/intel/intel_tex_format.c b/src/mesa/drivers/dri/intel/intel_tex_format.c index f8316ae2f8d..c9763c9ae16 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_format.c +++ b/src/mesa/drivers/dri/intel/intel_tex_format.c @@ -4,6 +4,39 @@ #include "main/formats.h" /** + * Returns the renderbuffer DataType for a MESA_FORMAT. + */ +GLenum +intel_mesa_format_to_rb_datatype(gl_format format) +{ + switch (format) { + case MESA_FORMAT_ARGB8888: + case MESA_FORMAT_XRGB8888: + case MESA_FORMAT_SARGB8: + case MESA_FORMAT_R8: + case MESA_FORMAT_RG88: + case MESA_FORMAT_A8: + case MESA_FORMAT_AL88: + case MESA_FORMAT_RGB565: + case MESA_FORMAT_ARGB1555: + case MESA_FORMAT_ARGB4444: + return GL_UNSIGNED_BYTE; + case MESA_FORMAT_R16: + case MESA_FORMAT_RG1616: + case MESA_FORMAT_Z16: + return GL_UNSIGNED_SHORT; + case MESA_FORMAT_X8_Z24: + return GL_UNSIGNED_INT; + case MESA_FORMAT_S8_Z24: + return GL_UNSIGNED_INT_24_8_EXT; + default: + _mesa_problem(NULL, "unexpected MESA_FORMAT for renderbuffer"); + return GL_UNSIGNED_BYTE; + } +} + + +/** * Choose hardware texture format given the user's glTexImage parameters. * * It works out that this function is fine for all the supported diff --git a/src/mesa/drivers/dri/nouveau/nouveau_driver.h b/src/mesa/drivers/dri/nouveau/nouveau_driver.h index 8036b18edc0..c5ac1282d0d 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_driver.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_driver.h @@ -38,7 +38,6 @@ #include <assert.h> #include "nouveau_device.h" -#include "nouveau_pushbuf.h" #include "nouveau_grobj.h" #include "nouveau_channel.h" #include "nouveau_bo.h" @@ -46,6 +45,7 @@ #include "nouveau_screen.h" #include "nouveau_state.h" #include "nouveau_surface.h" +#include "nv04_pushbuf.h" #define DRIVER_DATE "20091015" #define DRIVER_AUTHOR "Nouveau" diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_swizzles.c b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_swizzles.c index a0f7bd81741..133a9f72ec7 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_swizzles.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_dataflow_swizzles.c @@ -56,6 +56,7 @@ static void rewrite_source(struct radeon_compiler * c, mov->U.I.DstReg.Index = tempreg; mov->U.I.DstReg.WriteMask = split.Phase[phase]; mov->U.I.SrcReg[0] = inst->U.I.SrcReg[src]; + mov->U.I.PreSub = inst->U.I.PreSub; phase_refmask = 0; for(unsigned int chan = 0; chan < 4; ++chan) { diff --git a/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c b/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c index 58977a40c7c..c8063171b81 100644 --- a/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c +++ b/src/mesa/drivers/dri/r300/compiler/radeon_program_alu.c @@ -689,11 +689,12 @@ static void transform_r300_vertex_fix_LIT(struct radeon_compiler* c, &constant_swizzle); /* MOV dst, src */ + dst.WriteMask = RC_MASK_XYZW; emit1(c, inst->Prev, RC_OPCODE_MOV, 0, dst, inst->U.I.SrcReg[0]); - /* MAX dst.z, src, 0.00...001 */ + /* MAX dst.y, src, 0.00...001 */ emit2(c, inst->Prev, RC_OPCODE_MAX, 0, dstregtmpmask(dst.Index, RC_MASK_Y), srcreg(RC_FILE_TEMPORARY, dst.Index), diff --git a/src/mesa/drivers/dri/r600/r700_assembler.c b/src/mesa/drivers/dri/r600/r700_assembler.c index 1fa559cec1a..bee9c3bc6d3 100644 --- a/src/mesa/drivers/dri/r600/r700_assembler.c +++ b/src/mesa/drivers/dri/r600/r700_assembler.c @@ -1134,7 +1134,7 @@ GLboolean EG_assemble_vfetch_instruction(r700_AssemblerBase* pAsm, EG_VTX_WORD1__DST_SEL_W_shift, EG_VTX_WORD1__DST_SEL_W_mask); - SETfield(vfetch_instruction_ptr->m_Word1.val, 0, /* use format here, in r6/r7, format used set in const, need to use same */ + SETfield(vfetch_instruction_ptr->m_Word1.val, 1, EG_VTX_WORD1__UCF_shift, EG_VTX_WORD1__UCF_bit); SETfield(vfetch_instruction_ptr->m_Word1.val, data_format, diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index b71afdd61f3..fd5b4e915cd 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -249,7 +249,8 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) #if FEATURE_ARB_framebuffer_object ctx->Extensions.ARB_framebuffer_object = GL_TRUE; #endif -#if FEATURE_ARB_geometry_shader4 +#if FEATURE_ARB_geometry_shader4 && 0 + /* XXX re-enable when GLSL compiler again supports geometry shaders */ ctx->Extensions.ARB_geometry_shader4 = GL_TRUE; #endif ctx->Extensions.ARB_half_float_pixel = GL_TRUE; @@ -258,6 +259,7 @@ _mesa_enable_sw_extensions(struct gl_context *ctx) ctx->Extensions.ARB_multitexture = GL_TRUE; #if FEATURE_queryobj ctx->Extensions.ARB_occlusion_query = GL_TRUE; + ctx->Extensions.ARB_occlusion_query2 = GL_TRUE; #endif ctx->Extensions.ARB_point_sprite = GL_TRUE; #if FEATURE_ARB_shader_objects @@ -857,8 +859,6 @@ make_extension_string_es2(const struct gl_context *ctx, GLubyte *str) { size_t len = 0; - len += append_extension(&str, "GL_OES_compressed_paletted_texture"); - if (ctx->Extensions.ARB_framebuffer_object) { len += append_extension(&str, "GL_OES_depth24"); len += append_extension(&str, "GL_OES_depth32"); diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c index cd9eb81852f..42f70ca232b 100644 --- a/src/mesa/main/formats.c +++ b/src/mesa/main/formats.c @@ -863,7 +863,6 @@ const char * _mesa_get_format_name(gl_format format) { const struct gl_format_info *info = _mesa_get_format_info(format); - ASSERT(info->BytesPerBlock); return info->StrName; } diff --git a/src/mesa/main/queryobj.c b/src/mesa/main/queryobj.c index 88743977206..66fb5980589 100644 --- a/src/mesa/main/queryobj.c +++ b/src/mesa/main/queryobj.c @@ -143,6 +143,11 @@ get_query_binding_point(struct gl_context *ctx, GLenum target) return &ctx->Query.CurrentOcclusionObject; else return NULL; + case GL_ANY_SAMPLES_PASSED: + if (ctx->Extensions.ARB_occlusion_query2) + return &ctx->Query.CurrentOcclusionObject; + else + return NULL; case GL_TIME_ELAPSED_EXT: if (ctx->Extensions.EXT_timer_query) return &ctx->Query.CurrentTimerObject; @@ -378,11 +383,18 @@ _mesa_GetQueryObjectivARB(GLuint id, GLenum pname, GLint *params) if (!q->Ready) ctx->Driver.WaitQuery(ctx, q); /* if result is too large for returned type, clamp to max value */ - if (q->Result > 0x7fffffff) { - *params = 0x7fffffff; - } - else { - *params = (GLint)q->Result; + if (q->Target == GL_ANY_SAMPLES_PASSED) { + if (q->Result) + *params = GL_TRUE; + else + *params = GL_FALSE; + } else { + if (q->Result > 0x7fffffff) { + *params = 0x7fffffff; + } + else { + *params = (GLint)q->Result; + } } break; case GL_QUERY_RESULT_AVAILABLE_ARB: @@ -418,11 +430,18 @@ _mesa_GetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) if (!q->Ready) ctx->Driver.WaitQuery(ctx, q); /* if result is too large for returned type, clamp to max value */ - if (q->Result > 0xffffffff) { - *params = 0xffffffff; - } - else { - *params = (GLuint)q->Result; + if (q->Target == GL_ANY_SAMPLES_PASSED) { + if (q->Result) + *params = GL_TRUE; + else + *params = GL_FALSE; + } else { + if (q->Result > 0xffffffff) { + *params = 0xffffffff; + } + else { + *params = (GLuint)q->Result; + } } break; case GL_QUERY_RESULT_AVAILABLE_ARB: diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index b274a961b28..490c4cab7ab 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -1569,7 +1569,13 @@ ir_to_mesa_visitor::visit(ir_dereference_record *ir) break; offset += type_size(struct_type->fields.structure[i].type); } - this->result.swizzle = swizzle_for_size(ir->type->vector_elements); + + /* If the type is smaller than a vec4, replicate the last channel out. */ + if (ir->type->is_scalar() || ir->type->is_vector()) + this->result.swizzle = swizzle_for_size(ir->type->vector_elements); + else + this->result.swizzle = SWIZZLE_NOOP; + this->result.index += offset; } diff --git a/src/mesa/program/ir_to_mesa.h b/src/mesa/program/ir_to_mesa.h index 7197615f949..7410e149735 100644 --- a/src/mesa/program/ir_to_mesa.h +++ b/src/mesa/program/ir_to_mesa.h @@ -25,8 +25,11 @@ extern "C" { #endif -#include "main/config.h" -#include "main/mtypes.h" +#include "main/glheader.h" + +struct gl_context; +struct gl_shader; +struct gl_shader_program; void _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *sh); void _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog); diff --git a/src/mesa/program/nvfragparse.h b/src/mesa/program/nvfragparse.h index 3e85dd2c30b..088e7527d5b 100644 --- a/src/mesa/program/nvfragparse.h +++ b/src/mesa/program/nvfragparse.h @@ -30,7 +30,10 @@ #ifndef NVFRAGPARSE_H #define NVFRAGPARSE_H -#include "main/mtypes.h" +#include "main/glheader.h" + +struct gl_context; +struct gl_fragment_program; extern void _mesa_parse_nv_fragment_program(struct gl_context *ctx, GLenum target, diff --git a/src/mesa/program/nvvertparse.h b/src/mesa/program/nvvertparse.h index e98e867320f..7318e149416 100644 --- a/src/mesa/program/nvvertparse.h +++ b/src/mesa/program/nvvertparse.h @@ -29,7 +29,10 @@ #ifndef NVVERTPARSE_H #define NVVERTPARSE_H -#include "main/mtypes.h" +#include "main/glheader.h" + +struct gl_context; +struct gl_vertex_program; extern void _mesa_parse_nv_vertex_program(struct gl_context *ctx, GLenum target, diff --git a/src/mesa/program/prog_cache.h b/src/mesa/program/prog_cache.h index 4907ae3030e..01673348279 100644 --- a/src/mesa/program/prog_cache.h +++ b/src/mesa/program/prog_cache.h @@ -30,8 +30,9 @@ #define PROG_CACHE_H -#include "main/mtypes.h" +#include "main/glheader.h" +struct gl_context; /** Opaque type */ struct gl_program_cache; diff --git a/src/mesa/program/prog_execute.c b/src/mesa/program/prog_execute.c index 1d97a077f52..dd15e9a1ccd 100644 --- a/src/mesa/program/prog_execute.c +++ b/src/mesa/program/prog_execute.c @@ -1670,6 +1670,18 @@ _mesa_execute_program(struct gl_context * ctx, fetch_texel(ctx, machine, inst, texcoord, lodBias, color); + if (DEBUG_PROG) { + printf("TXB (%g, %g, %g, %g) = texture[%d][%g %g %g %g]" + " bias %g\n", + color[0], color[1], color[2], color[3], + inst->TexSrcUnit, + texcoord[0], + texcoord[1], + texcoord[2], + texcoord[3], + lodBias); + } + store_vector4(inst, machine, color); } break; diff --git a/src/mesa/program/prog_optimize.h b/src/mesa/program/prog_optimize.h index 00f1080449b..463f5fc51c4 100644 --- a/src/mesa/program/prog_optimize.h +++ b/src/mesa/program/prog_optimize.h @@ -27,9 +27,10 @@ #include "main/config.h" -#include "main/mtypes.h" +#include "main/glheader.h" +struct gl_context; struct gl_program; struct prog_instruction; diff --git a/src/mesa/program/prog_statevars.h b/src/mesa/program/prog_statevars.h index 009ebde0012..f2407af9c87 100644 --- a/src/mesa/program/prog_statevars.h +++ b/src/mesa/program/prog_statevars.h @@ -25,8 +25,10 @@ #ifndef PROG_STATEVARS_H #define PROG_STATEVARS_H -#include "main/mtypes.h" +#include "main/glheader.h" +struct gl_context; +struct gl_program_parameter_list; /** * Number of STATE_* values we need to address any GL state. diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index 05442ef91b5..c311d043931 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -50,99 +50,6 @@ #include "st_program.h" - -/** - * Translate fragment program if needed. - */ -static void -translate_fp(struct st_context *st, - struct st_fragment_program *stfp) -{ - if (!stfp->tgsi.tokens) { - assert(stfp->Base.Base.NumInstructions > 0); - - st_translate_fragment_program(st, stfp); - } -} - -/* - * Translate geometry program if needed. - */ -static void -translate_gp(struct st_context *st, - struct st_geometry_program *stgp) -{ - if (!stgp->tgsi.tokens) { - assert(stgp->Base.Base.NumInstructions > 1); - - st_translate_geometry_program(st, stgp); - } -} - -/** - * Find a translated vertex program that corresponds to stvp and - * has outputs matched to stfp's inputs. - * This performs vertex and fragment translation (to TGSI) when needed. - */ -static struct st_vp_varient * -find_translated_vp(struct st_context *st, - struct st_vertex_program *stvp ) -{ - struct st_vp_varient *vpv; - struct st_vp_varient_key key; - - /* Nothing in our key yet. This will change: - */ - memset(&key, 0, sizeof key); - - /* When this is true, we will add an extra input to the vertex - * shader translation (for edgeflags), an extra output with - * edgeflag semantics, and extend the vertex shader to pass through - * the input to the output. We'll need to use similar logic to set - * up the extra vertex_element input for edgeflags. - * _NEW_POLYGON, ST_NEW_EDGEFLAGS_DATA - */ - key.passthrough_edgeflags = (st->vertdata_edgeflags && ( - st->ctx->Polygon.FrontMode != GL_FILL || - st->ctx->Polygon.BackMode != GL_FILL)); - - - /* Do we need to throw away old translations after a change in the - * GL program string? - */ - if (stvp->serialNo != stvp->lastSerialNo) { - /* These may have changed if the program string changed. - */ - st_prepare_vertex_program( st, stvp ); - - /* We are now up-to-date: - */ - stvp->lastSerialNo = stvp->serialNo; - } - - /* See if we've got a translated vertex program whose outputs match - * the fragment program's inputs. - */ - for (vpv = stvp->varients; vpv; vpv = vpv->next) { - if (memcmp(&vpv->key, &key, sizeof key) == 0) { - break; - } - } - - /* No? Perform new translation here. */ - if (!vpv) { - vpv = st_translate_vertex_program(st, stvp, &key); - if (!vpv) - return NULL; - - vpv->next = stvp->varients; - stvp->varients = vpv; - } - - return vpv; -} - - /** * Return pointer to a pass-through fragment shader. * This shader is used when a texture is missing/incomplete. @@ -167,12 +74,16 @@ static void update_fp( struct st_context *st ) { struct st_fragment_program *stfp; + struct st_fp_variant_key key; assert(st->ctx->FragmentProgram._Current); stfp = st_fragment_program(st->ctx->FragmentProgram._Current); assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB); - translate_fp(st, stfp); + memset(&key, 0, sizeof(key)); + key.st = st; + + st->fp_variant = st_get_fp_variant(st, stfp, &key); st_reference_fragprog(st, &st->fp, stfp); @@ -182,7 +93,8 @@ update_fp( struct st_context *st ) cso_set_fragment_shader_handle(st->cso_context, fs); } else { - cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader); + cso_set_fragment_shader_handle(st->cso_context, + st->fp_variant->driver_shader); } } @@ -206,6 +118,7 @@ static void update_vp( struct st_context *st ) { struct st_vertex_program *stvp; + struct st_vp_variant_key key; /* find active shader and params -- Should be covered by * ST_NEW_VERTEX_PROGRAM @@ -214,12 +127,26 @@ update_vp( struct st_context *st ) stvp = st_vertex_program(st->ctx->VertexProgram._Current); assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB); - st->vp_varient = find_translated_vp(st, stvp); + memset(&key, 0, sizeof key); + key.st = st; /* variants are per-context */ + + /* When this is true, we will add an extra input to the vertex + * shader translation (for edgeflags), an extra output with + * edgeflag semantics, and extend the vertex shader to pass through + * the input to the output. We'll need to use similar logic to set + * up the extra vertex_element input for edgeflags. + * _NEW_POLYGON, ST_NEW_EDGEFLAGS_DATA + */ + key.passthrough_edgeflags = (st->vertdata_edgeflags && ( + st->ctx->Polygon.FrontMode != GL_FILL || + st->ctx->Polygon.BackMode != GL_FILL)); + + st->vp_variant = st_get_vp_variant(st, stvp, &key); st_reference_vertprog(st, &st->vp, stvp); cso_set_vertex_shader_handle(st->cso_context, - st->vp_varient->driver_shader); + st->vp_variant->driver_shader); st->vertex_result_to_slot = stvp->result_to_output; } @@ -231,14 +158,16 @@ const struct st_tracked_state st_update_vp = { _NEW_POLYGON, /* mesa */ ST_NEW_VERTEX_PROGRAM | ST_NEW_EDGEFLAGS_DATA /* st */ }, - update_vp /* update */ + update_vp /* update */ }; + + static void update_gp( struct st_context *st ) { - struct st_geometry_program *stgp; + struct st_gp_variant_key key; if (!st->ctx->GeometryProgram._Current) { cso_set_geometry_shader_handle(st->cso_context, NULL); @@ -248,18 +177,22 @@ update_gp( struct st_context *st ) stgp = st_geometry_program(st->ctx->GeometryProgram._Current); assert(stgp->Base.Base.Target == MESA_GEOMETRY_PROGRAM); - translate_gp(st, stgp); + memset(&key, 0, sizeof(key)); + key.st = st; + + st->gp_variant = st_get_gp_variant(st, stgp, &key); st_reference_geomprog(st, &st->gp, stgp); - cso_set_geometry_shader_handle(st->cso_context, stgp->driver_shader); + cso_set_geometry_shader_handle(st->cso_context, + st->gp_variant->driver_shader); } const struct st_tracked_state st_update_gp = { - "st_update_gp", /* name */ - { /* dirty */ - 0, /* mesa */ - ST_NEW_GEOMETRY_PROGRAM /* st */ + "st_update_gp", /* name */ + { /* dirty */ + 0, /* mesa */ + ST_NEW_GEOMETRY_PROGRAM /* st */ }, - update_gp /* update */ + update_gp /* update */ }; diff --git a/src/mesa/state_tracker/st_cb_accum.h b/src/mesa/state_tracker/st_cb_accum.h index b8c9c350031..050a21483e4 100644 --- a/src/mesa/state_tracker/st_cb_accum.h +++ b/src/mesa/state_tracker/st_cb_accum.h @@ -30,7 +30,11 @@ #define ST_CB_ACCUM_H -#include "main/mtypes.h" +#include "main/mfeatures.h" + +struct dd_function_table; +struct gl_context; +struct gl_renderbuffer; #if FEATURE_accum diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index f08697fe23b..516346c8c7a 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -185,48 +185,47 @@ find_free_bit(uint bitfield) /** * Combine basic bitmap fragment program with the user-defined program. + * \param st current context + * \param fpIn the incoming fragment program + * \param fpOut the new fragment program which does fragment culling + * \param bitmap_sampler sampler number for the bitmap texture */ -static struct st_fragment_program * -combined_bitmap_fragment_program(struct gl_context *ctx) +void +st_make_bitmap_fragment_program(struct st_context *st, + struct gl_fragment_program *fpIn, + struct gl_fragment_program **fpOut, + GLuint *bitmap_sampler) { - struct st_context *st = st_context(ctx); - struct st_fragment_program *stfp = st->fp; - - if (!stfp->bitmap_program) { - /* - * Generate new program which is the user-defined program prefixed - * with the bitmap sampler/kill instructions. - */ - struct st_fragment_program *bitmap_prog; - uint sampler; - - sampler = find_free_bit(st->fp->Base.Base.SamplersUsed); - bitmap_prog = make_bitmap_fragment_program(ctx, sampler); + struct st_fragment_program *bitmap_prog; + struct gl_program *newProg; + uint sampler; - stfp->bitmap_program = (struct st_fragment_program *) - _mesa_combine_programs(ctx, - &bitmap_prog->Base.Base, &stfp->Base.Base); - stfp->bitmap_program->bitmap_sampler = sampler; + /* + * Generate new program which is the user-defined program prefixed + * with the bitmap sampler/kill instructions. + */ + sampler = find_free_bit(fpIn->Base.SamplersUsed); + bitmap_prog = make_bitmap_fragment_program(st->ctx, sampler); - /* done with this after combining */ - st_reference_fragprog(st, &bitmap_prog, NULL); + newProg = _mesa_combine_programs(st->ctx, + &bitmap_prog->Base.Base, + &fpIn->Base); + /* done with this after combining */ + st_reference_fragprog(st, &bitmap_prog, NULL); #if 0 - { - struct gl_program *p = &stfp->bitmap_program->Base.Base; - printf("Combined bitmap program:\n"); - _mesa_print_program(p); - printf("InputsRead: 0x%x\n", p->InputsRead); - printf("OutputsWritten: 0x%x\n", p->OutputsWritten); - _mesa_print_parameter_list(p->Parameters); - } -#endif - - /* translate to TGSI tokens */ - st_translate_fragment_program(st, stfp->bitmap_program); + { + printf("Combined bitmap program:\n"); + _mesa_print_program(newProg); + printf("InputsRead: 0x%x\n", newProg->InputsRead); + printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten); + _mesa_print_parameter_list(newProg->Parameters); } +#endif - return stfp->bitmap_program; + /* return results */ + *fpOut = (struct gl_fragment_program *) newProg; + *bitmap_sampler = sampler; } @@ -349,7 +348,8 @@ setup_bitmap_vertex_data(struct st_context *st, bool normalized, if (!st->bitmap.vbuf) { st->bitmap.vbuf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER, - max_slots * sizeof(st->bitmap.vertices)); + max_slots * + sizeof(st->bitmap.vertices)); } /* Positions are in clip coords since we need to do clipping in case @@ -389,10 +389,11 @@ setup_bitmap_vertex_data(struct st_context *st, bool normalized, /* put vertex data into vbuf */ pipe_buffer_write_nooverlap(st->pipe, - st->bitmap.vbuf, - st->bitmap.vbuf_slot * sizeof st->bitmap.vertices, - sizeof st->bitmap.vertices, - st->bitmap.vertices); + st->bitmap.vbuf, + st->bitmap.vbuf_slot + * sizeof(st->bitmap.vertices), + sizeof st->bitmap.vertices, + st->bitmap.vertices); return st->bitmap.vbuf_slot++ * sizeof st->bitmap.vertices; } @@ -411,11 +412,16 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; struct cso_context *cso = st->cso_context; - struct st_fragment_program *stfp; + struct st_fp_variant *fpv; + struct st_fp_variant_key key; GLuint maxSize; GLuint offset; - stfp = combined_bitmap_fragment_program(ctx); + memset(&key, 0, sizeof(key)); + key.st = st; + key.bitmap = GL_TRUE; + + fpv = st_get_fp_variant(st, st->fp, &key); /* As an optimization, Mesa's fragment programs will sometimes get the * primary color from a statevar/constant rather than a varying variable. @@ -428,7 +434,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, GLfloat colorSave[4]; COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color); - st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT); + st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave); } @@ -437,7 +443,8 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, /* XXX if the bitmap is larger than the max texture size, break * it up into chunks. */ - maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); + maxSize = 1 << (pipe->screen->get_param(pipe->screen, + PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1); assert(width <= (GLsizei)maxSize); assert(height <= (GLsizei)maxSize); @@ -454,7 +461,7 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, cso_set_rasterizer(cso, &st->bitmap.rasterizer); /* fragment shader state: TEX lookup program */ - cso_set_fragment_shader_handle(cso, stfp->driver_shader); + cso_set_fragment_shader_handle(cso, fpv->driver_shader); /* vertex shader state: position + texcoord pass-through */ cso_set_vertex_shader_handle(cso, st->bitmap.vs); @@ -462,21 +469,22 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, /* user samplers, plus our bitmap sampler */ { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; - uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_samplers); + uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_samplers); uint i; for (i = 0; i < st->state.num_samplers; i++) { samplers[i] = &st->state.samplers[i]; } - samplers[stfp->bitmap_sampler] = &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT]; + samplers[fpv->bitmap_sampler] = + &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT]; cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers); } /* user textures, plus the bitmap texture */ { struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; - uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_textures); + uint num = MAX2(fpv->bitmap_sampler + 1, st->state.num_textures); memcpy(sampler_views, st->state.sampler_views, sizeof(sampler_views)); - sampler_views[stfp->bitmap_sampler] = sv; + sampler_views[fpv->bitmap_sampler] = sv; cso_set_fragment_sampler_views(cso, num, sampler_views); } @@ -504,7 +512,9 @@ draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z, z = z * 2.0 - 1.0; /* draw textured quad */ - offset = setup_bitmap_vertex_data(st, sv->texture->target != PIPE_TEXTURE_RECT, x, y, width, height, z, color); + offset = setup_bitmap_vertex_data(st, + sv->texture->target != PIPE_TEXTURE_RECT, + x, y, width, height, z, color); util_draw_vertex_buffer(pipe, st->bitmap.vbuf, offset, PIPE_PRIM_TRIANGLE_FAN, @@ -573,6 +583,9 @@ print_cache(const struct bitmap_cache *cache) } +/** + * Create gallium pipe_transfer object for the bitmap cache. + */ static void create_cache_trans(struct st_context *st) { @@ -651,7 +664,9 @@ st_flush_bitmap_cache(struct st_context *st) } } -/* Flush bitmap cache and release vertex buffer. + +/** + * Flush bitmap cache and release vertex buffer. */ void st_flush_bitmap( struct st_context *st ) @@ -737,7 +752,8 @@ accum_bitmap(struct st_context *st, * Called via ctx->Driver.Bitmap() */ static void -st_Bitmap(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height, +st_Bitmap(struct gl_context *ctx, GLint x, GLint y, + GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap ) { struct st_context *st = st_context(ctx); @@ -764,7 +780,8 @@ st_Bitmap(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei heigh pt = make_bitmap_texture(ctx, width, height, unpack, bitmap); if (pt) { - struct pipe_sampler_view *sv = st_create_texture_sampler_view(st->pipe, pt); + struct pipe_sampler_view *sv = + st_create_texture_sampler_view(st->pipe, pt); assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT); @@ -814,15 +831,18 @@ st_init_bitmap(struct st_context *st) st->bitmap.rasterizer.gl_rasterization_rules = 1; /* find a usable texture format */ - if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, PIPE_TEXTURE_2D, 0, + if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, + PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW, 0)) { st->bitmap.tex_format = PIPE_FORMAT_I8_UNORM; } - else if (screen->is_format_supported(screen, PIPE_FORMAT_A8_UNORM, PIPE_TEXTURE_2D, 0, + else if (screen->is_format_supported(screen, PIPE_FORMAT_A8_UNORM, + PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW, 0)) { st->bitmap.tex_format = PIPE_FORMAT_A8_UNORM; } - else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM, PIPE_TEXTURE_2D, 0, + else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM, + PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW, 0)) { st->bitmap.tex_format = PIPE_FORMAT_L8_UNORM; } @@ -845,8 +865,6 @@ st_destroy_bitmap(struct st_context *st) struct pipe_context *pipe = st->pipe; struct bitmap_cache *cache = st->bitmap.cache; - - if (st->bitmap.vs) { cso_delete_vertex_shader(st->cso_context, st->bitmap.vs); st->bitmap.vs = NULL; diff --git a/src/mesa/state_tracker/st_cb_bitmap.h b/src/mesa/state_tracker/st_cb_bitmap.h index d04b2b67795..2bd63b9b741 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.h +++ b/src/mesa/state_tracker/st_cb_bitmap.h @@ -34,6 +34,8 @@ struct dd_function_table; struct st_context; +struct gl_fragment_program; +struct st_fragment_program; #if FEATURE_drawpix @@ -47,6 +49,12 @@ extern void st_destroy_bitmap(struct st_context *st); extern void +st_make_bitmap_fragment_program(struct st_context *st, + struct gl_fragment_program *fpIn, + struct gl_fragment_program **fpOut, + GLuint *bitmap_sampler); + +extern void st_flush_bitmap_cache(struct st_context *st); /* Flush bitmap cache and release vertex buffer. Needed at end of diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.c b/src/mesa/state_tracker/st_cb_bufferobjects.c index 8b60f9040d0..d4d9af4ada3 100644 --- a/src/mesa/state_tracker/st_cb_bufferobjects.c +++ b/src/mesa/state_tracker/st_cb_bufferobjects.c @@ -360,7 +360,7 @@ st_bufferobj_unmap(struct gl_context *ctx, GLenum target, struct gl_buffer_objec struct st_buffer_object *st_obj = st_buffer_object(obj); if (obj->Length) - pipe_buffer_unmap(pipe, st_obj->buffer, st_obj->transfer); + pipe_buffer_unmap(pipe, st_obj->transfer); st_obj->transfer = NULL; obj->Pointer = NULL; @@ -409,8 +409,8 @@ st_copy_buffer_subdata(struct gl_context *ctx, if (srcPtr && dstPtr) memcpy(dstPtr + writeOffset, srcPtr + readOffset, size); - pipe_buffer_unmap(pipe, srcObj->buffer, src_transfer); - pipe_buffer_unmap(pipe, dstObj->buffer, dst_transfer); + pipe_buffer_unmap(pipe, src_transfer); + pipe_buffer_unmap(pipe, dst_transfer); } diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index c9786024575..1fc47688e4a 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -94,88 +94,61 @@ is_passthrough_program(const struct gl_fragment_program *prog) /** * Make fragment shader for glDraw/CopyPixels. This shader is made * by combining the pixel transfer shader with the user-defined shader. - * \return pointer to Gallium driver fragment shader + * \param fpIn the current/incoming fragment program + * \param fpOut returns the combined fragment program */ -static void * -combined_drawpix_fragment_program(struct gl_context *ctx) +void +st_make_drawpix_fragment_program(struct st_context *st, + struct gl_fragment_program *fpIn, + struct gl_fragment_program **fpOut) { - struct st_context *st = st_context(ctx); - struct st_fragment_program *stfp; + struct gl_program *newProg; - if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn - && st->fp->serialNo == st->pixel_xfer.user_prog_sn) { - /* the pixel tranfer program has not changed and the user-defined - * program has not changed, so re-use the combined program. - */ - stfp = st->pixel_xfer.combined_prog; + if (is_passthrough_program(fpIn)) { + newProg = (struct gl_program *) _mesa_clone_fragment_program(st->ctx, + &st->pixel_xfer.program->Base); } else { - /* Concatenate the pixel transfer program with the current user- - * defined program. - */ - if (is_passthrough_program(&st->fp->Base)) { - stfp = (struct st_fragment_program *) - _mesa_clone_fragment_program(ctx, &st->pixel_xfer.program->Base); - } - else { #if 0 - printf("Base program:\n"); - _mesa_print_program(&st->fp->Base.Base); - printf("DrawPix program:\n"); - _mesa_print_program(&st->pixel_xfer.program->Base.Base); + /* debug */ + printf("Base program:\n"); + _mesa_print_program(&fpIn->Base); + printf("DrawPix program:\n"); + _mesa_print_program(&st->pixel_xfer.program->Base.Base); #endif - stfp = (struct st_fragment_program *) - _mesa_combine_programs(ctx, - &st->pixel_xfer.program->Base.Base, - &st->fp->Base.Base); - } + newProg = _mesa_combine_programs(st->ctx, + &st->pixel_xfer.program->Base.Base, + &fpIn->Base); + } #if 0 - { - struct gl_program *p = &stfp->Base.Base; - printf("Combined DrawPixels program:\n"); - _mesa_print_program(p); - printf("InputsRead: 0x%x\n", p->InputsRead); - printf("OutputsWritten: 0x%x\n", p->OutputsWritten); - _mesa_print_parameter_list(p->Parameters); - } + /* debug */ + printf("Combined DrawPixels program:\n"); + _mesa_print_program(newProg); + printf("InputsRead: 0x%x\n", newProg->InputsRead); + printf("OutputsWritten: 0x%x\n", newProg->OutputsWritten); + _mesa_print_parameter_list(newProg->Parameters); #endif - /* translate to TGSI tokens */ - st_translate_fragment_program(st, stfp); - - /* save new program, update serial numbers */ - st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo; - st->pixel_xfer.user_prog_sn = st->fp->serialNo; - st->pixel_xfer.combined_prog_sn = stfp->serialNo; - /* can't reference new program directly, already have a reference on it */ - st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL); - st->pixel_xfer.combined_prog = stfp; - } - - /* Ideally we'd have updated the pipe constants during the normal - * st/atom mechanism. But we can't since this is specific to glDrawPixels. - */ - st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT); - - return stfp->driver_shader; + *fpOut = (struct gl_fragment_program *) newProg; } /** - * Create fragment shader that does a TEX() instruction to get a Z and/or + * Create fragment program that does a TEX() instruction to get a Z and/or * stencil value value, then writes to FRAG_RESULT_DEPTH/FRAG_RESULT_STENCIL. * Used for glDrawPixels(GL_DEPTH_COMPONENT / GL_STENCIL_INDEX). * Pass fragment color through as-is. - * \return pointer to the Gallium driver fragment shader + * \return pointer to the gl_fragment program */ -static void * -make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth, - GLboolean write_stencil) +struct gl_fragment_program * +st_make_drawpix_z_stencil_program(struct st_context *st, + GLboolean write_depth, + GLboolean write_stencil) { struct gl_context *ctx = st->ctx; struct gl_program *p; - struct st_fragment_program *stp; + struct gl_fragment_program *fp; GLuint ic = 0; const GLuint shaderIndex = write_depth * 2 + write_stencil; @@ -183,7 +156,7 @@ make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth, if (st->drawpix.shaders[shaderIndex]) { /* already have the proper shader */ - return st->drawpix.shaders[shaderIndex]->driver_shader; + return st->drawpix.shaders[shaderIndex]; } /* @@ -245,18 +218,15 @@ make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth, if (write_stencil) p->SamplersUsed |= 1 << 1; - stp = st_fragment_program((struct gl_fragment_program *) p); + fp = (struct gl_fragment_program *) p; /* save the new shader */ - st->drawpix.shaders[shaderIndex] = stp; + st->drawpix.shaders[shaderIndex] = fp; - st_translate_fragment_program(st, stp); - - return stp->driver_shader; + return fp; } - /** * Create a simple vertex shader that just passes through the * vertex position and texcoord (and optionally, color). @@ -873,6 +843,61 @@ draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, /** + * Get fragment program variant for a glDrawPixels or glCopyPixels + * command for RGBA data. + */ +static struct st_fp_variant * +get_color_fp_variant(struct st_context *st) +{ + struct gl_context *ctx = st->ctx; + struct st_fp_variant_key key; + struct st_fp_variant *fpv; + + memset(&key, 0, sizeof(key)); + + key.st = st; + key.drawpixels = 1; + key.scaleAndBias = (ctx->Pixel.RedBias != 0.0 || + ctx->Pixel.RedScale != 1.0 || + ctx->Pixel.GreenBias != 0.0 || + ctx->Pixel.GreenScale != 1.0 || + ctx->Pixel.BlueBias != 0.0 || + ctx->Pixel.BlueScale != 1.0 || + ctx->Pixel.AlphaBias != 0.0 || + ctx->Pixel.AlphaScale != 1.0); + key.pixelMaps = ctx->Pixel.MapColorFlag; + + fpv = st_get_fp_variant(st, st->fp, &key); + + return fpv; +} + + +/** + * Get fragment program variant for a glDrawPixels or glCopyPixels + * command for depth/stencil data. + */ +static struct st_fp_variant * +get_depth_stencil_fp_variant(struct st_context *st, GLboolean write_depth, + GLboolean write_stencil) +{ + struct st_fp_variant_key key; + struct st_fp_variant *fpv; + + memset(&key, 0, sizeof(key)); + + key.st = st; + key.drawpixels = 1; + key.drawpixels_z = write_depth; + key.drawpixels_stencil = write_stencil; + + fpv = st_get_fp_variant(st, st->fp, &key); + + return fpv; +} + + +/** * Called via ctx->Driver.DrawPixels() */ static void @@ -889,6 +914,7 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y, struct pipe_sampler_view *sv[2]; int num_sampler_view = 1; enum pipe_format stencil_format = PIPE_FORMAT_NONE; + struct st_fp_variant *fpv; if (format == GL_DEPTH_STENCIL) write_stencil = write_depth = GL_TRUE; @@ -921,14 +947,25 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y, st_validate_state(st); + /* + * Get vertex/fragment shaders + */ if (write_depth || write_stencil) { - driver_fp = make_fragment_shader_z_stencil(st, write_depth, write_stencil); + fpv = get_depth_stencil_fp_variant(st, write_depth, write_stencil); + + driver_fp = fpv->driver_shader; + driver_vp = make_passthrough_vertex_shader(st, GL_TRUE); + color = ctx->Current.RasterColor; } else { - driver_fp = combined_drawpix_fragment_program(ctx); + fpv = get_color_fp_variant(st); + + driver_fp = fpv->driver_shader; + driver_vp = make_passthrough_vertex_shader(st, GL_FALSE); + color = NULL; if (st->pixel_xfer.pixelmap_enabled) { sv[1] = st->pixel_xfer.pixelmap_sampler_view; @@ -936,6 +973,9 @@ st_DrawPixels(struct gl_context *ctx, GLint x, GLint y, } } + /* update fragment program constants */ + st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); + /* draw with textured quad */ { struct pipe_resource *pt @@ -1116,6 +1156,7 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, GLint readX, readY, readW, readH; GLuint sample_count; struct gl_pixelstore_attrib pack = ctx->DefaultPacking; + struct st_fp_variant *fpv; st_validate_state(st); @@ -1125,11 +1166,18 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, return; } + /* + * Get vertex/fragment shaders + */ if (type == GL_COLOR) { rbRead = st_get_color_read_renderbuffer(ctx); color = NULL; - driver_fp = combined_drawpix_fragment_program(ctx); + + fpv = get_color_fp_variant(st); + driver_fp = fpv->driver_shader; + driver_vp = make_passthrough_vertex_shader(st, GL_FALSE); + if (st->pixel_xfer.pixelmap_enabled) { sv[1] = st->pixel_xfer.pixelmap_sampler_view; num_sampler_view++; @@ -1139,10 +1187,17 @@ st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy, assert(type == GL_DEPTH); rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer); color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; - driver_fp = make_fragment_shader_z_stencil(st, GL_TRUE, GL_FALSE); + + fpv = get_depth_stencil_fp_variant(st, GL_TRUE, GL_FALSE); + driver_fp = fpv->driver_shader; + driver_vp = make_passthrough_vertex_shader(st, GL_TRUE); } + /* update fragment program constants */ + st_upload_constants(st, fpv->parameters, PIPE_SHADER_FRAGMENT); + + if (rbRead->Base.Wrapped) rbRead = st_renderbuffer(rbRead->Base.Wrapped); @@ -1294,7 +1349,7 @@ st_destroy_drawpix(struct st_context *st) for (i = 0; i < Elements(st->drawpix.shaders); i++) { if (st->drawpix.shaders[i]) - st_reference_fragprog(st, &st->drawpix.shaders[i], NULL); + _mesa_reference_fragprog(st->ctx, &st->drawpix.shaders[i], NULL); } st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL); diff --git a/src/mesa/state_tracker/st_cb_drawpixels.h b/src/mesa/state_tracker/st_cb_drawpixels.h index 575f169e08e..8f73e626240 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.h +++ b/src/mesa/state_tracker/st_cb_drawpixels.h @@ -42,6 +42,16 @@ extern void st_init_drawpixels_functions(struct dd_function_table *functions); extern void st_destroy_drawpix(struct st_context *st); +extern void +st_make_drawpix_fragment_program(struct st_context *st, + struct gl_fragment_program *fpIn, + struct gl_fragment_program **fpOut); + +extern struct gl_fragment_program * +st_make_drawpix_z_stencil_program(struct st_context *st, + GLboolean write_depth, + GLboolean write_stencil); + #else static INLINE void diff --git a/src/mesa/state_tracker/st_cb_drawtex.c b/src/mesa/state_tracker/st_cb_drawtex.c index 6cad7d3216e..22a5ed425e5 100644 --- a/src/mesa/state_tracker/st_cb_drawtex.c +++ b/src/mesa/state_tracker/st_cb_drawtex.c @@ -220,7 +220,7 @@ st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, } } - pipe_buffer_unmap(pipe, vbuffer, vbuffer_transfer); + pipe_buffer_unmap(pipe, vbuffer_transfer); #undef SET_ATTRIB } diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c index 4d83fcc6ccb..32694975d17 100644 --- a/src/mesa/state_tracker/st_cb_program.c +++ b/src/mesa/state_tracker/st_cb_program.c @@ -46,16 +46,13 @@ #include "st_cb_program.h" -static GLuint SerialNo = 1; - /** * Called via ctx->Driver.BindProgram() to bind an ARB vertex or * fragment program. */ -static void st_bind_program( struct gl_context *ctx, - GLenum target, - struct gl_program *prog ) +static void +st_bind_program(struct gl_context *ctx, GLenum target, struct gl_program *prog) { struct st_context *st = st_context(ctx); @@ -77,7 +74,8 @@ static void st_bind_program( struct gl_context *ctx, * Called via ctx->Driver.UseProgram() to bind a linked GLSL program * (vertex shader + fragment shader). */ -static void st_use_program( struct gl_context *ctx, struct gl_shader_program *shProg) +static void +st_use_program(struct gl_context *ctx, struct gl_shader_program *shProg) { struct st_context *st = st_context(ctx); @@ -87,48 +85,28 @@ static void st_use_program( struct gl_context *ctx, struct gl_shader_program *sh } - /** * Called via ctx->Driver.NewProgram() to allocate a new vertex or * fragment program. */ -static struct gl_program *st_new_program( struct gl_context *ctx, - GLenum target, - GLuint id ) +static struct gl_program * +st_new_program(struct gl_context *ctx, GLenum target, GLuint id) { switch (target) { case GL_VERTEX_PROGRAM_ARB: { struct st_vertex_program *prog = ST_CALLOC_STRUCT(st_vertex_program); - - prog->serialNo = SerialNo++; - - return _mesa_init_vertex_program( ctx, - &prog->Base, - target, - id ); + return _mesa_init_vertex_program(ctx, &prog->Base, target, id); } case GL_FRAGMENT_PROGRAM_ARB: case GL_FRAGMENT_PROGRAM_NV: { struct st_fragment_program *prog = ST_CALLOC_STRUCT(st_fragment_program); - - prog->serialNo = SerialNo++; - - return _mesa_init_fragment_program( ctx, - &prog->Base, - target, - id ); + return _mesa_init_fragment_program(ctx, &prog->Base, target, id); } case MESA_GEOMETRY_PROGRAM: { struct st_geometry_program *prog = ST_CALLOC_STRUCT(st_geometry_program); - - prog->serialNo = SerialNo++; - - return _mesa_init_geometry_program( ctx, - &prog->Base, - target, - id ); + return _mesa_init_geometry_program(ctx, &prog->Base, target, id); } default: @@ -138,7 +116,10 @@ static struct gl_program *st_new_program( struct gl_context *ctx, } -void +/** + * Called via ctx->Driver.DeleteProgram() + */ +static void st_delete_program(struct gl_context *ctx, struct gl_program *prog) { struct st_context *st = st_context(ctx); @@ -147,17 +128,15 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog) case GL_VERTEX_PROGRAM_ARB: { struct st_vertex_program *stvp = (struct st_vertex_program *) prog; - st_vp_release_varients( st, stvp ); + st_release_vp_variants( st, stvp ); } break; case MESA_GEOMETRY_PROGRAM: { - struct st_geometry_program *stgp = (struct st_geometry_program *) prog; + struct st_geometry_program *stgp = + (struct st_geometry_program *) prog; - if (stgp->driver_shader) { - cso_delete_geometry_shader(st->cso_context, stgp->driver_shader); - stgp->driver_shader = NULL; - } + st_release_gp_variants(st, stgp); if (stgp->tgsi.tokens) { st_free_tokens((void *) stgp->tgsi.tokens); @@ -167,23 +146,15 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog) break; case GL_FRAGMENT_PROGRAM_ARB: { - struct st_fragment_program *stfp = (struct st_fragment_program *) prog; + struct st_fragment_program *stfp = + (struct st_fragment_program *) prog; - if (stfp->driver_shader) { - cso_delete_fragment_shader(st->cso_context, stfp->driver_shader); - stfp->driver_shader = NULL; - } + st_release_fp_variants(st, stfp); if (stfp->tgsi.tokens) { st_free_tokens(stfp->tgsi.tokens); stfp->tgsi.tokens = NULL; } - - if (stfp->bitmap_program) { - struct gl_program *prg = &stfp->bitmap_program->Base.Base; - _mesa_reference_program(ctx, &prg, NULL); - stfp->bitmap_program = NULL; - } } break; default: @@ -195,15 +166,25 @@ st_delete_program(struct gl_context *ctx, struct gl_program *prog) } -static GLboolean st_is_program_native( struct gl_context *ctx, - GLenum target, - struct gl_program *prog ) +/** + * Called via ctx->Driver.IsProgramNative() + */ +static GLboolean +st_is_program_native(struct gl_context *ctx, + GLenum target, + struct gl_program *prog) { return GL_TRUE; } -static GLboolean st_program_string_notify( struct gl_context *ctx, +/** + * Called via ctx->Driver.ProgramStringNotify() + * Called when the program's text/code is changed. We have to free + * all shader variants and corresponding gallium shaders when this happens. + */ +static GLboolean +st_program_string_notify( struct gl_context *ctx, GLenum target, struct gl_program *prog ) { @@ -212,12 +193,7 @@ static GLboolean st_program_string_notify( struct gl_context *ctx, if (target == GL_FRAGMENT_PROGRAM_ARB) { struct st_fragment_program *stfp = (struct st_fragment_program *) prog; - stfp->serialNo++; - - if (stfp->driver_shader) { - cso_delete_fragment_shader(st->cso_context, stfp->driver_shader); - stfp->driver_shader = NULL; - } + st_release_fp_variants(st, stfp); if (stfp->tgsi.tokens) { st_free_tokens(stfp->tgsi.tokens); @@ -230,12 +206,7 @@ static GLboolean st_program_string_notify( struct gl_context *ctx, else if (target == MESA_GEOMETRY_PROGRAM) { struct st_geometry_program *stgp = (struct st_geometry_program *) prog; - stgp->serialNo++; - - if (stgp->driver_shader) { - cso_delete_geometry_shader(st->cso_context, stgp->driver_shader); - stgp->driver_shader = NULL; - } + st_release_gp_variants(st, stgp); if (stgp->tgsi.tokens) { st_free_tokens((void *) stgp->tgsi.tokens); @@ -248,9 +219,7 @@ static GLboolean st_program_string_notify( struct gl_context *ctx, else if (target == GL_VERTEX_PROGRAM_ARB) { struct st_vertex_program *stvp = (struct st_vertex_program *) prog; - stvp->serialNo++; - - st_vp_release_varients( st, stvp ); + st_release_vp_variants( st, stvp ); if (st->vp == stvp) st->dirty.st |= ST_NEW_VERTEX_PROGRAM; @@ -261,8 +230,11 @@ static GLboolean st_program_string_notify( struct gl_context *ctx, } - -void st_init_program_functions(struct dd_function_table *functions) +/** + * Plug in the program and shader-related device driver functions. + */ +void +st_init_program_functions(struct dd_function_table *functions) { functions->BindProgram = st_bind_program; functions->UseProgram = st_use_program; diff --git a/src/mesa/state_tracker/st_cb_program.h b/src/mesa/state_tracker/st_cb_program.h index 004afb6d812..091a4439c48 100644 --- a/src/mesa/state_tracker/st_cb_program.h +++ b/src/mesa/state_tracker/st_cb_program.h @@ -29,15 +29,10 @@ #define ST_CB_PROGRAM_H -#include "main/mtypes.h" - struct dd_function_table; extern void st_init_program_functions(struct dd_function_table *functions); -extern void -st_delete_program(struct gl_context *ctx, struct gl_program *prog); - #endif diff --git a/src/mesa/state_tracker/st_cb_readpixels.h b/src/mesa/state_tracker/st_cb_readpixels.h index 83c9b659e3d..9622ae6feea 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.h +++ b/src/mesa/state_tracker/st_cb_readpixels.h @@ -29,9 +29,11 @@ #ifndef ST_CB_READPIXELS_H #define ST_CB_READPIXELS_H -#include "main/mtypes.h" +#include "main/glheader.h" struct dd_function_table; +struct gl_context; +struct gl_pixelstore_attrib; extern struct st_renderbuffer * st_get_color_read_renderbuffer(struct gl_context *ctx); diff --git a/src/mesa/state_tracker/st_cb_texture.h b/src/mesa/state_tracker/st_cb_texture.h index 60987055eb1..f1502bda788 100644 --- a/src/mesa/state_tracker/st_cb_texture.h +++ b/src/mesa/state_tracker/st_cb_texture.h @@ -31,9 +31,10 @@ #include "main/glheader.h" -#include "main/mtypes.h" struct dd_function_table; +struct gl_context; +struct gl_texture_object; struct pipe_context; struct st_context; diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index 6ec9c699a26..21bb91f47a8 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -252,6 +252,8 @@ void st_destroy_context( struct st_context *st ) _vbo_DestroyContext(st->ctx); + st_destroy_program_variants(st); + _mesa_free_context_data(ctx); st_destroy_context_priv(st); diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index d342c0cff1e..1fd80053c1b 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -1,4 +1,3 @@ -//struct dd_function_table; /************************************************************************** * * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. @@ -130,7 +129,9 @@ struct st_context struct st_fragment_program *fp; /**< Currently bound fragment program */ struct st_geometry_program *gp; /**< Currently bound geometry program */ - struct st_vp_varient *vp_varient; + struct st_vp_variant *vp_variant; + struct st_fp_variant *fp_variant; + struct st_gp_variant *gp_variant; struct gl_texture_object *default_texture; @@ -160,7 +161,7 @@ struct st_context /** for glDraw/CopyPixels */ struct { - struct st_fragment_program *shaders[4]; + struct gl_fragment_program *shaders[4]; void *vert_shaders[2]; /**< ureg shaders */ } drawpix; diff --git a/src/mesa/state_tracker/st_debug.c b/src/mesa/state_tracker/st_debug.c index df32491d044..e1e373d07d4 100644 --- a/src/mesa/state_tracker/st_debug.c +++ b/src/mesa/state_tracker/st_debug.c @@ -89,8 +89,8 @@ st_print_current(void) } #endif - if (st->vp->varients) - tgsi_dump( st->vp->varients[0].tgsi.tokens, 0 ); + if (st->vp->variants) + tgsi_dump( st->vp->variants[0].tgsi.tokens, 0 ); if (st->vp->Base.Base.Parameters) _mesa_print_parameter_list(st->vp->Base.Base.Parameters); diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 61a0e1b0877..f4bf1802390 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -241,7 +241,7 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, */ static GLboolean is_interleaved_arrays(const struct st_vertex_program *vp, - const struct st_vp_varient *vpv, + const struct st_vp_variant *vpv, const struct gl_client_array **arrays, GLboolean *userSpace) { @@ -297,7 +297,7 @@ is_interleaved_arrays(const struct st_vertex_program *vp, */ static void get_arrays_bounds(const struct st_vertex_program *vp, - const struct st_vp_varient *vpv, + const struct st_vp_variant *vpv, const struct gl_client_array **arrays, GLuint max_index, const GLubyte **low, const GLubyte **high) @@ -343,7 +343,7 @@ get_arrays_bounds(const struct st_vertex_program *vp, static void setup_interleaved_attribs(struct gl_context *ctx, const struct st_vertex_program *vp, - const struct st_vp_varient *vpv, + const struct st_vp_variant *vpv, const struct gl_client_array **arrays, GLuint max_index, GLboolean userSpace, @@ -409,7 +409,7 @@ setup_interleaved_attribs(struct gl_context *ctx, static void setup_non_interleaved_attribs(struct gl_context *ctx, const struct st_vertex_program *vp, - const struct st_vp_varient *vpv, + const struct st_vp_variant *vpv, const struct gl_client_array **arrays, GLuint max_index, GLboolean *userSpace, @@ -617,7 +617,7 @@ st_draw_vbo(struct gl_context *ctx, struct st_context *st = st_context(ctx); struct pipe_context *pipe = st->pipe; const struct st_vertex_program *vp; - const struct st_vp_varient *vpv; + const struct st_vp_variant *vpv; struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS]; GLuint attr; struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; @@ -650,7 +650,7 @@ st_draw_vbo(struct gl_context *ctx, /* must get these after state validation! */ vp = st->vp; - vpv = st->vp_varient; + vpv = st->vp_variant; #if 0 if (MESA_VERBOSE & VERBOSE_GLSL) { diff --git a/src/mesa/state_tracker/st_draw.h b/src/mesa/state_tracker/st_draw.h index 2e4c468cff5..5d3c278228f 100644 --- a/src/mesa/state_tracker/st_draw.h +++ b/src/mesa/state_tracker/st_draw.h @@ -36,10 +36,11 @@ #include "main/compiler.h" #include "main/glheader.h" -#include "main/mtypes.h" struct _mesa_index_buffer; struct _mesa_prim; +struct gl_client_array; +struct gl_context; struct st_context; void st_init_draw( struct st_context *st ); diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c index 7f392fc4916..da67c713710 100644 --- a/src/mesa/state_tracker/st_draw_feedback.c +++ b/src/mesa/state_tracker/st_draw_feedback.c @@ -123,10 +123,10 @@ st_feedback_draw_vbo(struct gl_context *ctx, /* must get these after state validation! */ vp = st->vp; - vs = &st->vp_varient->tgsi; + vs = &st->vp_variant->tgsi; - if (!st->vp_varient->draw_shader) { - st->vp_varient->draw_shader = draw_create_vertex_shader(draw, vs); + if (!st->vp_variant->draw_shader) { + st->vp_variant->draw_shader = draw_create_vertex_shader(draw, vs); } /* @@ -139,7 +139,7 @@ st_feedback_draw_vbo(struct gl_context *ctx, draw_set_viewport_state(draw, &st->state.viewport); draw_set_clip_state(draw, &st->state.clip); draw_set_rasterizer_state(draw, &st->state.rasterizer, NULL); - draw_bind_vertex_shader(draw, st->vp_varient->draw_shader); + draw_bind_vertex_shader(draw, st->vp_variant->draw_shader); set_feedback_vertex_format(ctx); /* loop over TGSI shader inputs to determine vertex buffer @@ -259,16 +259,14 @@ st_feedback_draw_vbo(struct gl_context *ctx, /* unmap constant buffers */ - pipe_buffer_unmap(pipe, st->state.constants[PIPE_SHADER_VERTEX], - cb_transfer); + pipe_buffer_unmap(pipe, cb_transfer); /* * unmap vertex/index buffers */ for (i = 0; i < PIPE_MAX_ATTRIBS; i++) { if (draw->pt.vertex_buffer[i].buffer) { - pipe_buffer_unmap(pipe, draw->pt.vertex_buffer[i].buffer, - vb_transfer[i]); + pipe_buffer_unmap(pipe, vb_transfer[i]); pipe_resource_reference(&draw->pt.vertex_buffer[i].buffer, NULL); draw_set_mapped_vertex_buffer(draw, i, NULL); } @@ -279,7 +277,7 @@ st_feedback_draw_vbo(struct gl_context *ctx, draw_set_index_buffer(draw, NULL); if (ib_transfer) - pipe_buffer_unmap(pipe, ibuffer.buffer, ib_transfer); + pipe_buffer_unmap(pipe, ib_transfer); pipe_resource_reference(&ibuffer.buffer, NULL); } } diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 930b60ade2d..62c9ce7273d 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -343,6 +343,7 @@ void st_init_extensions(struct st_context *st) if (screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY)) { ctx->Extensions.ARB_occlusion_query = GL_TRUE; + ctx->Extensions.ARB_occlusion_query2 = GL_TRUE; } if (screen->get_param(screen, PIPE_CAP_TIMER_QUERY)) { ctx->Extensions.EXT_timer_query = GL_TRUE; @@ -442,7 +443,9 @@ void st_init_extensions(struct st_context *st) #endif if (screen->get_shader_param(screen, PIPE_SHADER_GEOMETRY, PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) { +#if 0 /* XXX re-enable when GLSL compiler again supports geometry shaders */ ctx->Extensions.ARB_geometry_shader4 = GL_TRUE; +#endif } if (screen->get_param(screen, PIPE_CAP_PRIMITIVE_RESTART)) { diff --git a/src/mesa/state_tracker/st_format.h b/src/mesa/state_tracker/st_format.h index 43fa59b1006..fe195c1069b 100644 --- a/src/mesa/state_tracker/st_format.h +++ b/src/mesa/state_tracker/st_format.h @@ -31,11 +31,12 @@ #define ST_FORMAT_H #include "main/formats.h" -#include "main/mtypes.h" +#include "main/glheader.h" #include "pipe/p_defines.h" #include "pipe/p_format.h" +struct gl_context; struct pipe_screen; extern GLenum diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index aae2913c202..cfdc96b9dbe 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -32,7 +32,9 @@ #include "main/imports.h" +#include "main/hash.h" #include "main/mtypes.h" +#include "program/prog_parameter.h" #include "program/prog_print.h" #include "program/programopt.h" @@ -44,6 +46,8 @@ #include "tgsi/tgsi_ureg.h" #include "st_debug.h" +#include "st_cb_bitmap.h" +#include "st_cb_drawpixels.h" #include "st_context.h" #include "st_program.h" #include "st_mesa_to_tgsi.h" @@ -52,34 +56,109 @@ /** + * Delete a vertex program variant. Note the caller must unlink + * the variant from the linked list. + */ +static void +delete_vp_variant(struct st_context *st, struct st_vp_variant *vpv) +{ + if (vpv->driver_shader) + cso_delete_vertex_shader(st->cso_context, vpv->driver_shader); + +#if FEATURE_feedback || FEATURE_rastpos + if (vpv->draw_shader) + draw_delete_vertex_shader( st->draw, vpv->draw_shader ); +#endif + + if (vpv->tgsi.tokens) + st_free_tokens(vpv->tgsi.tokens); + + FREE( vpv ); +} + + + +/** * Clean out any old compilations: */ void -st_vp_release_varients( struct st_context *st, +st_release_vp_variants( struct st_context *st, struct st_vertex_program *stvp ) { - struct st_vp_varient *vpv; + struct st_vp_variant *vpv; - for (vpv = stvp->varients; vpv; ) { - struct st_vp_varient *next = vpv->next; + for (vpv = stvp->variants; vpv; ) { + struct st_vp_variant *next = vpv->next; + delete_vp_variant(st, vpv); + vpv = next; + } - if (vpv->driver_shader) - cso_delete_vertex_shader(st->cso_context, vpv->driver_shader); - -#if FEATURE_feedback || FEATURE_rastpos - if (vpv->draw_shader) - draw_delete_vertex_shader( st->draw, vpv->draw_shader ); -#endif + stvp->variants = NULL; +} + + + +/** + * Delete a fragment program variant. Note the caller must unlink + * the variant from the linked list. + */ +static void +delete_fp_variant(struct st_context *st, struct st_fp_variant *fpv) +{ + if (fpv->driver_shader) + cso_delete_fragment_shader(st->cso_context, fpv->driver_shader); - if (vpv->tgsi.tokens) - st_free_tokens(vpv->tgsi.tokens); + FREE(fpv); +} + + +/** + * Free all variants of a fragment program. + */ +void +st_release_fp_variants(struct st_context *st, struct st_fragment_program *stfp) +{ + struct st_fp_variant *fpv; + + for (fpv = stfp->variants; fpv; ) { + struct st_fp_variant *next = fpv->next; + delete_fp_variant(st, fpv); + fpv = next; + } + + stfp->variants = NULL; +} + + +/** + * Delete a geometry program variant. Note the caller must unlink + * the variant from the linked list. + */ +static void +delete_gp_variant(struct st_context *st, struct st_gp_variant *gpv) +{ + if (gpv->driver_shader) + cso_delete_geometry_shader(st->cso_context, gpv->driver_shader); - FREE( vpv ); + FREE(gpv); +} - vpv = next; + +/** + * Free all variants of a geometry program. + */ +void +st_release_gp_variants(struct st_context *st, struct st_geometry_program *stgp) +{ + struct st_gp_variant *gpv; + + for (gpv = stgp->variants; gpv; ) { + struct st_gp_variant *next = gpv->next; + delete_gp_variant(st, gpv); + gpv = next; } - stvp->varients = NULL; + stgp->variants = NULL; } @@ -92,7 +171,7 @@ st_vp_release_varients( struct st_context *st, * \param tokensOut destination for TGSI tokens * \return pointer to cached pipe_shader object. */ -void +static void st_prepare_vertex_program(struct st_context *st, struct st_vertex_program *stvp) { @@ -196,17 +275,22 @@ st_prepare_vertex_program(struct st_context *st, } -struct st_vp_varient * +/** + * Translate a vertex program to create a new variant. + */ +static struct st_vp_variant * st_translate_vertex_program(struct st_context *st, struct st_vertex_program *stvp, - const struct st_vp_varient_key *key) + const struct st_vp_variant_key *key) { - struct st_vp_varient *vpv = CALLOC_STRUCT(st_vp_varient); + struct st_vp_variant *vpv = CALLOC_STRUCT(st_vp_variant); struct pipe_context *pipe = st->pipe; struct ureg_program *ureg; enum pipe_error error; unsigned num_outputs; + st_prepare_vertex_program( st, stvp ); + _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT); _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_VARYING); @@ -231,23 +315,22 @@ st_translate_vertex_program(struct st_context *st, debug_printf("\n"); } - error = - st_translate_mesa_program(st->ctx, - TGSI_PROCESSOR_VERTEX, - ureg, - &stvp->Base.Base, - /* inputs */ - vpv->num_inputs, - stvp->input_to_index, - NULL, /* input semantic name */ - NULL, /* input semantic index */ - NULL, - /* outputs */ - num_outputs, - stvp->result_to_output, - stvp->output_semantic_name, - stvp->output_semantic_index, - key->passthrough_edgeflags ); + error = st_translate_mesa_program(st->ctx, + TGSI_PROCESSOR_VERTEX, + ureg, + &stvp->Base.Base, + /* inputs */ + vpv->num_inputs, + stvp->input_to_index, + NULL, /* input semantic name */ + NULL, /* input semantic index */ + NULL, + /* outputs */ + num_outputs, + stvp->result_to_output, + stvp->output_semantic_name, + stvp->output_semantic_index, + key->passthrough_edgeflags ); if (error) goto fail; @@ -277,201 +360,310 @@ fail: } +/** + * Find/create a vertex program variant. + */ +struct st_vp_variant * +st_get_vp_variant(struct st_context *st, + struct st_vertex_program *stvp, + const struct st_vp_variant_key *key) +{ + struct st_vp_variant *vpv; + + /* Search for existing variant */ + for (vpv = stvp->variants; vpv; vpv = vpv->next) { + if (memcmp(&vpv->key, key, sizeof(*key)) == 0) { + break; + } + } + + if (!vpv) { + /* create now */ + vpv = st_translate_vertex_program(st, stvp, key); + if (vpv) { + /* insert into list */ + vpv->next = stvp->variants; + stvp->variants = vpv; + } + } + + return vpv; +} + /** - * Translate a Mesa fragment shader into a TGSI shader. - * \return pointer to cached pipe_shader object. + * Translate a Mesa fragment shader into a TGSI shader using extra info in + * the key. + * \return new fragment program variant */ -void +static struct st_fp_variant * st_translate_fragment_program(struct st_context *st, - struct st_fragment_program *stfp ) + struct st_fragment_program *stfp, + const struct st_fp_variant_key *key) { struct pipe_context *pipe = st->pipe; - GLuint outputMapping[FRAG_RESULT_MAX]; - GLuint inputMapping[FRAG_ATTRIB_MAX]; - GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */ - GLuint attr; - enum pipe_error error; - const GLbitfield inputsRead = stfp->Base.Base.InputsRead; - struct ureg_program *ureg; + struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant); - ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; - ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; - uint fs_num_inputs = 0; + if (!variant) + return NULL; - ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; - ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; - uint fs_num_outputs = 0; + assert(!(key->bitmap && key->drawpixels)); - _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT); + if (key->bitmap) { + /* glBitmap drawing */ + struct gl_fragment_program *fp; - /* - * Convert Mesa program inputs to TGSI input register semantics. - */ - for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) { - if (inputsRead & (1 << attr)) { - const GLuint slot = fs_num_inputs++; + st_make_bitmap_fragment_program(st, &stfp->Base, + &fp, &variant->bitmap_sampler); - inputMapping[attr] = slot; + variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters); + stfp = st_fragment_program(fp); + } + else if (key->drawpixels) { + /* glDrawPixels drawing */ + struct gl_fragment_program *fp; - switch (attr) { - case FRAG_ATTRIB_WPOS: - input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; - input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; - break; - case FRAG_ATTRIB_COL0: - input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; - input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; - break; - case FRAG_ATTRIB_COL1: - input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; - input_semantic_index[slot] = 1; - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; - break; - case FRAG_ATTRIB_FOGC: - input_semantic_name[slot] = TGSI_SEMANTIC_FOG; - input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; - break; - case FRAG_ATTRIB_FACE: - input_semantic_name[slot] = TGSI_SEMANTIC_FACE; - input_semantic_index[slot] = 0; - interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; - break; - /* In most cases, there is nothing special about these - * inputs, so adopt a convention to use the generic - * semantic name and the mesa FRAG_ATTRIB_ number as the - * index. - * - * All that is required is that the vertex shader labels - * its own outputs similarly, and that the vertex shader - * generates at least every output required by the - * fragment shader plus fixed-function hardware (such as - * BFC). - * - * There is no requirement that semantic indexes start at - * zero or be restricted to a particular range -- nobody - * should be building tables based on semantic index. - */ - case FRAG_ATTRIB_PNTC: - case FRAG_ATTRIB_TEX0: - case FRAG_ATTRIB_TEX1: - case FRAG_ATTRIB_TEX2: - case FRAG_ATTRIB_TEX3: - case FRAG_ATTRIB_TEX4: - case FRAG_ATTRIB_TEX5: - case FRAG_ATTRIB_TEX6: - case FRAG_ATTRIB_TEX7: - case FRAG_ATTRIB_VAR0: - default: - /* Actually, let's try and zero-base this just for - * readability of the generated TGSI. - */ - assert(attr >= FRAG_ATTRIB_TEX0); - input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0); - input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; - if (attr == FRAG_ATTRIB_PNTC) - interpMode[slot] = TGSI_INTERPOLATE_LINEAR; - else - interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; - break; - } + if (key->drawpixels_z || key->drawpixels_stencil) { + fp = st_make_drawpix_z_stencil_program(st, key->drawpixels_z, + key->drawpixels_stencil); } else { - inputMapping[attr] = -1; + /* RGBA */ + st_make_drawpix_fragment_program(st, &stfp->Base, &fp); + variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters); } + stfp = st_fragment_program(fp); } - /* - * Semantics and mapping for outputs - */ - { - uint numColors = 0; - GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten; - - /* if z is written, emit that first */ - if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { - fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION; - fs_output_semantic_index[fs_num_outputs] = 0; - outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs; - fs_num_outputs++; - outputsWritten &= ~(1 << FRAG_RESULT_DEPTH); - } + if (!stfp->tgsi.tokens) { + /* need to translate Mesa instructions to TGSI now */ + GLuint outputMapping[FRAG_RESULT_MAX]; + GLuint inputMapping[FRAG_ATTRIB_MAX]; + GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */ + GLuint attr; + enum pipe_error error; + const GLbitfield inputsRead = stfp->Base.Base.InputsRead; + struct ureg_program *ureg; - if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) { - fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL; - fs_output_semantic_index[fs_num_outputs] = 0; - outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs; - fs_num_outputs++; - outputsWritten &= ~(1 << FRAG_RESULT_STENCIL); - } + ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; + ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; + uint fs_num_inputs = 0; + + ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; + ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; + uint fs_num_outputs = 0; + + + _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT); + + /* + * Convert Mesa program inputs to TGSI input register semantics. + */ + for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) { + if (inputsRead & (1 << attr)) { + const GLuint slot = fs_num_inputs++; + + inputMapping[attr] = slot; - /* handle remaning outputs (color) */ - for (attr = 0; attr < FRAG_RESULT_MAX; attr++) { - if (outputsWritten & BITFIELD64_BIT(attr)) { switch (attr) { - case FRAG_RESULT_DEPTH: - case FRAG_RESULT_STENCIL: - /* handled above */ - assert(0); + case FRAG_ATTRIB_WPOS: + input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_LINEAR; + break; + case FRAG_ATTRIB_COL0: + input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_LINEAR; break; + case FRAG_ATTRIB_COL1: + input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; + input_semantic_index[slot] = 1; + interpMode[slot] = TGSI_INTERPOLATE_LINEAR; + break; + case FRAG_ATTRIB_FOGC: + input_semantic_name[slot] = TGSI_SEMANTIC_FOG; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; + break; + case FRAG_ATTRIB_FACE: + input_semantic_name[slot] = TGSI_SEMANTIC_FACE; + input_semantic_index[slot] = 0; + interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; + break; + /* In most cases, there is nothing special about these + * inputs, so adopt a convention to use the generic + * semantic name and the mesa FRAG_ATTRIB_ number as the + * index. + * + * All that is required is that the vertex shader labels + * its own outputs similarly, and that the vertex shader + * generates at least every output required by the + * fragment shader plus fixed-function hardware (such as + * BFC). + * + * There is no requirement that semantic indexes start at + * zero or be restricted to a particular range -- nobody + * should be building tables based on semantic index. + */ + case FRAG_ATTRIB_PNTC: + case FRAG_ATTRIB_TEX0: + case FRAG_ATTRIB_TEX1: + case FRAG_ATTRIB_TEX2: + case FRAG_ATTRIB_TEX3: + case FRAG_ATTRIB_TEX4: + case FRAG_ATTRIB_TEX5: + case FRAG_ATTRIB_TEX6: + case FRAG_ATTRIB_TEX7: + case FRAG_ATTRIB_VAR0: default: - assert(attr == FRAG_RESULT_COLOR || - (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX)); - fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR; - fs_output_semantic_index[fs_num_outputs] = numColors; - outputMapping[attr] = fs_num_outputs; - numColors++; + /* Actually, let's try and zero-base this just for + * readability of the generated TGSI. + */ + assert(attr >= FRAG_ATTRIB_TEX0); + input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0); + input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; + if (attr == FRAG_ATTRIB_PNTC) + interpMode[slot] = TGSI_INTERPOLATE_LINEAR; + else + interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; break; } + } + else { + inputMapping[attr] = -1; + } + } + /* + * Semantics and mapping for outputs + */ + { + uint numColors = 0; + GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten; + + /* if z is written, emit that first */ + if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { + fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION; + fs_output_semantic_index[fs_num_outputs] = 0; + outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs; fs_num_outputs++; + outputsWritten &= ~(1 << FRAG_RESULT_DEPTH); + } + + if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) { + fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL; + fs_output_semantic_index[fs_num_outputs] = 0; + outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs; + fs_num_outputs++; + outputsWritten &= ~(1 << FRAG_RESULT_STENCIL); + } + + /* handle remaning outputs (color) */ + for (attr = 0; attr < FRAG_RESULT_MAX; attr++) { + if (outputsWritten & BITFIELD64_BIT(attr)) { + switch (attr) { + case FRAG_RESULT_DEPTH: + case FRAG_RESULT_STENCIL: + /* handled above */ + assert(0); + break; + default: + assert(attr == FRAG_RESULT_COLOR || + (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX)); + fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR; + fs_output_semantic_index[fs_num_outputs] = numColors; + outputMapping[attr] = fs_num_outputs; + numColors++; + break; + } + + fs_num_outputs++; + } } } - } - ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); - if (ureg == NULL) - return; + ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); + if (ureg == NULL) + return NULL; - if (ST_DEBUG & DEBUG_MESA) { - _mesa_print_program(&stfp->Base.Base); - _mesa_print_program_parameters(st->ctx, &stfp->Base.Base); - debug_printf("\n"); + if (ST_DEBUG & DEBUG_MESA) { + _mesa_print_program(&stfp->Base.Base); + _mesa_print_program_parameters(st->ctx, &stfp->Base.Base); + debug_printf("\n"); + } + + error = st_translate_mesa_program(st->ctx, + TGSI_PROCESSOR_FRAGMENT, + ureg, + &stfp->Base.Base, + /* inputs */ + fs_num_inputs, + inputMapping, + input_semantic_name, + input_semantic_index, + interpMode, + /* outputs */ + fs_num_outputs, + outputMapping, + fs_output_semantic_name, + fs_output_semantic_index, FALSE ); + + stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); + ureg_destroy( ureg ); } - error = - st_translate_mesa_program(st->ctx, - TGSI_PROCESSOR_FRAGMENT, - ureg, - &stfp->Base.Base, - /* inputs */ - fs_num_inputs, - inputMapping, - input_semantic_name, - input_semantic_index, - interpMode, - /* outputs */ - fs_num_outputs, - outputMapping, - fs_output_semantic_name, - fs_output_semantic_index, FALSE ); - - stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); - ureg_destroy( ureg ); - stfp->driver_shader = pipe->create_fs_state(pipe, &stfp->tgsi); + /* fill in variant */ + variant->driver_shader = pipe->create_fs_state(pipe, &stfp->tgsi); + variant->key = *key; if (ST_DEBUG & DEBUG_TGSI) { tgsi_dump( stfp->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/ ); debug_printf("\n"); } + + return variant; } -void + +/** + * Translate fragment program if needed. + */ +struct st_fp_variant * +st_get_fp_variant(struct st_context *st, + struct st_fragment_program *stfp, + const struct st_fp_variant_key *key) +{ + struct st_fp_variant *fpv; + + /* Search for existing variant */ + for (fpv = stfp->variants; fpv; fpv = fpv->next) { + if (memcmp(&fpv->key, key, sizeof(*key)) == 0) { + break; + } + } + + if (!fpv) { + /* create new */ + fpv = st_translate_fragment_program(st, stfp, key); + if (fpv) { + /* insert into list */ + fpv->next = stfp->variants; + stfp->variants = fpv; + } + } + + return fpv; +} + + +/** + * Translate a geometry program to create a new variant. + */ +static struct st_gp_variant * st_translate_geometry_program(struct st_context *st, - struct st_geometry_program *stgp) + struct st_geometry_program *stgp, + const struct st_gp_variant_key *key) { GLuint inputMapping[GEOM_ATTRIB_MAX]; GLuint outputMapping[GEOM_RESULT_MAX]; @@ -494,12 +686,19 @@ st_translate_geometry_program(struct st_context *st, GLuint maxSlot = 0; struct ureg_program *ureg; + struct st_gp_variant *gpv; + + gpv = CALLOC_STRUCT(st_gp_variant); + if (!gpv) + return NULL; + _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT); _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING); ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY ); if (ureg == NULL) { - return; + FREE(gpv); + return NULL; } /* which vertex output goes to the first geometry input */ @@ -529,7 +728,7 @@ st_translate_geometry_program(struct st_context *st, } else ++gs_builtin_inputs; -#if 1 +#if 0 debug_printf("input map at %d = %d\n", slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]); #endif @@ -671,37 +870,35 @@ st_translate_geometry_program(struct st_context *st, st_free_tokens(stgp->tgsi.tokens); stgp->tgsi.tokens = NULL; } - if (stgp->driver_shader) { - cso_delete_geometry_shader(st->cso_context, stgp->driver_shader); - stgp->driver_shader = NULL; - } ureg_property_gs_input_prim(ureg, stgp->Base.InputType); ureg_property_gs_output_prim(ureg, stgp->Base.OutputType); ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut); - error = st_translate_mesa_program(st->ctx, - TGSI_PROCESSOR_GEOMETRY, - ureg, - &stgp->Base.Base, - /* inputs */ - gs_num_inputs, - inputMapping, - stgp->input_semantic_name, - stgp->input_semantic_index, - NULL, - /* outputs */ - gs_num_outputs, - outputMapping, - gs_output_semantic_name, - gs_output_semantic_index, - FALSE); - + error = st_translate_mesa_program(st->ctx, + TGSI_PROCESSOR_GEOMETRY, + ureg, + &stgp->Base.Base, + /* inputs */ + gs_num_inputs, + inputMapping, + stgp->input_semantic_name, + stgp->input_semantic_index, + NULL, + /* outputs */ + gs_num_outputs, + outputMapping, + gs_output_semantic_name, + gs_output_semantic_index, + FALSE); stgp->num_inputs = gs_num_inputs; stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); ureg_destroy( ureg ); - stgp->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi); + + /* fill in new variant */ + gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi); + gpv->key = *key; if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) { _mesa_print_program(&stgp->Base.Base); @@ -712,8 +909,44 @@ st_translate_geometry_program(struct st_context *st, tgsi_dump(stgp->tgsi.tokens, 0); debug_printf("\n"); } + + return gpv; +} + + +/** + * Get/create geometry program variant. + */ +struct st_gp_variant * +st_get_gp_variant(struct st_context *st, + struct st_geometry_program *stgp, + const struct st_gp_variant_key *key) +{ + struct st_gp_variant *gpv; + + /* Search for existing variant */ + for (gpv = stgp->variants; gpv; gpv = gpv->next) { + if (memcmp(&gpv->key, key, sizeof(*key)) == 0) { + break; + } + } + + if (!gpv) { + /* create new */ + gpv = st_translate_geometry_program(st, stgp, key); + if (gpv) { + /* insert into list */ + gpv->next = stgp->variants; + stgp->variants = gpv; + } + } + + return gpv; } + + + /** * Debug- print current shader text */ @@ -759,3 +992,155 @@ st_print_shaders(struct gl_context *ctx) } } } + + +/** + * Vert/Geom/Frag programs have per-context variants. Free all the + * variants attached to the given program which match the given context. + */ +static void +destroy_program_variants(struct st_context *st, struct gl_program *program) +{ + if (!program) + return; + + switch (program->Target) { + case GL_VERTEX_PROGRAM_ARB: + { + struct st_vertex_program *stvp = (struct st_vertex_program *) program; + struct st_vp_variant *vpv, **prevPtr = &stvp->variants; + + for (vpv = stvp->variants; vpv; ) { + struct st_vp_variant *next = vpv->next; + if (vpv->key.st == st) { + /* unlink from list */ + *prevPtr = next; + /* destroy this variant */ + delete_vp_variant(st, vpv); + } + else { + prevPtr = &vpv->next; + } + vpv = next; + } + } + break; + case GL_FRAGMENT_PROGRAM_ARB: + { + struct st_fragment_program *stfp = + (struct st_fragment_program *) program; + struct st_fp_variant *fpv, **prevPtr = &stfp->variants; + + for (fpv = stfp->variants; fpv; ) { + struct st_fp_variant *next = fpv->next; + if (fpv->key.st == st) { + /* unlink from list */ + *prevPtr = next; + /* destroy this variant */ + delete_fp_variant(st, fpv); + } + else { + prevPtr = &fpv->next; + } + fpv = next; + } + } + break; + case MESA_GEOMETRY_PROGRAM: + { + struct st_geometry_program *stgp = + (struct st_geometry_program *) program; + struct st_gp_variant *gpv, **prevPtr = &stgp->variants; + + for (gpv = stgp->variants; gpv; ) { + struct st_gp_variant *next = gpv->next; + if (gpv->key.st == st) { + /* unlink from list */ + *prevPtr = next; + /* destroy this variant */ + delete_gp_variant(st, gpv); + } + else { + prevPtr = &gpv->next; + } + gpv = next; + } + } + break; + default: + _mesa_problem(NULL, "Unexpected program target in " + "destroy_program_variants_cb()"); + } +} + + +/** + * Callback for _mesa_HashWalk. Free all the shader's program variants + * which match the given context. + */ +static void +destroy_shader_program_variants_cb(GLuint key, void *data, void *userData) +{ + struct st_context *st = (struct st_context *) userData; + struct gl_shader *shader = (struct gl_shader *) data; + + switch (shader->Type) { + case GL_SHADER_PROGRAM_MESA: + { + struct gl_shader_program *shProg = (struct gl_shader_program *) data; + GLuint i; + + for (i = 0; i < shProg->NumShaders; i++) { + destroy_program_variants(st, shProg->Shaders[i]->Program); + } + + destroy_program_variants(st, (struct gl_program *) + shProg->VertexProgram); + destroy_program_variants(st, (struct gl_program *) + shProg->FragmentProgram); + destroy_program_variants(st, (struct gl_program *) + shProg->GeometryProgram); + } + break; + case GL_VERTEX_SHADER: + case GL_FRAGMENT_SHADER: + case GL_GEOMETRY_SHADER: + { + destroy_program_variants(st, shader->Program); + } + break; + default: + assert(0); + } +} + + +/** + * Callback for _mesa_HashWalk. Free all the program variants which match + * the given context. + */ +static void +destroy_program_variants_cb(GLuint key, void *data, void *userData) +{ + struct st_context *st = (struct st_context *) userData; + struct gl_program *program = (struct gl_program *) data; + destroy_program_variants(st, program); +} + + +/** + * Walk over all shaders and programs to delete any variants which + * belong to the given context. + * This is called during context tear-down. + */ +void +st_destroy_program_variants(struct st_context *st) +{ + /* ARB vert/frag program */ + _mesa_HashWalk(st->ctx->Shared->Programs, + destroy_program_variants_cb, st); + + /* GLSL vert/frag/geom shaders */ + _mesa_HashWalk(st->ctx->Shared->ShaderObjects, + destroy_shader_program_variants_cb, st); +} diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index 72dbc715fe1..c4244df939e 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -40,26 +40,61 @@ #include "st_context.h" +/** Fragment program variant key */ +struct st_fp_variant_key +{ + struct st_context *st; /**< variants are per-context */ + + /** for glBitmap */ + GLuint bitmap:1; /**< glBitmap variant? */ + + /** for glDrawPixels */ + GLuint drawpixels:1; /**< glDrawPixels variant */ + GLuint scaleAndBias:1; /**< glDrawPixels w/ scale and/or bias? */ + GLuint pixelMaps:1; /**< glDrawPixels w/ pixel lookup map? */ + GLuint drawpixels_z:1; /**< glDrawPixels(GL_DEPTH) */ + GLuint drawpixels_stencil:1; /**< glDrawPixels(GL_STENCIL) */ +}; + + +/** + * Variant of a fragment program. + */ +struct st_fp_variant +{ + /** Parameters which generated this version of fragment program */ + struct st_fp_variant_key key; + + /** Driver's compiled shader */ + void *driver_shader; + + /** For glBitmap variants */ + struct gl_program_parameter_list *parameters; + uint bitmap_sampler; + + /** next in linked list */ + struct st_fp_variant *next; +}; + + /** * Derived from Mesa gl_fragment_program: */ struct st_fragment_program { struct gl_fragment_program Base; - GLuint serialNo; struct pipe_shader_state tgsi; - void *driver_shader; - /** Program prefixed with glBitmap prologue */ - struct st_fragment_program *bitmap_program; - uint bitmap_sampler; + struct st_fp_variant *variants; }; -struct st_vp_varient_key +/** Vertex program variant key */ +struct st_vp_variant_key { + struct st_context *st; /**< variants are per-context */ boolean passthrough_edgeflags; }; @@ -68,12 +103,12 @@ struct st_vp_varient_key * This represents a vertex program, especially translated to match * the inputs of a particular fragment shader. */ -struct st_vp_varient +struct st_vp_variant { /* Parameters which generated this translated version of a vertex * shader: */ - struct st_vp_varient_key key; + struct st_vp_variant_key key; /** * TGSI tokens (to later generate a 'draw' module shader for @@ -88,9 +123,9 @@ struct st_vp_varient struct draw_vertex_shader *draw_shader; /** Next in linked list */ - struct st_vp_varient *next; + struct st_vp_variant *next; - /** similar to that in st_vertex_program, but with information about edgeflags too */ + /** similar to that in st_vertex_program, but with edgeflags info too */ GLuint num_inputs; }; @@ -101,7 +136,6 @@ struct st_vp_varient struct st_vertex_program { struct gl_vertex_program Base; /**< The Mesa vertex program */ - GLuint serialNo, lastSerialNo; /** maps a Mesa VERT_ATTRIB_x to a packed TGSI input index */ GLuint input_to_index[VERT_ATTRIB_MAX]; @@ -115,18 +149,41 @@ struct st_vertex_program ubyte output_semantic_index[VERT_RESULT_MAX]; GLuint num_outputs; - /** List of translated varients of this vertex program. + /** List of translated variants of this vertex program. */ - struct st_vp_varient *varients; + struct st_vp_variant *variants; +}; + + + +/** Geometry program variant key */ +struct st_gp_variant_key +{ + struct st_context *st; /**< variants are per-context */ + /* no other fields yet */ +}; + + +/** + * Geometry program variant. + */ +struct st_gp_variant +{ + /* Parameters which generated this translated version of a vertex */ + struct st_gp_variant_key key; + + void *driver_shader; + + struct st_gp_variant *next; }; + /** * Derived from Mesa gl_geometry_program: */ struct st_geometry_program { struct gl_geometry_program Base; /**< The Mesa geometry program */ - GLuint serialNo; /** map GP input back to VP output */ GLuint input_map[PIPE_MAX_SHADER_INPUTS]; @@ -145,9 +202,12 @@ struct st_geometry_program ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; struct pipe_shader_state tgsi; - void *driver_shader; + + struct st_gp_variant *variants; }; + + static INLINE struct st_fragment_program * st_fragment_program( struct gl_fragment_program *fp ) { @@ -162,9 +222,9 @@ st_vertex_program( struct gl_vertex_program *vp ) } static INLINE struct st_geometry_program * -st_geometry_program( struct gl_geometry_program *vp ) +st_geometry_program( struct gl_geometry_program *gp ) { - return (struct st_geometry_program *)vp; + return (struct st_geometry_program *)gp; } static INLINE void @@ -198,32 +258,43 @@ st_reference_fragprog(struct st_context *st, } -extern void -st_translate_fragment_program(struct st_context *st, - struct st_fragment_program *fp); +extern struct st_vp_variant * +st_get_vp_variant(struct st_context *st, + struct st_vertex_program *stvp, + const struct st_vp_variant_key *key); + + +extern struct st_fp_variant * +st_get_fp_variant(struct st_context *st, + struct st_fragment_program *stfp, + const struct st_fp_variant_key *key); + + +extern struct st_gp_variant * +st_get_gp_variant(struct st_context *st, + struct st_geometry_program *stgp, + const struct st_gp_variant_key *key); + + extern void -st_translate_geometry_program(struct st_context *st, - struct st_geometry_program *stgp); +st_release_vp_variants( struct st_context *st, + struct st_vertex_program *stvp ); -/* Called after program string change, discard all previous - * compilation results. - */ extern void -st_prepare_vertex_program(struct st_context *st, - struct st_vertex_program *stvp); +st_release_fp_variants( struct st_context *st, + struct st_fragment_program *stfp ); -extern struct st_vp_varient * -st_translate_vertex_program(struct st_context *st, - struct st_vertex_program *stvp, - const struct st_vp_varient_key *key); +extern void +st_release_gp_variants(struct st_context *st, + struct st_geometry_program *stgp); -void -st_vp_release_varients( struct st_context *st, - struct st_vertex_program *stvp ); extern void st_print_shaders(struct gl_context *ctx); +extern void +st_destroy_program_variants(struct st_context *st); + #endif diff --git a/src/mesa/tnl/t_vb_program.c b/src/mesa/tnl/t_vb_program.c index 76f8fde3f52..94372bbafbc 100644 --- a/src/mesa/tnl/t_vb_program.c +++ b/src/mesa/tnl/t_vb_program.c @@ -67,6 +67,8 @@ struct vp_stage_data { GLvector4f ndcCoords; /**< normalized device coords */ GLubyte *clipmask; /**< clip flags */ GLubyte ormask, andmask; /**< for clipping */ + + struct gl_program_machine machine; }; @@ -311,7 +313,7 @@ run_vp( struct gl_context *ctx, struct tnl_pipeline_stage *stage ) struct vp_stage_data *store = VP_STAGE_DATA(stage); struct vertex_buffer *VB = &tnl->vb; struct gl_vertex_program *program = ctx->VertexProgram._Current; - struct gl_program_machine machine; + struct gl_program_machine *machine = &store->machine; GLuint outputs[VERT_RESULT_MAX], numOutputs; GLuint i, j; @@ -339,7 +341,7 @@ run_vp( struct gl_context *ctx, struct tnl_pipeline_stage *stage ) for (i = 0; i < VB->Count; i++) { GLuint attr; - init_machine(ctx, &machine); + init_machine(ctx, machine); #if 0 printf("Input %d: %f, %f, %f, %f\n", i, @@ -372,23 +374,23 @@ run_vp( struct gl_context *ctx, struct tnl_pipeline_stage *stage ) check_float(data[2]); check_float(data[3]); #endif - COPY_CLEAN_4V(machine.VertAttribs[attr], size, data); + COPY_CLEAN_4V(machine->VertAttribs[attr], size, data); } } /* execute the program */ - _mesa_execute_program(ctx, &program->Base, &machine); + _mesa_execute_program(ctx, &program->Base, machine); /* copy the output registers into the VB->attribs arrays */ for (j = 0; j < numOutputs; j++) { const GLuint attr = outputs[j]; #ifdef NAN_CHECK - check_float(machine.Outputs[attr][0]); - check_float(machine.Outputs[attr][1]); - check_float(machine.Outputs[attr][2]); - check_float(machine.Outputs[attr][3]); + check_float(machine->Outputs[attr][0]); + check_float(machine->Outputs[attr][1]); + check_float(machine->Outputs[attr][2]); + check_float(machine->Outputs[attr][3]); #endif - COPY_4V(store->results[attr].data[i], machine.Outputs[attr]); + COPY_4V(store->results[attr].data[i], machine->Outputs[attr]); } /* FOGC is a special case. Fragment shader expects (f,0,0,1) */ @@ -398,14 +400,14 @@ run_vp( struct gl_context *ctx, struct tnl_pipeline_stage *stage ) store->results[VERT_RESULT_FOGC].data[i][3] = 1.0; } #ifdef NAN_CHECK - ASSERT(machine.Outputs[0][3] != 0.0F); + ASSERT(machine->Outputs[0][3] != 0.0F); #endif #if 0 printf("HPOS: %f %f %f %f\n", - machine.Outputs[0][0], - machine.Outputs[0][1], - machine.Outputs[0][2], - machine.Outputs[0][3]); + machine->Outputs[0][0], + machine->Outputs[0][1], + machine->Outputs[0][2], + machine->Outputs[0][3]); #endif } @@ -501,7 +503,7 @@ init_vp(struct gl_context *ctx, struct tnl_pipeline_stage *stage) const GLuint size = VB->Size; GLuint i; - stage->privatePtr = MALLOC(sizeof(*store)); + stage->privatePtr = CALLOC(sizeof(*store)); store = VP_STAGE_DATA(stage); if (!store) return GL_FALSE; |