diff options
author | Keith Whitwell <keithw@vmware.com> | 2010-03-21 09:54:53 +0000 |
---|---|---|
committer | Keith Whitwell <keithw@vmware.com> | 2010-03-21 09:54:53 +0000 |
commit | be7af29d3ad1a10409b0ea689d882cf30a4e1d62 (patch) | |
tree | a3675995b8dbe62b60571ff96cbf281868ec9c25 /src/gallium | |
parent | d22c2c6cb23a063e3334a165d0c5c3d73f05d234 (diff) | |
parent | 12deb9e6ca76d222badf71c8643e84640673e86d (diff) |
Merge commit 'origin/master' into gallium-resources
Conflicts:
src/gallium/auxiliary/cso_cache/cso_context.c
src/gallium/auxiliary/cso_cache/cso_context.h
src/gallium/drivers/r300/r300_context.c
src/gallium/drivers/r300/r300_render.c
src/gallium/drivers/r300/r300_state.c
src/gallium/drivers/r300/r300_state_derived.c
src/gallium/state_trackers/vega/api_filters.c
src/gallium/state_trackers/vega/image.c
src/gallium/state_trackers/vega/image.h
src/gallium/state_trackers/vega/mask.c
src/gallium/state_trackers/vega/mask.h
src/gallium/state_trackers/vega/paint.c
src/gallium/state_trackers/vega/paint.h
src/gallium/state_trackers/vega/renderer.c
src/gallium/state_trackers/vega/renderer.h
src/gallium/state_trackers/vega/shader.c
src/gallium/state_trackers/vega/vg_context.h
src/gallium/state_trackers/vega/vg_tracker.c
src/mesa/state_tracker/st_manager.c
Diffstat (limited to 'src/gallium')
57 files changed, 2346 insertions, 1426 deletions
diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c index 2747173755..d6f8dd34bf 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.c +++ b/src/gallium/auxiliary/cso_cache/cso_context.c @@ -618,74 +618,6 @@ cso_restore_vertex_samplers(struct cso_context *ctx) } -enum pipe_error cso_set_sampler_textures( struct cso_context *ctx, - uint count, - struct pipe_resource **textures ) -{ - uint i; - - ctx->nr_fragment_sampler_views = count; - - for (i = 0; i < count; i++) { - struct pipe_sampler_view templ, *view; - - u_sampler_view_default_template(&templ, - textures[i], - textures[i]->format); - - view = ctx->pipe->create_sampler_view(ctx->pipe, - textures[i], - &templ); - - pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], view); - } - for ( ; i < PIPE_MAX_SAMPLERS; i++) { - pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL); - } - - ctx->pipe->set_fragment_sampler_views(ctx->pipe, - count, - ctx->fragment_sampler_views); - - return PIPE_OK; -} - -void cso_save_sampler_textures( struct cso_context *ctx ) -{ - uint i; - - ctx->nr_fragment_sampler_views_saved = ctx->nr_fragment_sampler_views; - for (i = 0; i < ctx->nr_fragment_sampler_views; i++) { - assert(!ctx->fragment_sampler_views_saved[i]); - - pipe_sampler_view_reference(&ctx->fragment_sampler_views_saved[i], - ctx->fragment_sampler_views[i]); - } -} - -void cso_restore_sampler_textures( struct cso_context *ctx ) -{ - uint i; - - ctx->nr_fragment_sampler_views = ctx->nr_fragment_sampler_views_saved; - - for (i = 0; i < ctx->nr_fragment_sampler_views; i++) { - pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL); - ctx->fragment_sampler_views[i] = ctx->fragment_sampler_views_saved[i]; - ctx->fragment_sampler_views_saved[i] = NULL; - } - for ( ; i < PIPE_MAX_SAMPLERS; i++) { - pipe_sampler_view_reference(&ctx->fragment_sampler_views[i], NULL); - } - - ctx->pipe->set_fragment_sampler_views(ctx->pipe, - ctx->nr_fragment_sampler_views, - ctx->fragment_sampler_views); - - ctx->nr_fragment_sampler_views_saved = 0; -} - - enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx, const struct pipe_depth_stencil_alpha_state *templ) { diff --git a/src/gallium/auxiliary/cso_cache/cso_context.h b/src/gallium/auxiliary/cso_cache/cso_context.h index 18c2e43588..d6bcb1fe8f 100644 --- a/src/gallium/auxiliary/cso_cache/cso_context.h +++ b/src/gallium/auxiliary/cso_cache/cso_context.h @@ -103,14 +103,6 @@ void cso_single_vertex_sampler_done(struct cso_context *cso); - -enum pipe_error cso_set_sampler_textures( struct cso_context *cso, - uint count, - struct pipe_resource **textures ); -void cso_save_sampler_textures( struct cso_context *cso ); -void cso_restore_sampler_textures( struct cso_context *cso ); - - enum pipe_error cso_set_vertex_elements(struct cso_context *ctx, unsigned count, const struct pipe_vertex_element *states); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_depth.c b/src/gallium/auxiliary/gallivm/lp_bld_depth.c index e4500e5aef..4ce1a27a06 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_depth.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_depth.c @@ -52,7 +52,14 @@ * Z31 Z32 Z41 Z42 Z33 Z34 Z43 Z44 ... * ... ... ... ... ... ... ... ... ... * - * FIXME: Code generate stencil test + * + * Stencil test: + * Two-sided stencil test is supported but probably not as efficient as + * it could be. Currently, we use if/then/else constructs to do the + * operations for front vs. back-facing polygons. We could probably do + * both the front and back arithmetic then use a Select() instruction to + * choose the result depending on polyon orientation. We'd have to + * measure performance both ways and see which is better. * * @author Jose Fonseca <jfonseca@vmware.com> */ @@ -70,23 +77,35 @@ #include "lp_bld_swizzle.h" +/** Used to select fields from pipe_stencil_state */ +enum stencil_op { + S_FAIL_OP, + Z_FAIL_OP, + Z_PASS_OP +}; + + /** - * Do the stencil test comparison (compare fb Z values against ref value. - * \param stencilVals vector of stencil values from framebuffer + * Do the stencil test comparison (compare FB stencil values against ref value). + * This will be used twice when generating two-sided stencil code. + * \param stencil the front/back stencil state * \param stencilRef the stencil reference value, replicated as a vector - * \return mask of pass/fail values + * \param stencilVals vector of stencil values from framebuffer + * \return vector mask of pass/fail values (~0 or 0) */ static LLVMValueRef -lp_build_stencil_test(struct lp_build_context *bld, - const struct pipe_stencil_state *stencil, - LLVMValueRef stencilRef, - LLVMValueRef stencilVals) +lp_build_stencil_test_single(struct lp_build_context *bld, + const struct pipe_stencil_state *stencil, + LLVMValueRef stencilRef, + LLVMValueRef stencilVals) { const unsigned stencilMax = 255; /* XXX fix */ struct lp_type type = bld->type; LLVMValueRef res; + assert(type.sign); + assert(stencil->enabled); if (stencil->valuemask != stencilMax) { @@ -104,23 +123,101 @@ lp_build_stencil_test(struct lp_build_context *bld, /** + * Do the one or two-sided stencil test comparison. + * \sa lp_build_stencil_test_single + * \param face an integer indicating front (+) or back (-) facing polygon. + * If NULL, assume front-facing. + */ +static LLVMValueRef +lp_build_stencil_test(struct lp_build_context *bld, + const struct pipe_stencil_state stencil[2], + LLVMValueRef stencilRefs[2], + LLVMValueRef stencilVals, + LLVMValueRef face) +{ + LLVMValueRef res; + + assert(stencil[0].enabled); + + if (stencil[1].enabled && face) { + /* do two-sided test */ + struct lp_build_flow_context *flow_ctx; + struct lp_build_if_state if_ctx; + LLVMValueRef front_facing; + LLVMValueRef zero = LLVMConstReal(LLVMFloatType(), 0.0); + LLVMValueRef result = bld->undef; + + flow_ctx = lp_build_flow_create(bld->builder); + lp_build_flow_scope_begin(flow_ctx); + + lp_build_flow_scope_declare(flow_ctx, &result); + + /* front_facing = face > 0.0 */ + front_facing = LLVMBuildFCmp(bld->builder, LLVMRealUGT, face, zero, ""); + + lp_build_if(&if_ctx, flow_ctx, bld->builder, front_facing); + { + result = lp_build_stencil_test_single(bld, &stencil[0], + stencilRefs[0], stencilVals); + } + lp_build_else(&if_ctx); + { + result = lp_build_stencil_test_single(bld, &stencil[1], + stencilRefs[1], stencilVals); + } + lp_build_endif(&if_ctx); + + lp_build_flow_scope_end(flow_ctx); + lp_build_flow_destroy(flow_ctx); + + res = result; + } + else { + /* do single-side test */ + res = lp_build_stencil_test_single(bld, &stencil[0], + stencilRefs[0], stencilVals); + } + + return res; +} + + +/** * Apply the stencil operator (add/sub/keep/etc) to the given vector * of stencil values. * \return new stencil values vector */ static LLVMValueRef -lp_build_stencil_op(struct lp_build_context *bld, - const struct pipe_stencil_state *stencil, - unsigned stencil_op, - LLVMValueRef stencilRef, - LLVMValueRef stencilVals, - LLVMValueRef mask) +lp_build_stencil_op_single(struct lp_build_context *bld, + const struct pipe_stencil_state *stencil, + enum stencil_op op, + LLVMValueRef stencilRef, + LLVMValueRef stencilVals, + LLVMValueRef mask) { const unsigned stencilMax = 255; /* XXX fix */ struct lp_type type = bld->type; LLVMValueRef res; LLVMValueRef max = lp_build_const_int_vec(type, stencilMax); + unsigned stencil_op; + + assert(type.sign); + + switch (op) { + case S_FAIL_OP: + stencil_op = stencil->fail_op; + break; + case Z_FAIL_OP: + stencil_op = stencil->zfail_op; + break; + case Z_PASS_OP: + stencil_op = stencil->zpass_op; + break; + default: + assert(0 && "Invalid stencil_op mode"); + stencil_op = PIPE_STENCIL_OP_KEEP; + } switch (stencil_op) { case PIPE_STENCIL_OP_KEEP: @@ -151,6 +248,7 @@ lp_build_stencil_op(struct lp_build_context *bld, break; case PIPE_STENCIL_OP_INVERT: res = LLVMBuildNot(bld->builder, stencilVals, ""); + res = LLVMBuildAnd(bld->builder, res, max, ""); break; default: assert(0 && "bad stencil op mode"); @@ -174,6 +272,63 @@ lp_build_stencil_op(struct lp_build_context *bld, /** + * Do the one or two-sided stencil test op/update. + */ +static LLVMValueRef +lp_build_stencil_op(struct lp_build_context *bld, + const struct pipe_stencil_state stencil[2], + enum stencil_op op, + LLVMValueRef stencilRefs[2], + LLVMValueRef stencilVals, + LLVMValueRef mask, + LLVMValueRef face) + +{ + assert(stencil[0].enabled); + + if (stencil[1].enabled && face) { + /* do two-sided op */ + struct lp_build_flow_context *flow_ctx; + struct lp_build_if_state if_ctx; + LLVMValueRef front_facing; + LLVMValueRef zero = LLVMConstReal(LLVMFloatType(), 0.0); + LLVMValueRef result = bld->undef; + + flow_ctx = lp_build_flow_create(bld->builder); + lp_build_flow_scope_begin(flow_ctx); + + lp_build_flow_scope_declare(flow_ctx, &result); + + /* front_facing = face > 0.0 */ + front_facing = LLVMBuildFCmp(bld->builder, LLVMRealUGT, face, zero, ""); + + lp_build_if(&if_ctx, flow_ctx, bld->builder, front_facing); + { + result = lp_build_stencil_op_single(bld, &stencil[0], op, + stencilRefs[0], stencilVals, mask); + } + lp_build_else(&if_ctx); + { + result = lp_build_stencil_op_single(bld, &stencil[1], op, + stencilRefs[1], stencilVals, mask); + } + lp_build_endif(&if_ctx); + + lp_build_flow_scope_end(flow_ctx); + lp_build_flow_destroy(flow_ctx); + + return result; + } + else { + /* do single-sided op */ + return lp_build_stencil_op_single(bld, &stencil[0], op, + stencilRefs[0], stencilVals, mask); + } +} + + + +/** * Return a type appropriate for depth/stencil testing. */ struct lp_type @@ -213,36 +368,96 @@ lp_depth_type(const struct util_format_description *format_desc, } -static LLVMValueRef -lp_build_get_stencil_ref(struct lp_build_context *bld, - struct lp_type type, LLVMValueRef stencil_refs_ptr) +/** + * Compute bitmask and bit shift to apply to the incoming fragment Z values + * and the Z buffer values needed before doing the Z comparison. + * + * Note that we leave the Z bits in the position that we find them + * in the Z buffer (typically 0xffffff00 or 0x00ffffff). That lets us + * get by with fewer bit twiddling steps. + */ +static boolean +get_z_shift_and_mask(const struct util_format_description *format_desc, + unsigned *shift, unsigned *mask) +{ + const unsigned total_bits = format_desc->block.bits; + unsigned z_swizzle; + int chan; + unsigned padding_left, padding_right; + + assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS); + assert(format_desc->block.width == 1); + assert(format_desc->block.height == 1); + + z_swizzle = format_desc->swizzle[0]; + + if (z_swizzle == UTIL_FORMAT_SWIZZLE_NONE) + return FALSE; + + padding_right = 0; + for (chan = 0; chan < z_swizzle; ++chan) + padding_right += format_desc->channel[chan].size; + + padding_left = + total_bits - (padding_right + format_desc->channel[z_swizzle].size); + + if (padding_left || padding_right) { + unsigned long long mask_left = (1ULL << (total_bits - padding_left)) - 1; + unsigned long long mask_right = (1ULL << (padding_right)) - 1; + *mask = mask_left ^ mask_right; + } + else { + *mask = 0xffffffff; + } + + *shift = padding_left; + + return TRUE; +} + + +/** + * Compute bitmask and bit shift to apply to the framebuffer pixel values + * to put the stencil bits in the least significant position. + * (i.e. 0x000000ff) + */ +static boolean +get_s_shift_and_mask(const struct util_format_description *format_desc, + unsigned *shift, unsigned *mask) { - LLVMValueRef indexes[2], ptr, ref, ref_vec; + unsigned s_swizzle; + int chan, sz; + + s_swizzle = format_desc->swizzle[1]; - /* load 0th element of the array */ - indexes[0] = indexes[1] = LLVMConstInt(LLVMInt32Type(), 0, 0); - ptr = LLVMBuildGEP(bld->builder, stencil_refs_ptr, indexes, 2, ""); - ref = LLVMBuildLoad(bld->builder, ptr, ""); + if (s_swizzle == UTIL_FORMAT_SWIZZLE_NONE) + return FALSE; - /* convert int8 value to i32 */ - ref = LLVMBuildZExt(bld->builder, ref, LLVMIntType(type.width), ""); + *shift = 0; + for (chan = 0; chan < s_swizzle; chan++) + *shift += format_desc->channel[chan].size; - /* make scalar into vector */ - ref_vec = lp_build_broadcast_scalar(bld, ref); + sz = format_desc->channel[s_swizzle].size; + *mask = (1U << sz) - 1U; - return ref_vec; + return TRUE; } + /** * Generate code for performing depth and/or stencil tests. * We operate on a vector of values (typically a 2x2 quad). * + * \param depth the depth test state + * \param stencil the front/back stencil state * \param type the data type of the fragment depth/stencil values * \param format_desc description of the depth/stencil surface - * \param mask the alive/dead pixel mask for the quad - * \param src the incoming depth/stencil values (a 2x2 quad) - * \param dst_ptr the outgoing/updated depth/stencil values + * \param mask the alive/dead pixel mask for the quad (vector) + * \param stencil_refs the front/back stencil ref values (scalar) + * \param z_src the incoming depth/stencil values (a 2x2 quad) + * \param zs_dst_ptr pointer to depth/stencil values in framebuffer + * \param facing contains float value indicating front/back facing polygon */ void lp_build_depth_stencil_test(LLVMBuilderRef builder, @@ -251,119 +466,131 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, struct lp_type type, const struct util_format_description *format_desc, struct lp_build_mask_context *mask, - LLVMValueRef stencil_refs, + LLVMValueRef stencil_refs[2], LLVMValueRef z_src, - LLVMValueRef zs_dst_ptr) + LLVMValueRef zs_dst_ptr, + LLVMValueRef face) { struct lp_build_context bld; - unsigned z_swizzle, s_swizzle; + struct lp_build_context sbld; + struct lp_type s_type; LLVMValueRef zs_dst, z_dst = NULL; LLVMValueRef stencil_vals = NULL; - LLVMValueRef z_bitmask = NULL, s_bitmask = NULL; + LLVMValueRef z_bitmask = NULL, stencil_shift = NULL; LLVMValueRef z_pass = NULL, s_pass_mask = NULL; LLVMValueRef orig_mask = mask->value; - assert(depth->enabled || stencil[0].enabled); + /* Sanity checking */ + { + const unsigned z_swizzle = format_desc->swizzle[0]; + const unsigned s_swizzle = format_desc->swizzle[1]; - assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS); - assert(format_desc->block.width == 1); - assert(format_desc->block.height == 1); + assert(z_swizzle != UTIL_FORMAT_SWIZZLE_NONE || + s_swizzle != UTIL_FORMAT_SWIZZLE_NONE); - z_swizzle = format_desc->swizzle[0]; - s_swizzle = format_desc->swizzle[1]; + assert(depth->enabled || stencil[0].enabled); - assert(z_swizzle != UTIL_FORMAT_SWIZZLE_NONE || - s_swizzle != UTIL_FORMAT_SWIZZLE_NONE); + assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS); + assert(format_desc->block.width == 1); + assert(format_desc->block.height == 1); - /* Sanity checking */ - assert(z_swizzle < 4); - assert(format_desc->block.bits == type.width); - if(type.floating) { - assert(z_swizzle == 0); - assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_FLOAT); - assert(format_desc->channel[z_swizzle].size == format_desc->block.bits); - } - else { - assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED); - assert(format_desc->channel[z_swizzle].normalized); - assert(!type.fixed); - assert(!type.sign); - assert(type.norm); + if (stencil[0].enabled) { + assert(format_desc->format == PIPE_FORMAT_Z24S8_UNORM || + format_desc->format == PIPE_FORMAT_S8Z24_UNORM); + } + + assert(z_swizzle < 4); + assert(format_desc->block.bits == type.width); + if (type.floating) { + assert(z_swizzle == 0); + assert(format_desc->channel[z_swizzle].type == + UTIL_FORMAT_TYPE_FLOAT); + assert(format_desc->channel[z_swizzle].size == + format_desc->block.bits); + } + else { + assert(format_desc->channel[z_swizzle].type == + UTIL_FORMAT_TYPE_UNSIGNED); + assert(format_desc->channel[z_swizzle].normalized); + assert(!type.fixed); + assert(!type.sign); + assert(type.norm); + } } - /* Setup build context */ + + /* Setup build context for Z vals */ lp_build_context_init(&bld, builder, type); + /* Setup build context for stencil vals */ + s_type = lp_type_int_vec(type.width); + lp_build_context_init(&sbld, builder, s_type); + /* Load current z/stencil value from z/stencil buffer */ zs_dst = LLVMBuildLoad(builder, zs_dst_ptr, ""); lp_build_name(zs_dst, "zsbufval"); - /* Align the source depth bits with the destination's, and mask out any - * stencil or padding bits from both */ - if(format_desc->channel[z_swizzle].size == format_desc->block.bits) { - assert(z_swizzle == 0); - z_dst = zs_dst; - } - else { - /* shift/mask bits to right-justify the Z bits */ - unsigned padding_left; - unsigned padding_right; - unsigned chan; - - assert(format_desc->layout == UTIL_FORMAT_LAYOUT_PLAIN); - assert(format_desc->channel[z_swizzle].type == UTIL_FORMAT_TYPE_UNSIGNED); - assert(format_desc->channel[z_swizzle].size <= format_desc->block.bits); - assert(format_desc->channel[z_swizzle].normalized); - - padding_right = 0; - for(chan = 0; chan < z_swizzle; ++chan) - padding_right += format_desc->channel[chan].size; - padding_left = format_desc->block.bits - - (padding_right + format_desc->channel[z_swizzle].size); - - if(padding_left || padding_right) { - const unsigned long long mask_left = (1ULL << (format_desc->block.bits - padding_left)) - 1; - const unsigned long long mask_right = (1ULL << (padding_right)) - 1; - z_bitmask = lp_build_const_int_vec(type, mask_left ^ mask_right); - } - - s_bitmask = LLVMBuildNot(builder, z_bitmask, ""); - stencil_vals = LLVMBuildAnd(builder, zs_dst, s_bitmask, ""); + /* Compute and apply the Z/stencil bitmasks and shifts. + */ + { + unsigned z_shift, z_mask; + unsigned s_shift, s_mask; + + if (get_z_shift_and_mask(format_desc, &z_shift, &z_mask)) { + if (z_shift) { + LLVMValueRef shift = lp_build_const_int_vec(type, z_shift); + z_src = LLVMBuildLShr(builder, z_src, shift, ""); + } + + if (z_mask != 0xffffffff) { + LLVMValueRef mask = lp_build_const_int_vec(type, z_mask); + z_src = LLVMBuildAnd(builder, z_src, mask, ""); + z_dst = LLVMBuildAnd(builder, zs_dst, mask, ""); + z_bitmask = mask; /* used below */ + } + else { + z_dst = zs_dst; + } + + lp_build_name(z_dst, "zsbuf.z"); + } - if(padding_left) - z_src = LLVMBuildLShr(builder, z_src, - lp_build_const_int_vec(type, padding_left), ""); - if(padding_right) - z_src = LLVMBuildAnd(builder, z_src, z_bitmask, ""); - if(padding_left || padding_right) - z_dst = LLVMBuildAnd(builder, zs_dst, z_bitmask, ""); - else - z_dst = zs_dst; + if (get_s_shift_and_mask(format_desc, &s_shift, &s_mask)) { + if (s_shift) { + LLVMValueRef shift = lp_build_const_int_vec(type, s_shift); + stencil_vals = LLVMBuildLShr(builder, zs_dst, shift, ""); + stencil_shift = shift; /* used below */ + } + else { + stencil_vals = zs_dst; + } + + if (s_mask != 0xffffffff) { + LLVMValueRef mask = lp_build_const_int_vec(type, s_mask); + stencil_vals = LLVMBuildAnd(builder, stencil_vals, mask, ""); + } + + lp_build_name(stencil_vals, "stencil"); + } } - lp_build_name(z_dst, "zsbuf.z"); - - /* - printf("build depth %d stencil %d\n", - depth->enabled, - stencil[0].enabled); - */ if (stencil[0].enabled) { - /* Incoming stencil_refs is ptr to int8[2]. Get/convert to int32[4]. */ - stencil_refs = lp_build_get_stencil_ref(&bld, type, stencil_refs); + /* convert scalar stencil refs into vectors */ + stencil_refs[0] = lp_build_broadcast_scalar(&bld, stencil_refs[0]); + stencil_refs[1] = lp_build_broadcast_scalar(&bld, stencil_refs[1]); - s_pass_mask = lp_build_stencil_test(&bld, stencil, - stencil_refs, stencil_vals); + s_pass_mask = lp_build_stencil_test(&sbld, stencil, + stencil_refs, stencil_vals, face); /* apply stencil-fail operator */ { LLVMValueRef s_fail_mask = lp_build_andc(&bld, orig_mask, s_pass_mask); - stencil_vals = lp_build_stencil_op(&bld, stencil, stencil[0].fail_op, + stencil_vals = lp_build_stencil_op(&sbld, stencil, S_FAIL_OP, stencil_refs, stencil_vals, - s_fail_mask); + s_fail_mask, face); } } @@ -394,15 +621,15 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, /* apply Z-fail operator */ z_fail_mask = lp_build_andc(&bld, orig_mask, z_pass); - stencil_vals = lp_build_stencil_op(&bld, stencil, stencil[0].zfail_op, + stencil_vals = lp_build_stencil_op(&sbld, stencil, Z_FAIL_OP, stencil_refs, stencil_vals, - z_fail_mask); + z_fail_mask, face); /* apply Z-pass operator */ z_pass_mask = LLVMBuildAnd(bld.builder, orig_mask, z_pass, ""); - stencil_vals = lp_build_stencil_op(&bld, stencil, stencil[0].zpass_op, + stencil_vals = lp_build_stencil_op(&sbld, stencil, Z_PASS_OP, stencil_refs, stencil_vals, - z_pass_mask); + z_pass_mask, face); } } else { @@ -410,10 +637,18 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, * passed the stencil test. */ s_pass_mask = LLVMBuildAnd(bld.builder, orig_mask, s_pass_mask, ""); - stencil_vals = lp_build_stencil_op(&bld, stencil, stencil[0].zpass_op, - stencil_refs, stencil_vals, s_pass_mask); + stencil_vals = lp_build_stencil_op(&sbld, stencil, Z_PASS_OP, + stencil_refs, stencil_vals, + s_pass_mask, face); } + /* The Z bits are already in the right place but we may need to shift the + * stencil bits before ORing Z with Stencil to make the final pixel value. + */ + if (stencil_vals && stencil_shift) + stencil_vals = LLVMBuildShl(bld.builder, stencil_vals, + stencil_shift, ""); + /* Finally, merge/store the z/stencil values */ if ((depth->enabled && depth->writemask) || (stencil[0].enabled && stencil[0].writemask)) { diff --git a/src/gallium/auxiliary/gallivm/lp_bld_depth.h b/src/gallium/auxiliary/gallivm/lp_bld_depth.h index eedc1e419b..27dd46b625 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_depth.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_depth.h @@ -57,9 +57,10 @@ lp_build_depth_stencil_test(LLVMBuilderRef builder, struct lp_type type, const struct util_format_description *format_desc, struct lp_build_mask_context *mask, - LLVMValueRef stencil_refs, + LLVMValueRef stencil_refs[2], LLVMValueRef zs_src, - LLVMValueRef zs_dst_ptr); + LLVMValueRef zs_dst_ptr, + LLVMValueRef facing); #endif /* !LP_BLD_DEPTH_H */ diff --git a/src/gallium/auxiliary/util/u_format.csv b/src/gallium/auxiliary/util/u_format.csv index 96a0fa6550..11243e7349 100644 --- a/src/gallium/auxiliary/util/u_format.csv +++ b/src/gallium/auxiliary/util/u_format.csv @@ -63,6 +63,7 @@ PIPE_FORMAT_A8R8G8B8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , yzwx, r PIPE_FORMAT_X8R8G8B8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , yzw1, rgb PIPE_FORMAT_A8B8G8R8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , wzyx, rgb PIPE_FORMAT_X8B8G8R8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , wzy1, rgb +PIPE_FORMAT_B5G5R5X1_UNORM , plain, 1, 1, un5 , un5 , un5 , un1 , zyx1, rgb PIPE_FORMAT_B5G5R5A1_UNORM , plain, 1, 1, un5 , un5 , un5 , un1 , zyxw, rgb PIPE_FORMAT_B4G4R4A4_UNORM , plain, 1, 1, un4 , un4 , un4 , un4 , zyxw, rgb PIPE_FORMAT_B5G6R5_UNORM , plain, 1, 1, un5 , un6 , un5 , , zyx1, rgb diff --git a/src/gallium/auxiliary/util/u_format_tests.c b/src/gallium/auxiliary/util/u_format_tests.c index 182a474044..9d6debcd8c 100644 --- a/src/gallium/auxiliary/util/u_format_tests.c +++ b/src/gallium/auxiliary/util/u_format_tests.c @@ -120,6 +120,13 @@ util_format_test_cases[] = * 16-bit rendertarget formats */ + {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x001f), {0.0, 0.0, 1.0, 0.0}}, + {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x03e0), {0.0, 1.0, 0.0, 0.0}}, + {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x7c00), {1.0, 0.0, 0.0, 0.0}}, + {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x8000), {0.0, 0.0, 0.0, 1.0}}, + {PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0xffff), {1.0, 1.0, 1.0, 1.0}}, + {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), {0.0, 0.0, 0.0, 0.0}}, {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x001f), {0.0, 0.0, 1.0, 0.0}}, {PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x03e0), {0.0, 1.0, 0.0, 0.0}}, diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c index c4fb4f3cac..2ea22a9aa9 100644 --- a/src/gallium/auxiliary/util/u_gen_mipmap.c +++ b/src/gallium/auxiliary/util/u_gen_mipmap.c @@ -938,6 +938,7 @@ format_to_type_comps(enum pipe_format pformat, *datatype = DTYPE_UBYTE; *comps = 4; return; + case PIPE_FORMAT_B5G5R5X1_UNORM: case PIPE_FORMAT_B5G5R5A1_UNORM: *datatype = DTYPE_USHORT_1_5_5_5_REV; *comps = 4; diff --git a/src/gallium/auxiliary/util/u_pack_color.h b/src/gallium/auxiliary/util/u_pack_color.h index 50f1b1670b..c5fd7a6783 100644 --- a/src/gallium/auxiliary/util/u_pack_color.h +++ b/src/gallium/auxiliary/util/u_pack_color.h @@ -92,6 +92,11 @@ util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a, uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); } return; + case PIPE_FORMAT_B5G5R5X1_UNORM: + { + uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); + } + return; case PIPE_FORMAT_B5G5R5A1_UNORM: { uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); @@ -216,6 +221,15 @@ util_unpack_color_ub(enum pipe_format format, union util_color *uc, *a = (ubyte) 0xff; } return; + case PIPE_FORMAT_B5G5R5X1_UNORM: + { + ushort p = uc->us; + *r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7)); + *g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7)); + *b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7)); + *a = (ubyte) 0xff; + } + return; case PIPE_FORMAT_B5G5R5A1_UNORM: { ushort p = uc->us; @@ -361,6 +375,11 @@ util_pack_color(const float rgba[4], enum pipe_format format, union util_color * uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3); } return; + case PIPE_FORMAT_B5G5R5X1_UNORM: + { + uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); + } + return; case PIPE_FORMAT_B5G5R5A1_UNORM: { uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3); diff --git a/src/gallium/auxiliary/util/u_tile.c b/src/gallium/auxiliary/util/u_tile.c index 26bb4771b0..61d92c954d 100644 --- a/src/gallium/auxiliary/util/u_tile.c +++ b/src/gallium/auxiliary/util/u_tile.c @@ -295,6 +295,55 @@ r8g8b8a8_put_tile_rgba(unsigned *dst, } +/*** PIPE_FORMAT_B5G5R5X1_UNORM ***/ + +static void +x1r5g5b5_get_tile_rgba(const ushort *src, + unsigned w, unsigned h, + float *p, + unsigned dst_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + const ushort pixel = *src++; + pRow[0] = ((pixel >> 10) & 0x1f) * (1.0f / 31.0f); + pRow[1] = ((pixel >> 5) & 0x1f) * (1.0f / 31.0f); + pRow[2] = ((pixel ) & 0x1f) * (1.0f / 31.0f); + pRow[3] = 1.0f; + } + p += dst_stride; + } +} + + +static void +x1r5g5b5_put_tile_rgba(ushort *dst, + unsigned w, unsigned h, + const float *p, + unsigned src_stride) +{ + unsigned i, j; + + for (i = 0; i < h; i++) { + const float *pRow = p; + for (j = 0; j < w; j++, pRow += 4) { + unsigned r, g, b; + r = float_to_ubyte(pRow[0]); + g = float_to_ubyte(pRow[1]); + b = float_to_ubyte(pRow[2]); + r = r >> 3; /* 5 bits */ + g = g >> 3; /* 5 bits */ + b = b >> 3; /* 5 bits */ + *dst++ = (1 << 15) | (r << 10) | (g << 5) | b; + } + p += src_stride; + } +} + + /*** PIPE_FORMAT_B5G5R5A1_UNORM ***/ static void @@ -1174,6 +1223,9 @@ pipe_tile_raw_to_rgba(enum pipe_format format, case PIPE_FORMAT_A8B8G8R8_UNORM: r8g8b8a8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); break; + case PIPE_FORMAT_B5G5R5X1_UNORM: + x1r5g5b5_get_tile_rgba((ushort *) src, w, h, dst, dst_stride); + break; case PIPE_FORMAT_B5G5R5A1_UNORM: a1r5g5b5_get_tile_rgba((ushort *) src, w, h, dst, dst_stride); break; @@ -1368,6 +1420,9 @@ pipe_put_tile_rgba(struct pipe_context *pipe, case PIPE_FORMAT_A8B8G8R8_UNORM: r8g8b8a8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride); break; + case PIPE_FORMAT_B5G5R5X1_UNORM: + x1r5g5b5_put_tile_rgba((ushort *) packed, w, h, p, src_stride); + break; case PIPE_FORMAT_B5G5R5A1_UNORM: a1r5g5b5_put_tile_rgba((ushort *) packed, w, h, p, src_stride); break; diff --git a/src/gallium/docs/source/context.rst b/src/gallium/docs/source/context.rst index 1f022570db..2b0941010b 100644 --- a/src/gallium/docs/source/context.rst +++ b/src/gallium/docs/source/context.rst @@ -50,6 +50,7 @@ Non-CSO State These pieces of state are too small, variable, and/or trivial to have CSO objects. They all follow simple, one-method binding calls, e.g. ``set_blend_color``. + * ``set_stencil_ref`` sets the stencil front and back reference values which are used as comparison values in stencil test. * ``set_blend_color`` @@ -73,11 +74,11 @@ is being cast to another format. Casting can be done only between compatible formats, that is formats that have matching component order and sizes. Swizzle fields specify they way in which fetched texel components are placed -in the result register. For example, swizzle_r specifies what is going to be -placed in destination register x (AKA r). +in the result register. For example, ``swizzle_r`` specifies what is going to be +placed in first component of result register. -first_level and last_level fields of sampler view template specify the LOD -range the texture is going to be constrained to. +The ``first_level`` and ``last_level`` fields of sampler view template specify +the LOD range the texture is going to be constrained to. * ``set_fragment_sampler_views`` binds an array of sampler views to fragment shader stage. Every binding point acquires a reference @@ -88,7 +89,7 @@ range the texture is going to be constrained to. shader stage. Every binding point acquires a reference to a respective sampler view and releases a reference to the previous sampler view. -* ``create_sampler_view`` creates a new sampler view. texture is associated +* ``create_sampler_view`` creates a new sampler view. ``texture`` is associated with the sampler view which results in sampler view holding a reference to the texture. Format specified in template must be compatible with texture format. diff --git a/src/gallium/docs/source/cso/velems.rst b/src/gallium/docs/source/cso/velems.rst index 8e758fae10..92cde014fb 100644 --- a/src/gallium/docs/source/cso/velems.rst +++ b/src/gallium/docs/source/cso/velems.rst @@ -1,4 +1,4 @@ -.. _vertex,elements +.. _vertexelements: Vertex Elements =============== diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c index 1eee9212e6..927e472ff2 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.c +++ b/src/gallium/drivers/llvmpipe/lp_jit.c @@ -96,7 +96,8 @@ lp_jit_init_globals(struct llvmpipe_screen *screen) elem_types[LP_JIT_CTX_CONSTANTS] = LLVMPointerType(LLVMFloatType(), 0); elem_types[LP_JIT_CTX_ALPHA_REF] = LLVMFloatType(); - elem_types[LP_JIT_CTX_STENCIL_REF] = LLVMArrayType(LLVMInt8Type(), 2); + elem_types[LP_JIT_CTX_STENCIL_REF_FRONT] = LLVMInt32Type(); + elem_types[LP_JIT_CTX_STENCIL_REF_BACK] = LLVMInt32Type(); elem_types[LP_JIT_CTX_SCISSOR_XMIN] = LLVMFloatType(); elem_types[LP_JIT_CTX_SCISSOR_YMIN] = LLVMFloatType(); elem_types[LP_JIT_CTX_SCISSOR_XMAX] = LLVMFloatType(); @@ -113,9 +114,12 @@ lp_jit_init_globals(struct llvmpipe_screen *screen) LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, alpha_ref_value, screen->target, context_type, LP_JIT_CTX_ALPHA_REF); - LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, stencil_ref, + LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, stencil_ref_front, screen->target, context_type, - LP_JIT_CTX_STENCIL_REF); + LP_JIT_CTX_STENCIL_REF_FRONT); + LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, stencil_ref_back, + screen->target, context_type, + LP_JIT_CTX_STENCIL_REF_BACK); LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_xmin, screen->target, context_type, LP_JIT_CTX_SCISSOR_XMIN); diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h index 63e05c5d5e..4930ff02e6 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.h +++ b/src/gallium/drivers/llvmpipe/lp_jit.h @@ -84,7 +84,7 @@ struct lp_jit_context float alpha_ref_value; - uint8_t stencil_ref[2]; + uint32_t stencil_ref_front, stencil_ref_back; /** floats, not ints */ float scissor_xmin, scissor_ymin, scissor_xmax, scissor_ymax; @@ -103,7 +103,8 @@ struct lp_jit_context enum { LP_JIT_CTX_CONSTANTS = 0, LP_JIT_CTX_ALPHA_REF, - LP_JIT_CTX_STENCIL_REF, + LP_JIT_CTX_STENCIL_REF_FRONT, + LP_JIT_CTX_STENCIL_REF_BACK, LP_JIT_CTX_SCISSOR_XMIN, LP_JIT_CTX_SCISSOR_YMIN, LP_JIT_CTX_SCISSOR_XMAX, @@ -120,8 +121,11 @@ enum { #define lp_jit_context_alpha_ref_value(_builder, _ptr) \ lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_ALPHA_REF, "alpha_ref_value") -#define lp_jit_context_stencil_ref_values(_builder, _ptr) \ - lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CTX_STENCIL_REF, "stencil_ref") +#define lp_jit_context_stencil_ref_front_value(_builder, _ptr) \ + lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_STENCIL_REF_FRONT, "stencil_ref_front") + +#define lp_jit_context_stencil_ref_back_value(_builder, _ptr) \ + lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_STENCIL_REF_BACK, "stencil_ref_back") #define lp_jit_context_scissor_xmin_value(_builder, _ptr) \ lp_build_struct_get(_builder, _ptr, LP_JIT_CTX_SCISSOR_XMIN, "scissor_xmin") @@ -142,10 +146,16 @@ enum { lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CONTEXT_TEXTURES, "textures") +/** Indexes into jit_function[] array */ +#define RAST_WHOLE 0 +#define RAST_EDGE_TEST 1 + + typedef void (*lp_jit_frag_func)(const struct lp_jit_context *context, uint32_t x, uint32_t y, + float facing, const void *a0, const void *dadx, const void *dady, diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index 497bfb0994..f5f51f2222 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -312,15 +312,16 @@ lp_rast_shade_tile(struct lp_rasterizer_task *task, depth = lp_rast_depth_pointer(rast, tile_x + x, tile_y + y); /* run shader */ - state->jit_function[0]( &state->jit_context, - tile_x + x, tile_y + y, - inputs->a0, - inputs->dadx, - inputs->dady, - color, - depth, - INT_MIN, INT_MIN, INT_MIN, - NULL, NULL, NULL ); + state->jit_function[RAST_WHOLE]( &state->jit_context, + tile_x + x, tile_y + y, + inputs->facing, + inputs->a0, + inputs->dadx, + inputs->dady, + color, + depth, + INT_MIN, INT_MIN, INT_MIN, + NULL, NULL, NULL ); } } } @@ -375,15 +376,18 @@ void lp_rast_shade_quads( struct lp_rasterizer_task *task, assert(lp_check_alignment(inputs->step[2], 16)); /* run shader */ - state->jit_function[1]( &state->jit_context, - x, y, - inputs->a0, - inputs->dadx, - inputs->dady, - color, - depth, - c1, c2, c3, - inputs->step[0], inputs->step[1], inputs->step[2]); + state->jit_function[RAST_EDGE_TEST]( &state->jit_context, + x, y, + inputs->facing, + inputs->a0, + inputs->dadx, + inputs->dady, + color, + depth, + c1, c2, c3, + inputs->step[0], + inputs->step[1], + inputs->step[2]); } diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h index 303f6e3f7e..ae838f3fbe 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.h +++ b/src/gallium/drivers/llvmpipe/lp_rast.h @@ -82,6 +82,8 @@ struct lp_rast_state { * These pointers point into the bin data buffer. */ struct lp_rast_shader_inputs { + float facing; /** Positive for front-facing, negative for back-facing */ + float (*a0)[4]; float (*dadx)[4]; float (*dady)[4]; diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h index 39bf2c2587..6ee9bcaae3 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h +++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h @@ -195,6 +195,7 @@ lp_rast_shade_quads_all( struct lp_rasterizer_task *task, /* run shader */ state->jit_function[0]( &state->jit_context, x, y, + inputs->facing, inputs->a0, inputs->dadx, inputs->dady, diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 3ee07196ab..c48c3c0f52 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -406,10 +406,10 @@ lp_setup_set_stencil_ref_values( struct lp_setup_context *setup, { LP_DBG(DEBUG_SETUP, "%s %d %d\n", __FUNCTION__, refs[0], refs[1]); - if (setup->fs.current.jit_context.stencil_ref[0] != refs[0] || - setup->fs.current.jit_context.stencil_ref[1] != refs[1]) { - setup->fs.current.jit_context.stencil_ref[0] = refs[0]; - setup->fs.current.jit_context.stencil_ref[1] = refs[1]; + if (setup->fs.current.jit_context.stencil_ref_front != refs[0] || + setup->fs.current.jit_context.stencil_ref_back != refs[1]) { + setup->fs.current.jit_context.stencil_ref_front = refs[0]; + setup->fs.current.jit_context.stencil_ref_back = refs[1]; setup->dirty |= LP_SETUP_NEW_FS; } } diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c index ac6264dc73..ce689d3d56 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c @@ -361,6 +361,8 @@ do_triangle_ccw(struct lp_setup_context *setup, */ setup_tri_coefficients( setup, tri, oneoverarea, v1, v2, v3, frontfacing ); + tri->inputs.facing = frontfacing ? 1.0F : -1.0F; + /* half-edge constants, will be interated over the whole render target. */ tri->c1 = tri->dy12 * x1 - tri->dx12 * y1; diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index e1c82d0374..c57b4a4258 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -144,13 +144,17 @@ generate_depth_stencil(LLVMBuilderRef builder, const struct lp_fragment_shader_variant_key *key, struct lp_type src_type, struct lp_build_mask_context *mask, - LLVMValueRef stencil_refs, + LLVMValueRef stencil_refs[2], LLVMValueRef src, - LLVMValueRef dst_ptr) + LLVMValueRef dst_ptr, + LLVMValueRef facing) { const struct util_format_description *format_desc; struct lp_type dst_type; + if (!key->depth.enabled && !key->stencil[0].enabled && !key->stencil[1].enabled) + return; + format_desc = util_format_description(key->zsbuf_format); assert(format_desc); @@ -189,7 +193,8 @@ generate_depth_stencil(LLVMBuilderRef builder, mask, stencil_refs, src, - dst_ptr); + dst_ptr, + facing); } @@ -389,6 +394,7 @@ generate_fs(struct llvmpipe_context *lp, LLVMValueRef *pmask, LLVMValueRef (*color)[4], LLVMValueRef depth_ptr, + LLVMValueRef facing, unsigned do_tri_test, LLVMValueRef c0, LLVMValueRef c1, @@ -404,7 +410,7 @@ generate_fs(struct llvmpipe_context *lp, LLVMValueRef consts_ptr; LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][NUM_CHANNELS]; LLVMValueRef z = interp->pos[2]; - LLVMValueRef stencil_refs; + LLVMValueRef stencil_refs[2]; struct lp_build_flow_context *flow; struct lp_build_mask_context mask; boolean early_depth_stencil_test; @@ -414,7 +420,8 @@ generate_fs(struct llvmpipe_context *lp, assert(i < 4); - stencil_refs = lp_jit_context_stencil_ref_values(builder, context_ptr); + stencil_refs[0] = lp_jit_context_stencil_ref_front_value(builder, context_ptr); + stencil_refs[1] = lp_jit_context_stencil_ref_back_value(builder, context_ptr); elem_type = lp_build_elem_type(type); vec_type = lp_build_vec_type(type); @@ -464,7 +471,7 @@ generate_fs(struct llvmpipe_context *lp, if (early_depth_stencil_test) generate_depth_stencil(builder, key, type, &mask, - stencil_refs, z, depth_ptr); + stencil_refs, z, depth_ptr, facing); lp_build_tgsi_soa(builder, tokens, type, &mask, consts_ptr, interp->pos, interp->inputs, @@ -511,7 +518,7 @@ generate_fs(struct llvmpipe_context *lp, if (!early_depth_stencil_test) generate_depth_stencil(builder, key, type, &mask, - stencil_refs, z, depth_ptr); + stencil_refs, z, depth_ptr, facing); lp_build_mask_end(&mask); @@ -622,7 +629,7 @@ generate_fragment(struct llvmpipe_context *lp, LLVMTypeRef fs_int_vec_type; LLVMTypeRef blend_vec_type; LLVMTypeRef blend_int_vec_type; - LLVMTypeRef arg_types[14]; + LLVMTypeRef arg_types[15]; LLVMTypeRef func_type; LLVMTypeRef int32_vec4_type = lp_build_int32_vec4_type(); LLVMValueRef context_ptr; @@ -645,6 +652,7 @@ generate_fragment(struct llvmpipe_context *lp, LLVMValueRef blend_mask; LLVMValueRef blend_in_color[NUM_CHANNELS]; LLVMValueRef function; + LLVMValueRef facing; unsigned num_fs; unsigned i; unsigned chan; @@ -684,20 +692,21 @@ generate_fragment(struct llvmpipe_context *lp, arg_types[0] = screen->context_ptr_type; /* context */ arg_types[1] = LLVMInt32Type(); /* x */ arg_types[2] = LLVMInt32Type(); /* y */ - arg_types[3] = LLVMPointerType(fs_elem_type, 0); /* a0 */ - arg_types[4] = LLVMPointerType(fs_elem_type, 0); /* dadx */ - arg_types[5] = LLVMPointerType(fs_elem_type, 0); /* dady */ - arg_types[6] = LLVMPointerType(LLVMPointerType(blend_vec_type, 0), 0); /* color */ - arg_types[7] = LLVMPointerType(fs_int_vec_type, 0); /* depth */ - arg_types[8] = LLVMInt32Type(); /* c0 */ - arg_types[9] = LLVMInt32Type(); /* c1 */ - arg_types[10] = LLVMInt32Type(); /* c2 */ + arg_types[3] = LLVMFloatType(); /* facing */ + arg_types[4] = LLVMPointerType(fs_elem_type, 0); /* a0 */ + arg_types[5] = LLVMPointerType(fs_elem_type, 0); /* dadx */ + arg_types[6] = LLVMPointerType(fs_elem_type, 0); /* dady */ + arg_types[7] = LLVMPointerType(LLVMPointerType(blend_vec_type, 0), 0); /* color */ + arg_types[8] = LLVMPointerType(fs_int_vec_type, 0); /* depth */ + arg_types[9] = LLVMInt32Type(); /* c0 */ + arg_types[10] = LLVMInt32Type(); /* c1 */ + arg_types[11] = LLVMInt32Type(); /* c2 */ /* Note: the step arrays are built as int32[16] but we interpret * them here as int32_vec4[4]. */ - arg_types[11] = LLVMPointerType(int32_vec4_type, 0);/* step0 */ - arg_types[12] = LLVMPointerType(int32_vec4_type, 0);/* step1 */ - arg_types[13] = LLVMPointerType(int32_vec4_type, 0);/* step2 */ + arg_types[12] = LLVMPointerType(int32_vec4_type, 0);/* step0 */ + arg_types[13] = LLVMPointerType(int32_vec4_type, 0);/* step1 */ + arg_types[14] = LLVMPointerType(int32_vec4_type, 0);/* step2 */ func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0); @@ -717,17 +726,18 @@ generate_fragment(struct llvmpipe_context *lp, context_ptr = LLVMGetParam(function, 0); x = LLVMGetParam(function, 1); y = LLVMGetParam(function, 2); - a0_ptr = LLVMGetParam(function, 3); - dadx_ptr = LLVMGetParam(function, 4); - dady_ptr = LLVMGetParam(function, 5); - color_ptr_ptr = LLVMGetParam(function, 6); - depth_ptr = LLVMGetParam(function, 7); - c0 = LLVMGetParam(function, 8); - c1 = LLVMGetParam(function, 9); - c2 = LLVMGetParam(function, 10); - step0_ptr = LLVMGetParam(function, 11); - step1_ptr = LLVMGetParam(function, 12); - step2_ptr = LLVMGetParam(function, 13); + facing = LLVMGetParam(function, 3); + a0_ptr = LLVMGetParam(function, 4); + dadx_ptr = LLVMGetParam(function, 5); + dady_ptr = LLVMGetParam(function, 6); + color_ptr_ptr = LLVMGetParam(function, 7); + depth_ptr = LLVMGetParam(function, 8); + c0 = LLVMGetParam(function, 9); + c1 = LLVMGetParam(function, 10); + c2 = LLVMGetParam(function, 11); + step0_ptr = LLVMGetParam(function, 12); + step1_ptr = LLVMGetParam(function, 13); + step2_ptr = LLVMGetParam(function, 14); lp_build_name(context_ptr, "context"); lp_build_name(x, "x"); @@ -786,6 +796,7 @@ generate_fragment(struct llvmpipe_context *lp, &fs_mask[i], /* output */ out_color, depth_ptr_i, + facing, do_tri_test, c0, c1, c2, step0_ptr, step1_ptr, step2_ptr); @@ -1165,6 +1176,7 @@ llvmpipe_update_fs(struct llvmpipe_context *lp) opaque = !key.blend.logicop_enable && !key.blend.rt[0].blend_enable && key.blend.rt[0].colormask == 0xf && + !key.stencil[0].enabled && !key.alpha.enabled && !key.depth.enabled && !key.scissor && @@ -1172,7 +1184,7 @@ llvmpipe_update_fs(struct llvmpipe_context *lp) ? TRUE : FALSE; lp_setup_set_fs_functions(lp->setup, - shader->current->jit_function[0], - shader->current->jit_function[1], + shader->current->jit_function[RAST_WHOLE], + shader->current->jit_function[RAST_EDGE_TEST], opaque); } diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index d25846f7a0..261117a366 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -71,20 +71,6 @@ static void r300_destroy_context(struct pipe_context* context) } -static unsigned int -r300_is_resource_referenced(struct pipe_context *pipe, - struct pipe_resource *buf, - unsigned face, unsigned level) -{ - /* This only checks to see whether actual hardware buffers are - * referenced. Since we use managed BOs and transfers, it's actually not - * possible for pipe_buffers to ever reference the actual hardware, so - * buffers are never referenced. - */ - - return 0; -} - static void r300_flush_cb(void *data) { struct r300_context* const cs_context_copy = data; @@ -185,10 +171,10 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, draw_set_viewport_state(r300->draw, &r300_viewport_identity); } - r300->context.is_resource_referenced = r300_is_resource_referenced; - r300_setup_atoms(r300); + r300->sprite_coord_index = -1; + /* Open up the OQ BO. */ r300->oqbo = pipe_buffer_create(screen, 4096, PIPE_BUFFER_USAGE_VERTEX, 4096); diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index fe2b78e654..ca15d87d1f 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -99,6 +99,16 @@ struct r300_rs_state { uint32_t line_stipple_value; /* R300_GA_LINE_STIPPLE_VALUE: 0x4260 */ uint32_t color_control; /* R300_GA_COLOR_CONTROL: 0x4278 */ uint32_t polygon_mode; /* R300_GA_POLY_MODE: 0x4288 */ + + /* Specifies top of Raster pipe specific enable controls, + * i.e. texture coordinates stuffing for points, lines, triangles */ + uint32_t stuffing_enable; /* R300_GB_ENABLE: 0x4008 */ + + /* Point sprites texture coordinates, 0: lower left, 1: upper right */ + float point_texcoord_left; /* R300_GA_POINT_S0: 0x4200 */ + float point_texcoord_bottom; /* R300_GA_POINT_T0: 0x4204 */ + float point_texcoord_right; /* R300_GA_POINT_S1: 0x4208 */ + float point_texcoord_top; /* R300_GA_POINT_T1: 0x420c */ }; struct r300_rs_block { @@ -391,6 +401,9 @@ struct r300_context { uint32_t zbuffer_bpp; /* Whether scissor is enabled. */ boolean scissor_enabled; + /* Point sprites texcoord index, -1 = unused. */ + int sprite_coord_index; + /* upload managers */ struct u_upload_mgr *upload_vb; struct u_upload_mgr *upload_ib; diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 1592c9dd5a..cf0d237058 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -616,6 +616,12 @@ void r300_emit_rs_state(struct r300_context* r300, unsigned size, void* state) OUT_CS_REG(R300_GA_LINE_STIPPLE_CONFIG, rs->line_stipple_config); OUT_CS_REG(R300_GA_LINE_STIPPLE_VALUE, rs->line_stipple_value); OUT_CS_REG(R300_GA_POLY_MODE, rs->polygon_mode); + OUT_CS_REG(R300_GB_ENABLE, rs->stuffing_enable); + OUT_CS_REG_SEQ(R300_GA_POINT_S0, 4); + OUT_CS_32F(rs->point_texcoord_left); + OUT_CS_32F(rs->point_texcoord_bottom); + OUT_CS_32F(rs->point_texcoord_right); + OUT_CS_32F(rs->point_texcoord_top); END_CS; } @@ -1044,9 +1050,11 @@ validate: } /* ...textures... */ for (i = 0; i < texstate->count; i++) { - tex = (struct r300_texture*)texstate->fragment_sampler_views[i]->texture; - if (!tex || !texstate->sampler_states[i]) + if (!(texstate->tx_enable & (1 << i))) { continue; + } + + tex = (struct r300_texture*)texstate->fragment_sampler_views[i]->texture; if (!r300_add_texture(r300->rws, tex, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0)) { r300->context.flush(&r300->context, 0, NULL); diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 77ec33e0a8..bcdff8aeb9 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -141,7 +141,7 @@ static boolean immd_is_good_idea(struct r300_context *r300, unsigned vertex_element_count = r300->velems->count; unsigned i, vbi; - if (count > 4) { + if (count > 10) { return FALSE; } @@ -307,10 +307,9 @@ static void r300_emit_draw_elements(struct r300_context *r300, #endif CS_LOCALS(r300); - assert((start * indexSize) % 4 == 0); assert(count < (1 << 24)); - maxIndex = MIN3(maxIndex, r300->vertex_buffer_max_index, count - minIndex); + maxIndex = MIN2(maxIndex, r300->vertex_buffer_max_index); DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n", count, minIndex, maxIndex); @@ -357,6 +356,7 @@ static void r300_emit_draw_elements(struct r300_context *r300, static void r300_shorten_ubyte_elts(struct r300_context* r300, struct pipe_resource** elts, + unsigned start, unsigned count) { struct pipe_context* context = &r300->context; @@ -376,6 +376,8 @@ static void r300_shorten_ubyte_elts(struct r300_context* r300, in_map = pipe_buffer_map(context, *elts, PIPE_BUFFER_USAGE_CPU_READ, &src_transfer); out_map = pipe_buffer_map(context, new_elts, PIPE_BUFFER_USAGE_CPU_WRITE, &dst_transfer); + in_map += start; + for (i = 0; i < count; i++) { *out_map = (unsigned short)*in_map; in_map++; @@ -388,6 +390,32 @@ static void r300_shorten_ubyte_elts(struct r300_context* r300, *elts = new_elts; } +static void r300_align_ushort_elts(struct r300_context *r300, + struct pipe_resource **elts, + unsigned start, unsigned count) +{ + struct pipe_screen* screen = r300->context.screen; + struct pipe_resource* new_elts; + unsigned short *in_map; + unsigned short *out_map; + + new_elts = pipe_buffer_create(screen, 32, + PIPE_BUFFER_USAGE_INDEX | + PIPE_BUFFER_USAGE_CPU_WRITE | + PIPE_BUFFER_USAGE_GPU_READ, + 2 * count); + + in_map = pipe_buffer_map(screen, *elts, PIPE_BUFFER_USAGE_CPU_READ); + out_map = pipe_buffer_map(screen, new_elts, PIPE_BUFFER_USAGE_CPU_WRITE); + + memcpy(out_map, in_map+start, 2 * count); + + pipe_buffer_unmap(screen, *elts); + pipe_buffer_unmap(screen, new_elts); + + *elts = new_elts; +} + /* This is the fast-path drawing & emission for HW TCL. */ void r300_draw_range_elements(struct pipe_context* pipe, struct pipe_resource* indexBuffer, @@ -413,8 +441,12 @@ void r300_draw_range_elements(struct pipe_context* pipe, } if (indexSize == 1) { - r300_shorten_ubyte_elts(r300, &indexBuffer, count); + r300_shorten_ubyte_elts(r300, &indexBuffer, start, count); indexSize = 2; + start = 0; + } else if (indexSize == 2 && start % 2 != 0) { + r300_align_ushort_elts(r300, &indexBuffer, start, count); + start = 0; } r300_update_derived_state(r300); diff --git a/src/gallium/drivers/r300/r300_resource.c b/src/gallium/drivers/r300/r300_resource.c index a63a79efe2..fe779ef515 100644 --- a/src/gallium/drivers/r300/r300_resource.c +++ b/src/gallium/drivers/r300/r300_resource.c @@ -80,6 +80,7 @@ r300_init_resource_functions(struct r300_context *r300) r300->context.transfer_unmap = u_transfer_unmap_vtbl; r300->context.transfer_destroy = u_transfer_destroy_vtbl; r300->context.transfer_inline_write = u_transfer_inline_write_vtbl; + r300->context.is_resource_referenced = u_is_resource_referenced_vtbl; } void diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index e5349abb61..e915d1700d 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -715,6 +715,7 @@ static void* r300_create_rs_state(struct pipe_context* pipe, { struct r300_screen* r300screen = r300_screen(pipe->screen); struct r300_rs_state* rs = CALLOC_STRUCT(r300_rs_state); + unsigned coord_index; /* Copy rasterizer state for Draw. */ rs->rs = *state; @@ -807,6 +808,32 @@ static void* r300_create_rs_state(struct pipe_context* pipe, rs->color_control = R300_SHADE_MODEL_SMOOTH; } + /* Point sprites */ + if (state->sprite_coord_enable) { + coord_index = ffs(state->sprite_coord_enable)-1; + + SCREEN_DBG(r300screen, DBG_DRAW, + "r300: point sprite: shader coord=%d\n", coord_index); + + rs->stuffing_enable = + R300_GB_POINT_STUFF_ENABLE | + R300_GB_TEX_ST << (R300_GB_TEX0_SOURCE_SHIFT + (coord_index*2)); + + rs->point_texcoord_left = 0.0f; + rs->point_texcoord_right = 1.0f; + + switch (state->sprite_coord_mode) { + case PIPE_SPRITE_COORD_UPPER_LEFT: + rs->point_texcoord_top = 0.0f; + rs->point_texcoord_bottom = 1.0f; + break; + case PIPE_SPRITE_COORD_LOWER_LEFT: + rs->point_texcoord_top = 1.0f; + rs->point_texcoord_bottom = 0.0f; + break; + } + } + return (void*)rs; } @@ -816,6 +843,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) struct r300_context* r300 = r300_context(pipe); struct r300_rs_state* rs = (struct r300_rs_state*)state; boolean scissor_was_enabled = r300->scissor_enabled; + int last_sprite_coord_index = r300->sprite_coord_index; if (r300->draw) { draw_flush(r300->draw); @@ -825,17 +853,22 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) if (rs) { r300->polygon_offset_enabled = rs->rs.offset_cw || rs->rs.offset_ccw; r300->scissor_enabled = rs->rs.scissor; + r300->sprite_coord_index = ffs(rs->rs.sprite_coord_enable)-1; } else { r300->polygon_offset_enabled = FALSE; r300->scissor_enabled = FALSE; + r300->sprite_coord_index = -1; } UPDATE_STATE(state, r300->rs_state); - r300->rs_state.size = 17 + (r300->polygon_offset_enabled ? 5 : 0); + r300->rs_state.size = 24 + (r300->polygon_offset_enabled ? 5 : 0); if (scissor_was_enabled != r300->scissor_enabled) { r300->scissor_state.dirty = TRUE; } + if (last_sprite_coord_index != r300->sprite_coord_index) { + r300->rs_block_state.dirty = TRUE; + } } /* Free rasterizer state. */ @@ -940,6 +973,7 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); struct r300_textures_state* state = (struct r300_textures_state*)r300->textures_state.state; + struct r300_texture *texture; unsigned i; boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500; boolean dirty_tex = FALSE; @@ -951,15 +985,18 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe, for (i = 0; i < count; i++) { if (state->fragment_sampler_views[i] != views[i]) { - struct r300_texture *texture; - pipe_sampler_view_reference(&state->fragment_sampler_views[i], views[i]); - dirty_tex = TRUE; - texture = (struct r300_texture *)views[i]->texture; + if (!views[i]) { + continue; + } + + /* A new sampler view (= texture)... */ + dirty_tex = TRUE; /* R300-specific - set the texrect factor in the fragment shader */ + texture = (struct r300_texture *)views[i]->texture; if (!is_r500 && texture->is_npot) { /* XXX It would be nice to re-emit just 1 constant, * XXX not all of them */ @@ -1002,7 +1039,6 @@ r300_create_sampler_view(struct pipe_context *pipe, return view; } - static void r300_sampler_view_destroy(struct pipe_context *pipe, struct pipe_sampler_view *view) @@ -1072,26 +1108,62 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, const struct pipe_vertex_buffer* buffers) { struct r300_context* r300 = r300_context(pipe); - int i; - unsigned max_index = (1 << 24) - 1; - boolean any_user_buffer = false; + struct pipe_vertex_buffer *vbo; + unsigned i, max_index = (1 << 24) - 1; + boolean any_user_buffer = FALSE; if (count == r300->vertex_buffer_count && - memcmp(r300->vertex_buffer, buffers, count * sizeof(buffers[0])) == 0) + memcmp(r300->vertex_buffer, buffers, + sizeof(struct pipe_vertex_buffer) * count) == 0) { return; + } + /* Check if the stride is aligned to the size of DWORD. */ for (i = 0; i < count; i++) { - pipe_resource_reference(&r300->vertex_buffer[i].buffer, buffers[i].buffer); - if (r300_buffer_is_user_buffer(buffers[i].buffer)) - any_user_buffer = true; - max_index = MIN2(buffers[i].max_index, max_index); + if (buffers[i].buffer) { + if (buffers[i].stride % 4 != 0) { + // XXX Shouldn't we align the buffer? + fprintf(stderr, "r300_set_vertex_buffers: " + "Unaligned buffer stride %i isn't supported.\n", + buffers[i].stride); + assert(0); + abort(); + } + } } - for ( ; i < r300->vertex_buffer_count; i++) - pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL); + for (i = 0; i < count; i++) { + /* Why, yes, I AM casting away constness. How did you know? */ + vbo = (struct pipe_vertex_buffer*)&buffers[i]; + + /* Reference our buffer. */ + pipe_resource_reference(&r300->vertex_buffer[i].buffer, vbo->buffer); + + /* Skip NULL buffers */ + if (!buffers[i].buffer) { + continue; + } + + if (r300_buffer_is_user_buffer(vbo->buffer)) { + any_user_buffer = TRUE; + } + + if (vbo->max_index == ~0) { + /* Bogus value from broken state tracker; hax it. */ + vbo->max_index = + (vbo->buffer->size - vbo->buffer_offset) / vbo->stride; + } + + max_index = MIN2(vbo->max_index, max_index); + } + + for (; i < r300->vertex_buffer_count; i++) { + /* Dereference any old buffers. */ + pipe_resource_reference(&r300->vertex_buffer[i].buffer, NULL); + } memcpy(r300->vertex_buffer, buffers, - sizeof(struct pipe_vertex_buffer) * count); + sizeof(struct pipe_vertex_buffer) * count); r300->vertex_buffer_count = count; r300->vertex_buffer_max_index = max_index; @@ -1103,22 +1175,6 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, } } -static boolean r300_validate_aos(struct r300_context *r300) -{ - struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; - struct pipe_vertex_element *velem = r300->velems->velem; - int i; - - /* Check if formats and strides are aligned to the size of DWORD. */ - for (i = 0; i < r300->velems->count; i++) { - if (vbuf[velem[i].vertex_buffer_index].stride % 4 != 0 || - util_format_get_blocksize(velem[i].src_format) % 4 != 0) { - return FALSE; - } - } - return TRUE; -} - static void r300_draw_emit_attrib(struct r300_context* r300, enum attrib_emit emit, enum interp_mode interp, @@ -1288,6 +1344,7 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, struct r300_context *r300 = r300_context(pipe); struct r300_screen* r300screen = r300_screen(pipe->screen); struct r300_vertex_element_state *velems; + unsigned i, size; assert(count <= PIPE_MAX_ATTRIBS); velems = CALLOC_STRUCT(r300_vertex_element_state); @@ -1296,6 +1353,20 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count); if (r300screen->caps->has_tcl) { + /* Check if the format is aligned to the size of DWORD. */ + for (i = 0; i < count; i++) { + size = util_format_get_blocksize(attribs[i].src_format); + + if (size % 4 != 0) { + /* XXX Shouldn't we align the format? */ + fprintf(stderr, "r300_create_vertex_elements_state: " + "Unaligned format %s:%i isn't supported\n", + util_format_name(attribs[i].src_format), size); + assert(0); + abort(); + } + } + r300_vertex_psc(velems); } else { memset(&r300->vertex_info, 0, sizeof(struct vertex_info)); @@ -1324,12 +1395,6 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe, draw_set_vertex_elements(r300->draw, velems->count, velems->velem); } - if (!r300_validate_aos(r300)) { - /* XXX We should fallback using draw. */ - assert(0); - abort(); - } - UPDATE_STATE(&velems->vertex_stream, r300->vertex_stream_state); r300->vertex_stream_state.size = (1 + velems->vertex_stream.count) * 2; } diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index fc212d2083..1114cfdf0c 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -178,7 +178,8 @@ static void r300_update_rs_block(struct r300_context* r300, /* Rasterize texture coordinates. */ for (i = 0; i < ATTR_GENERIC_COUNT; i++) { - if (vs_outputs->generic[i] != ATTR_UNUSED) { + if (vs_outputs->generic[i] != ATTR_UNUSED || + r300->sprite_coord_index == i) { /* Always rasterize if it's written by the VS, * otherwise it locks up. */ rX00_rs_tex(&rs, tex_count, tex_count, FALSE); @@ -186,6 +187,8 @@ static void r300_update_rs_block(struct r300_context* r300, /* Write it to the FS input register if it's used by the FS. */ if (fs_inputs->generic[i] != ATTR_UNUSED) { rX00_rs_tex_write(&rs, tex_count, fp_offset); + if (r300->sprite_coord_index == i) + debug_printf("r300: SpriteCoord (generic index %i) is being written to reg %i\n", i, fp_offset); fp_offset++; } tex_count++; @@ -332,20 +335,25 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) (struct r300_textures_state*)r300->textures_state.state; struct r300_texture_sampler_state *texstate; struct r300_sampler_state *sampler; + struct pipe_sampler_view *view; struct r300_texture *tex; unsigned min_level, max_level, i, size; unsigned count = MIN2(state->texture_count, state->sampler_count); state->tx_enable = 0; + state->count = 0; size = 2; for (i = 0; i < count; i++) { if (state->fragment_sampler_views[i] && state->sampler_states[i]) { state->tx_enable |= 1 << i; - tex = (struct r300_texture *)state->fragment_sampler_views[i]->texture; + view = state->fragment_sampler_views[i]; + tex = (struct r300_texture *)view->texture; sampler = state->sampler_states[i]; + assert(view->format == tex->tex.format); + texstate = &state->regs[i]; memcpy(texstate->format, &tex->state, sizeof(uint32_t)*3); texstate->filter[0] = sampler->filter0; @@ -367,8 +375,10 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300) } else { /* determine min/max levels */ /* the MAX_MIP level is the largest (finest) one */ - max_level = MIN2(sampler->max_lod, tex->b.b.last_level); - min_level = MIN2(sampler->min_lod, max_level); + max_level = MIN3(sampler->max_lod + view->first_level, + tex->b.b.last_level, view->last_level); + min_level = MIN2(sampler->min_lod + view->first_level, + max_level); texstate->format[0] |= R300_TX_NUM_LEVELS(max_level); texstate->filter[0] |= R300_TX_MAX_MIP_LEVEL(min_level); } diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c index 4a2c68269b..2d9a63d29a 100644 --- a/src/gallium/drivers/r300/r300_state_invariant.c +++ b/src/gallium/drivers/r300/r300_state_invariant.c @@ -44,13 +44,9 @@ void r300_emit_invariant_state(struct r300_context* r300, struct r300_capabilities* caps = r300_screen(r300->context.screen)->caps; CS_LOCALS(r300); - BEGIN_CS(14 + (caps->has_tcl ? 2: 0)); + BEGIN_CS(12 + (caps->has_tcl ? 2: 0)); /*** Graphics Backend (GB) ***/ - /* Various GB enables */ - OUT_CS_REG(R300_GB_ENABLE, R300_GB_POINT_STUFF_ENABLE | - R300_GB_LINE_STUFF_ENABLE | - R300_GB_TRIANGLE_STUFF_ENABLE); /* Subpixel multisampling for AA * These are commented out because glisse's CS checker doesn't like them. * I presume these will be re-enabled later. @@ -78,7 +74,7 @@ void r300_emit_invariant_state(struct r300_context* r300, END_CS; /* XXX unsorted stuff from surface_fill */ - BEGIN_CS(44 + (caps->has_tcl ? 7 : 0) + + BEGIN_CS(40 + (caps->has_tcl ? 7 : 0) + (caps->family >= CHIP_FAMILY_RV350 ? 4 : 0)); if (caps->has_tcl) { @@ -90,11 +86,6 @@ void r300_emit_invariant_state(struct r300_context* r300, OUT_CS_32F(1.0); OUT_CS_32F(1.0); } - /* XXX point tex stuffing */ - OUT_CS_REG_SEQ(R300_GA_POINT_S0, 1); - OUT_CS_32F(0.0); - OUT_CS_REG_SEQ(R300_GA_POINT_S1, 1); - OUT_CS_32F(1.0); /* XXX line tex stuffing */ OUT_CS_REG_SEQ(R300_GA_LINE_S0, 1); OUT_CS_32F(0.0); diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 21c51f9cb8..1e3052e51c 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -303,7 +303,6 @@ static uint32_t r300_translate_colorformat(enum pipe_format format) case PIPE_FORMAT_A8_UNORM: case PIPE_FORMAT_I8_UNORM: case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_L8_SRGB: case PIPE_FORMAT_R8_UNORM: case PIPE_FORMAT_R8_SNORM: return R300_COLOR_FORMAT_I8; @@ -312,24 +311,19 @@ static uint32_t r300_translate_colorformat(enum pipe_format format) case PIPE_FORMAT_B5G6R5_UNORM: return R300_COLOR_FORMAT_RGB565; case PIPE_FORMAT_B5G5R5A1_UNORM: + case PIPE_FORMAT_B5G5R5X1_UNORM: return R300_COLOR_FORMAT_ARGB1555; case PIPE_FORMAT_B4G4R4A4_UNORM: return R300_COLOR_FORMAT_ARGB4444; /* 32-bit buffers. */ case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_B8G8R8A8_SRGB: case PIPE_FORMAT_B8G8R8X8_UNORM: - case PIPE_FORMAT_B8G8R8X8_SRGB: case PIPE_FORMAT_A8R8G8B8_UNORM: - case PIPE_FORMAT_A8R8G8B8_SRGB: case PIPE_FORMAT_X8R8G8B8_UNORM: - case PIPE_FORMAT_X8R8G8B8_SRGB: case PIPE_FORMAT_A8B8G8R8_UNORM: case PIPE_FORMAT_R8G8B8A8_SNORM: - case PIPE_FORMAT_A8B8G8R8_SRGB: case PIPE_FORMAT_X8B8G8R8_UNORM: - case PIPE_FORMAT_X8B8G8R8_SRGB: case PIPE_FORMAT_R8SG8SB8UX8U_NORM: return R300_COLOR_FORMAT_ARGB8888; case PIPE_FORMAT_R10G10B10A2_UNORM: @@ -394,12 +388,7 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) desc = util_format_description(format); /* Specifies how the shader output is written to the fog unit. */ - if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) { - /* The gamma correction causes precision loss so we need - * higher precision to maintain reasonable quality. - * It has nothing to do with the colorbuffer format. */ - modifier |= R300_US_OUT_FMT_C4_10_GAMMA; - } else if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) { + if (desc->channel[0].type == UTIL_FORMAT_TYPE_FLOAT) { if (desc->channel[0].size == 32) { modifier |= R300_US_OUT_FMT_C4_32_FP; } else { @@ -429,46 +418,39 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) return modifier | R300_C2_SEL_A; case PIPE_FORMAT_I8_UNORM: case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_L8_SRGB: case PIPE_FORMAT_R8_UNORM: case PIPE_FORMAT_R8_SNORM: return modifier | R300_C2_SEL_R; - /* ARGB 32-bit outputs. */ + /* BGRA outputs. */ case PIPE_FORMAT_B5G6R5_UNORM: case PIPE_FORMAT_B5G5R5A1_UNORM: + case PIPE_FORMAT_B5G5R5X1_UNORM: case PIPE_FORMAT_B4G4R4A4_UNORM: case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_B8G8R8A8_SRGB: case PIPE_FORMAT_B8G8R8X8_UNORM: - case PIPE_FORMAT_B8G8R8X8_SRGB: return modifier | R300_C0_SEL_B | R300_C1_SEL_G | R300_C2_SEL_R | R300_C3_SEL_A; - /* BGRA 32-bit outputs. */ + /* ARGB outputs. */ case PIPE_FORMAT_A8R8G8B8_UNORM: - case PIPE_FORMAT_A8R8G8B8_SRGB: case PIPE_FORMAT_X8R8G8B8_UNORM: - case PIPE_FORMAT_X8R8G8B8_SRGB: return modifier | R300_C0_SEL_A | R300_C1_SEL_R | R300_C2_SEL_G | R300_C3_SEL_B; - /* RGBA 32-bit outputs. */ + /* ABGR outputs. */ case PIPE_FORMAT_A8B8G8R8_UNORM: - case PIPE_FORMAT_R8G8B8A8_SNORM: - case PIPE_FORMAT_A8B8G8R8_SRGB: case PIPE_FORMAT_X8B8G8R8_UNORM: - case PIPE_FORMAT_X8B8G8R8_SRGB: return modifier | R300_C0_SEL_A | R300_C1_SEL_B | R300_C2_SEL_G | R300_C3_SEL_R; - /* ABGR 32-bit outputs. */ + /* RGBA outputs. */ + case PIPE_FORMAT_R8G8B8A8_SNORM: case PIPE_FORMAT_R8SG8SB8UX8U_NORM: case PIPE_FORMAT_R10G10B10A2_UNORM: - /* RGBA high precision outputs (same swizzles as ABGR low precision) */ case PIPE_FORMAT_R16G16B16A16_UNORM: case PIPE_FORMAT_R16G16B16A16_SNORM: //case PIPE_FORMAT_R16G16B16A16_FLOAT: /* not in pipe_format */ diff --git a/src/gallium/include/pipe/p_format.h b/src/gallium/include/pipe/p_format.h index cbf3273ec8..ba2985f449 100644 --- a/src/gallium/include/pipe/p_format.h +++ b/src/gallium/include/pipe/p_format.h @@ -157,6 +157,7 @@ enum pipe_format { PIPE_FORMAT_DXT5_SRGBA = 109, PIPE_FORMAT_A8B8G8R8_UNORM = 110, + PIPE_FORMAT_B5G5R5X1_UNORM = 111, PIPE_FORMAT_COUNT }; diff --git a/src/gallium/state_trackers/dri/Makefile b/src/gallium/state_trackers/dri/Makefile index ef8f19709a..f5af8aa3a6 100644 --- a/src/gallium/state_trackers/dri/Makefile +++ b/src/gallium/state_trackers/dri/Makefile @@ -15,7 +15,9 @@ C_SOURCES = \ dri_context.c \ dri_screen.c \ dri_drawable.c \ - dri_extensions.c + dri_extensions.c \ + dri_st_api.c \ + dri1.c # $(TOP)/src/mesa/drivers/dri/common/utils.c \ $(TOP)/src/mesa/drivers/dri/common/vblank.c \ diff --git a/src/gallium/state_trackers/dri/SConscript b/src/gallium/state_trackers/dri/SConscript index ce2c273597..7c67ceecd8 100644 --- a/src/gallium/state_trackers/dri/SConscript +++ b/src/gallium/state_trackers/dri/SConscript @@ -18,6 +18,8 @@ if env['dri']: 'dri_drawable.c', 'dri_extensions.c', 'dri_screen.c', + 'dri_st_api.c', + 'dri1.c', ] ) Export('st_dri') diff --git a/src/gallium/state_trackers/dri/dri1.c b/src/gallium/state_trackers/dri/dri1.c new file mode 100644 index 0000000000..240bc69efd --- /dev/null +++ b/src/gallium/state_trackers/dri/dri1.c @@ -0,0 +1,583 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Author: Keith Whitwell <keithw@vmware.com> + * Author: Jakob Bornecrantz <wallbraker@gmail.com> + */ + +/* XXX DRI1 is untested after the switch to st_api.h */ + +#include "util/u_memory.h" +#include "util/u_rect.h" +#include "util/u_inlines.h" +#include "pipe/p_context.h" +#include "state_tracker/dri1_api.h" + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_drawable.h" +#include "dri_st_api.h" +#include "dri1.h" + +static INLINE void +dri1_lock(struct dri_context *ctx) +{ + drm_context_t hw_context = ctx->cPriv->hHWContext; + char ret = 0; + + DRM_CAS(ctx->lock, hw_context, DRM_LOCK_HELD | hw_context, ret); + if (ret) { + drmGetLock(ctx->sPriv->fd, hw_context, 0); + ctx->stLostLock = TRUE; + ctx->wsLostLock = TRUE; + } + ctx->isLocked = TRUE; +} + +static INLINE void +dri1_unlock(struct dri_context *ctx) +{ + ctx->isLocked = FALSE; + DRM_UNLOCK(ctx->sPriv->fd, ctx->lock, ctx->cPriv->hHWContext); +} + +static struct pipe_fence_handle * +dri_swap_fences_pop_front(struct dri_drawable *draw) +{ + struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen; + struct pipe_fence_handle *fence = NULL; + + if (draw->cur_fences >= draw->desired_fences) { + screen->fence_reference(screen, &fence, draw->swap_fences[draw->tail]); + screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL); + --draw->cur_fences; + draw->tail &= DRI_SWAP_FENCES_MASK; + } + return fence; +} + +static void +dri_swap_fences_push_back(struct dri_drawable *draw, + struct pipe_fence_handle *fence) +{ + struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen; + + if (!fence) + return; + + if (draw->cur_fences < DRI_SWAP_FENCES_MAX) { + draw->cur_fences++; + screen->fence_reference(screen, &draw->swap_fences[draw->head++], + fence); + draw->head &= DRI_SWAP_FENCES_MASK; + } +} + +void +dri1_swap_fences_clear(struct dri_drawable *drawable) +{ + struct pipe_screen *screen = dri_screen(drawable->sPriv)->pipe_screen; + struct pipe_fence_handle *fence; + + while (drawable->cur_fences) { + fence = dri_swap_fences_pop_front(drawable); + screen->fence_reference(screen, &fence, NULL); + } +} + +static void +dri1_update_drawables_locked(struct dri_context *ctx, + __DRIdrawable * driDrawPriv, + __DRIdrawable * driReadPriv) +{ + if (ctx->stLostLock) { + ctx->stLostLock = FALSE; + if (driDrawPriv == driReadPriv) + DRI_VALIDATE_DRAWABLE_INFO(ctx->sPriv, driDrawPriv); + else + DRI_VALIDATE_TWO_DRAWABLES_INFO(ctx->sPriv, driDrawPriv, + driReadPriv); + } +} + +/** + * This ensures all contexts which bind to a drawable pick up the + * drawable change and signal new buffer state. + */ +static void +dri1_propagate_drawable_change(struct dri_context *ctx) +{ + __DRIdrawable *dPriv = ctx->dPriv; + __DRIdrawable *rPriv = ctx->rPriv; + struct dri_drawable *draw = dri_drawable(dPriv); + struct dri_drawable *read = dri_drawable(rPriv); + boolean flushed = FALSE; + + if (dPriv && draw->texture_stamp != dPriv->lastStamp) { + ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + flushed = TRUE; + ctx->st->notify_invalid_framebuffer(ctx->st, draw->stfb); + } + + if (rPriv && dPriv != rPriv && read->texture_stamp != rPriv->lastStamp) { + if (!flushed) + ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + ctx->st->notify_invalid_framebuffer(ctx->st, read->stfb); + } +} + +static INLINE boolean +dri1_intersect_src_bbox(struct drm_clip_rect *dst, + int dst_x, + int dst_y, + const struct drm_clip_rect *src, + const struct drm_clip_rect *bbox) +{ + int xy1; + int xy2; + + xy1 = ((int)src->x1 > (int)bbox->x1 + dst_x) ? src->x1 : + (int)bbox->x1 + dst_x; + xy2 = ((int)src->x2 < (int)bbox->x2 + dst_x) ? src->x2 : + (int)bbox->x2 + dst_x; + if (xy1 >= xy2 || xy1 < 0) + return FALSE; + + dst->x1 = xy1; + dst->x2 = xy2; + + xy1 = ((int)src->y1 > (int)bbox->y1 + dst_y) ? src->y1 : + (int)bbox->y1 + dst_y; + xy2 = ((int)src->y2 < (int)bbox->y2 + dst_y) ? src->y2 : + (int)bbox->y2 + dst_y; + if (xy1 >= xy2 || xy1 < 0) + return FALSE; + + dst->y1 = xy1; + dst->y2 = xy2; + return TRUE; +} + +static void +dri1_swap_copy(struct pipe_context *pipe, + struct pipe_surface *dst, + struct pipe_surface *src, + __DRIdrawable * dPriv, const struct drm_clip_rect *bbox) +{ + struct drm_clip_rect clip; + struct drm_clip_rect *cur; + int i; + + cur = dPriv->pClipRects; + + for (i = 0; i < dPriv->numClipRects; ++i) { + if (dri1_intersect_src_bbox(&clip, dPriv->x, dPriv->y, cur++, bbox)) { + if (pipe->surface_copy) { + pipe->surface_copy(pipe, dst, clip.x1, clip.y1, + src, + (int)clip.x1 - dPriv->x, + (int)clip.y1 - dPriv->y, + clip.x2 - clip.x1, clip.y2 - clip.y1); + } else { + util_surface_copy(pipe, FALSE, dst, clip.x1, clip.y1, + src, + (int)clip.x1 - dPriv->x, + (int)clip.y1 - dPriv->y, + clip.x2 - clip.x1, clip.y2 - clip.y1); + } + } + } +} + +static struct pipe_surface * +dri1_get_pipe_surface(struct dri_drawable *drawable, struct pipe_texture *ptex) +{ + struct pipe_screen *pipe_screen = dri_screen(drawable->sPriv)->pipe_screen; + struct pipe_surface *psurf = drawable->dri1_surface; + + if (!psurf || psurf->texture != ptex) { + pipe_surface_reference(&drawable->dri1_surface, NULL); + + drawable->dri1_surface = pipe_screen->get_tex_surface(pipe_screen, + ptex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ); + + psurf = drawable->dri1_surface; + } + + return psurf; +} + +static struct pipe_context * +dri1_get_pipe_context(struct dri_drawable *drawable) +{ + struct dri_screen *screen = dri_screen(drawable->sPriv); + struct pipe_context *pipe = screen->dri1_pipe; + + if (!pipe) { + screen->dri1_pipe = + screen->pipe_screen->context_create(screen->pipe_screen, NULL); + pipe = screen->dri1_pipe; + } + + return pipe; +} + +static void +dri1_present_texture_locked(__DRIdrawable * dPriv, + struct pipe_texture *ptex, + const struct drm_clip_rect *sub_box, + struct pipe_fence_handle **fence) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct pipe_context *pipe; + struct pipe_surface *psurf; + struct drm_clip_rect bbox; + boolean visible = TRUE; + + *fence = NULL; + + bbox.x1 = 0; + bbox.x2 = ptex->width0; + bbox.y1 = 0; + bbox.y2 = ptex->height0; + + if (sub_box) + visible = dri1_intersect_src_bbox(&bbox, 0, 0, &bbox, sub_box); + if (!visible) + return; + + pipe = dri1_get_pipe_context(drawable); + psurf = dri1_get_pipe_surface(drawable, ptex); + if (!pipe || !psurf) + return; + + if (__dri1_api_hooks->present_locked) { + __dri1_api_hooks->present_locked(pipe, psurf, + dPriv->pClipRects, dPriv->numClipRects, + dPriv->x, dPriv->y, &bbox, fence); + } else if (__dri1_api_hooks->front_srf_locked) { + struct pipe_surface *front = __dri1_api_hooks->front_srf_locked(pipe); + + if (front) + dri1_swap_copy(pipe, front, psurf, dPriv, &bbox); + + pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, fence); + } +} + +static void +dri1_copy_to_front(struct dri_context *ctx, + struct pipe_texture *ptex, + __DRIdrawable * dPriv, + const struct drm_clip_rect *sub_box, + struct pipe_fence_handle **fence) +{ + boolean save_lost_lock; + + dri1_lock(ctx); + save_lost_lock = ctx->stLostLock; + dri1_update_drawables_locked(ctx, dPriv, dPriv); + + dri1_present_texture_locked(dPriv, ptex, sub_box, fence); + + ctx->stLostLock = save_lost_lock; + + /** + * FIXME: Revisit this: Update drawables on copy_sub_buffer ? + */ + + if (!sub_box) + dri1_update_drawables_locked(ctx, ctx->dPriv, ctx->rPriv); + + dri1_unlock(ctx); + dri1_propagate_drawable_change(ctx); +} + +void +dri1_flush_frontbuffer(struct dri_drawable *drawable, + struct pipe_texture *ptex) +{ + struct st_api *stapi = dri_get_st_api(); + struct dri_screen *screen = dri_screen(drawable->sPriv); + struct pipe_screen *pipe_screen = screen->pipe_screen; + struct dri_context *ctx; + struct pipe_fence_handle *dummy_fence; + struct st_context_iface *st = stapi->get_current(stapi); + + if (!st) + return; + + ctx = (struct dri_context *) st->st_manager_private; + + dri1_copy_to_front(ctx, ptex, ctx->dPriv, NULL, &dummy_fence); + pipe_screen->fence_reference(pipe_screen, &dummy_fence, NULL); + + /** + * FIXME: Do we need swap throttling here? + */ +} + +void +dri1_swap_buffers(__DRIdrawable * dPriv) +{ + struct dri_context *ctx = dri_get_current(); + struct dri_drawable *draw = dri_drawable(dPriv); + struct dri_screen *screen = dri_screen(draw->sPriv); + struct pipe_screen *pipe_screen = screen->pipe_screen; + struct pipe_fence_handle *fence; + struct pipe_texture *ptex; + + assert(__dri1_api_hooks != NULL); + + if (!ctx) + return; /* For now */ + + ptex = draw->textures[ST_ATTACHMENT_BACK_LEFT]; + if (ptex) { + ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + fence = dri_swap_fences_pop_front(draw); + if (fence) { + (void)pipe_screen->fence_finish(pipe_screen, fence, 0); + pipe_screen->fence_reference(pipe_screen, &fence, NULL); + } + dri1_copy_to_front(ctx, ptex, dPriv, NULL, &fence); + dri_swap_fences_push_back(draw, fence); + pipe_screen->fence_reference(pipe_screen, &fence, NULL); + } +} + +void +dri1_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h) +{ + struct dri_context *ctx = dri_get_current(); + struct dri_screen *screen = dri_screen(dPriv->driScreenPriv); + struct pipe_screen *pipe_screen = screen->pipe_screen; + struct drm_clip_rect sub_bbox; + struct dri_drawable *draw = dri_drawable(dPriv); + struct pipe_fence_handle *dummy_fence; + struct pipe_texture *ptex; + + assert(__dri1_api_hooks != NULL); + + if (!ctx) + return; + + sub_bbox.x1 = x; + sub_bbox.x2 = x + w; + sub_bbox.y1 = y; + sub_bbox.y2 = y + h; + + ptex = draw->textures[ST_ATTACHMENT_BACK_LEFT]; + if (ptex) { + ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + dri1_copy_to_front(ctx, ptex, dPriv, &sub_bbox, &dummy_fence); + pipe_screen->fence_reference(pipe_screen, &dummy_fence, NULL); + } +} + +void +dri1_allocate_textures(struct dri_drawable *drawable, + unsigned width, unsigned height, + unsigned mask) +{ + struct dri_screen *screen = dri_screen(drawable->sPriv); + struct pipe_texture templ; + int i; + + /* remove outdated textures */ + if (drawable->old_w != width || drawable->old_h != height) { + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_texture_reference(&drawable->textures[i], NULL); + } + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.last_level = 0; + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + enum pipe_format format; + unsigned tex_usage; + + /* the texture already exists or not requested */ + if (drawable->textures[i] || !(mask & (1 << i))) { + /* remember the texture */ + if (drawable->textures[i]) + mask |= (1 << i); + continue; + } + + switch (i) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_BACK_LEFT: + case ST_ATTACHMENT_FRONT_RIGHT: + case ST_ATTACHMENT_BACK_RIGHT: + format = drawable->stvis.color_format; + tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_RENDER_TARGET; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + format = drawable->stvis.depth_stencil_format; + tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; + break; + default: + format = PIPE_FORMAT_NONE; + break; + } + + if (format != PIPE_FORMAT_NONE) { + templ.format = format; + templ.tex_usage = tex_usage; + + drawable->textures[i] = + screen->pipe_screen->texture_create(screen->pipe_screen, &templ); + } + } + + drawable->old_w = width; + drawable->old_h = height; + drawable->texture_mask = mask; +} + +static void +st_dri_lock(struct pipe_context *pipe) +{ + dri1_lock((struct dri_context *)pipe->priv); +} + +static void +st_dri_unlock(struct pipe_context *pipe) +{ + dri1_unlock((struct dri_context *)pipe->priv); +} + +static boolean +st_dri_is_locked(struct pipe_context *pipe) +{ + return ((struct dri_context *)pipe->priv)->isLocked; +} + +static boolean +st_dri_lost_lock(struct pipe_context *pipe) +{ + return ((struct dri_context *)pipe->priv)->wsLostLock; +} + +static void +st_dri_clear_lost_lock(struct pipe_context *pipe) +{ + ((struct dri_context *)pipe->priv)->wsLostLock = FALSE; +} + +static struct dri1_api_lock_funcs dri1_lf = { + .lock = st_dri_lock, + .unlock = st_dri_unlock, + .is_locked = st_dri_is_locked, + .is_lock_lost = st_dri_lost_lock, + .clear_lost_lock = st_dri_clear_lost_lock +}; + +static const __DRIextension *dri1_screen_extensions[] = { + &driReadDrawableExtension, + &driCopySubBufferExtension.base, + &driSwapControlExtension.base, + &driFrameTrackingExtension.base, + &driMediaStreamCounterExtension.base, + NULL +}; + +struct dri1_api *__dri1_api_hooks = NULL; + +static INLINE void +dri1_copy_version(struct dri1_api_version *dst, + const struct __DRIversionRec *src) +{ + dst->major = src->major; + dst->minor = src->minor; + dst->patch_level = src->patch; +} + +const __DRIconfig ** +dri1_init_screen(__DRIscreen * sPriv) +{ + struct dri_screen *screen; + const __DRIconfig **configs; + struct dri1_create_screen_arg arg; + + screen = CALLOC_STRUCT(dri_screen); + if (!screen) + return NULL; + + screen->api = drm_api_create(); + screen->sPriv = sPriv; + screen->fd = sPriv->fd; + screen->drmLock = (drmLock *) & sPriv->pSAREA->lock; + + sPriv->private = (void *)screen; + sPriv->extensions = dri1_screen_extensions; + + arg.base.mode = DRM_CREATE_DRI1; + arg.lf = &dri1_lf; + arg.ddx_info = sPriv->pDevPriv; + arg.ddx_info_size = sPriv->devPrivSize; + arg.sarea = sPriv->pSAREA; + dri1_copy_version(&arg.ddx_version, &sPriv->ddx_version); + dri1_copy_version(&arg.dri_version, &sPriv->dri_version); + dri1_copy_version(&arg.drm_version, &sPriv->drm_version); + arg.api = NULL; + + screen->pipe_screen = screen->api->create_screen(screen->api, screen->fd, &arg.base); + + if (!screen->pipe_screen || !arg.api) { + debug_printf("%s: failed to create dri1 screen\n", __FUNCTION__); + goto out_no_screen; + } + + __dri1_api_hooks = arg.api; + + driParseOptionInfo(&screen->optionCache, + __driConfigOptions, __driNConfigOptions); + + /** + * FIXME: If the driver supports format conversion swapbuffer blits, we might + * want to support other color bit depths than the server is currently + * using. + */ + + configs = dri_fill_in_modes(screen, sPriv->fbBPP); + if (!configs) + goto out_no_configs; + + return configs; + out_no_configs: + screen->pipe_screen->destroy(screen->pipe_screen); + out_no_screen: + FREE(screen); + return NULL; +} diff --git a/src/gallium/state_trackers/dri/dri1.h b/src/gallium/state_trackers/dri/dri1.h new file mode 100644 index 0000000000..e83571e57b --- /dev/null +++ b/src/gallium/state_trackers/dri/dri1.h @@ -0,0 +1,63 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Author: Keith Whitwell <keithw@vmware.com> + * Author: Jakob Bornecrantz <wallbraker@gmail.com> + */ + +#ifndef DRI1_H +#define DRI1_H + +#include "dri_context.h" +#include "dri_drawable.h" + +#include "state_tracker/st_api.h" +#include "dri_util.h" + +extern struct dri1_api *__dri1_api_hooks; + +const __DRIconfig ** +dri1_init_screen(__DRIscreen * sPriv); + +void +dri1_flush_frontbuffer(struct dri_drawable *drawable, + struct pipe_texture *ptex); + +void +dri1_allocate_textures(struct dri_drawable *drawable, + unsigned width, unsigned height, + unsigned mask); + +void dri1_swap_buffers(__DRIdrawable * dPriv); + +void +dri1_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h); + +void +dri1_swap_fences_clear(struct dri_drawable *drawable); + +#endif /* DRI1_H */ diff --git a/src/gallium/state_trackers/dri/dri_context.c b/src/gallium/state_trackers/dri/dri_context.c index f772ba5d16..54568a8b22 100644 --- a/src/gallium/state_trackers/dri/dri_context.c +++ b/src/gallium/state_trackers/dri/dri_context.c @@ -30,25 +30,24 @@ */ #include "dri_screen.h" - #include "dri_drawable.h" -#include "state_tracker/drm_api.h" -#include "state_tracker/dri1_api.h" -#include "state_tracker/st_public.h" -#include "pipe/p_context.h" - #include "dri_context.h" +#include "dri_st_api.h" +#include "dri1.h" +#include "pipe/p_context.h" #include "util/u_memory.h" GLboolean dri_create_context(const __GLcontextModes * visual, __DRIcontext * cPriv, void *sharedContextPrivate) { + struct st_api *stapi = dri_get_st_api(); __DRIscreen *sPriv = cPriv->driScreenPriv; struct dri_screen *screen = dri_screen(sPriv); struct dri_context *ctx = NULL; - struct st_context *st_share = NULL; + struct st_context_iface *st_share = NULL; + struct st_visual stvis; if (sharedContextPrivate) { st_share = ((struct dri_context *)sharedContextPrivate)->st; @@ -62,21 +61,15 @@ dri_create_context(const __GLcontextModes * visual, ctx->cPriv = cPriv; ctx->sPriv = sPriv; ctx->lock = screen->drmLock; - ctx->d_stamp = -1; - ctx->r_stamp = -1; driParseConfigFiles(&ctx->optionCache, &screen->optionCache, sPriv->myNum, "dri"); - ctx->pipe = screen->pipe_screen->context_create( screen->pipe_screen, - ctx ); - - if (ctx->pipe == NULL) - goto fail; - - ctx->st = st_create_context(ctx->pipe, visual, st_share); + dri_fill_st_visual(&stvis, screen, visual); + ctx->st = stapi->create_context(stapi, screen->smapi, &stvis, st_share); if (ctx->st == NULL) goto fail; + ctx->st->st_manager_private = (void *) ctx; dri_init_extensions(ctx); @@ -84,10 +77,7 @@ dri_create_context(const __GLcontextModes * visual, fail: if (ctx && ctx->st) - st_destroy_context(ctx->st); - - if (ctx && ctx->pipe) - ctx->pipe->destroy(ctx->pipe); + ctx->st->destroy(ctx->st); FREE(ctx); return FALSE; @@ -109,11 +99,8 @@ dri_destroy_context(__DRIcontext * cPriv) * to avoid having to add code elsewhere to cope with flushing a * partially destroyed context. */ - st_flush(ctx->st, 0, NULL); - - /* Also frees ctx->pipe? - */ - st_destroy_context(ctx->st); + ctx->st->flush(ctx->st, 0, NULL); + ctx->st->destroy(ctx->st); FREE(ctx); } @@ -121,14 +108,16 @@ dri_destroy_context(__DRIcontext * cPriv) GLboolean dri_unbind_context(__DRIcontext * cPriv) { + struct st_api *stapi = dri_get_st_api(); + if (cPriv) { struct dri_context *ctx = dri_context(cPriv); if (--ctx->bind_count == 0) { - if (ctx->st && ctx->st == st_get_current()) { - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - st_make_current(NULL, NULL, NULL, NULL); - } + if (ctx->st == stapi->get_current(stapi)) { + ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + stapi->make_current(stapi, NULL, NULL, NULL); + } } } @@ -140,83 +129,47 @@ dri_make_current(__DRIcontext * cPriv, __DRIdrawable * driDrawPriv, __DRIdrawable * driReadPriv) { + struct st_api *stapi = dri_get_st_api(); + if (cPriv) { struct dri_context *ctx = dri_context(cPriv); struct dri_drawable *draw = dri_drawable(driDrawPriv); struct dri_drawable *read = dri_drawable(driReadPriv); - struct st_context *old_st = st_get_current(); + struct st_context_iface *old_st; + old_st = stapi->get_current(stapi); if (old_st && old_st != ctx->st) - st_flush(old_st, PIPE_FLUSH_RENDER_CACHE, NULL); + ctx->st->flush(old_st, PIPE_FLUSH_RENDER_CACHE, NULL); ++ctx->bind_count; if (ctx->dPriv != driDrawPriv) { ctx->dPriv = driDrawPriv; - ctx->d_stamp = driDrawPriv->lastStamp - 1; + draw->texture_stamp = driDrawPriv->lastStamp - 1; } if (ctx->rPriv != driReadPriv) { ctx->rPriv = driReadPriv; - ctx->r_stamp = driReadPriv->lastStamp - 1; + read->texture_stamp = driReadPriv->lastStamp - 1; } - /* DRI co-state tracker currently overrides flush_frontbuffer. - * When this is fixed, will need to pass the drawable in the - * fourth parameter here so that when Mesa calls - * flush_frontbuffer directly (in front-buffer rendering), it - * will have access to the drawable argument: - */ - st_make_current(ctx->st, draw->stfb, read->stfb, ctx); - - if (__dri1_api_hooks) { - dri1_update_drawables(ctx, draw, read); - } else { - dri_update_buffer(ctx->pipe->screen, - ctx->pipe->priv); - } - } else { - st_make_current(NULL, NULL, NULL, NULL); + stapi->make_current(stapi, ctx->st, draw->stfb, read->stfb); + } + else { + stapi->make_current(stapi, NULL, NULL, NULL); } return GL_TRUE; } -static void -st_dri_lock(struct pipe_context *pipe) -{ - dri_lock((struct dri_context *)pipe->priv); -} - -static void -st_dri_unlock(struct pipe_context *pipe) -{ - dri_unlock((struct dri_context *)pipe->priv); -} - -static boolean -st_dri_is_locked(struct pipe_context *pipe) +struct dri_context * +dri_get_current(void) { - return ((struct dri_context *)pipe->priv)->isLocked; -} + struct st_api *stapi = dri_get_st_api(); + struct st_context_iface *st; -static boolean -st_dri_lost_lock(struct pipe_context *pipe) -{ - return ((struct dri_context *)pipe->priv)->wsLostLock; -} + st = stapi->get_current(stapi); -static void -st_dri_clear_lost_lock(struct pipe_context *pipe) -{ - ((struct dri_context *)pipe->priv)->wsLostLock = FALSE; + return (struct dri_context *) (st) ? st->st_manager_private : NULL; } -struct dri1_api_lock_funcs dri1_lf = { - .lock = st_dri_lock, - .unlock = st_dri_unlock, - .is_locked = st_dri_is_locked, - .is_lock_lost = st_dri_lost_lock, - .clear_lost_lock = st_dri_clear_lost_lock -}; - /* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_context.h b/src/gallium/state_trackers/dri/dri_context.h index 13f497462f..845b420cf8 100644 --- a/src/gallium/state_trackers/dri/dri_context.h +++ b/src/gallium/state_trackers/dri/dri_context.h @@ -51,9 +51,6 @@ struct dri_context driOptionCache optionCache; - unsigned int d_stamp; - unsigned int r_stamp; - drmLock *lock; boolean isLocked; boolean stLostLock; @@ -62,8 +59,7 @@ struct dri_context unsigned int bind_count; /* gallium */ - struct st_context *st; - struct pipe_context *pipe; + struct st_context_iface *st; }; static INLINE struct dri_context * @@ -72,33 +68,9 @@ dri_context(__DRIcontext * driContextPriv) return (struct dri_context *)driContextPriv->driverPrivate; } -static INLINE void -dri_lock(struct dri_context *ctx) -{ - drm_context_t hw_context = ctx->cPriv->hHWContext; - char ret = 0; - - DRM_CAS(ctx->lock, hw_context, DRM_LOCK_HELD | hw_context, ret); - if (ret) { - drmGetLock(ctx->sPriv->fd, hw_context, 0); - ctx->stLostLock = TRUE; - ctx->wsLostLock = TRUE; - } - ctx->isLocked = TRUE; -} - -static INLINE void -dri_unlock(struct dri_context *ctx) -{ - ctx->isLocked = FALSE; - DRM_UNLOCK(ctx->sPriv->fd, ctx->lock, ctx->cPriv->hHWContext); -} - /*********************************************************************** * dri_context.c */ -extern struct dri1_api_lock_funcs dri1_lf; - void dri_destroy_context(__DRIcontext * driContextPriv); boolean dri_unbind_context(__DRIcontext * driContextPriv); @@ -108,6 +80,9 @@ dri_make_current(__DRIcontext * driContextPriv, __DRIdrawable * driDrawPriv, __DRIdrawable * driReadPriv); +struct dri_context * +dri_get_current(void); + boolean dri_create_context(const __GLcontextModes * visual, __DRIcontext * driContextPriv, diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c index c400725c7f..930387f8a6 100644 --- a/src/gallium/state_trackers/dri/dri_drawable.c +++ b/src/gallium/state_trackers/dri/dri_drawable.c @@ -32,251 +32,30 @@ #include "dri_screen.h" #include "dri_context.h" #include "dri_drawable.h" +#include "dri_st_api.h" +#include "dri1.h" -#include "pipe/p_context.h" #include "pipe/p_screen.h" -#include "main/mtypes.h" -#include "main/renderbuffer.h" -#include "state_tracker/drm_api.h" -#include "state_tracker/dri1_api.h" -#include "state_tracker/st_context.h" -#include "state_tracker/st_public.h" -#include "state_tracker/st_cb_fbo.h" - #include "util/u_format.h" #include "util/u_memory.h" -#include "util/u_rect.h" #include "util/u_inlines.h" -static struct pipe_surface * -dri_surface_from_handle(struct drm_api *api, - struct pipe_screen *screen, - unsigned handle, - enum pipe_format format, - unsigned width, unsigned height, unsigned pitch) -{ - struct pipe_surface *surface = NULL; - struct pipe_texture *texture = NULL; - struct pipe_texture templat; - struct winsys_handle whandle; - - memset(&templat, 0, sizeof(templat)); - templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; - templat.target = PIPE_TEXTURE_2D; - templat.last_level = 0; - templat.depth0 = 1; - templat.format = format; - templat.width0 = width; - templat.height0 = height; - - memset(&whandle, 0, sizeof(whandle)); - whandle.handle = handle; - whandle.stride = pitch; - - texture = screen->texture_from_handle(screen, &templat, &whandle); - - if (!texture) { - debug_printf("%s: Failed to blanket the buffer with a texture\n", __func__); - return NULL; - } - - surface = screen->get_tex_surface(screen, texture, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_GPU_WRITE); - - /* we don't need the texture from this point on */ - pipe_texture_reference(&texture, NULL); - return surface; -} - -/** - * Pixmaps have will have the same name of fake front and front. - */ -static boolean -dri2_check_if_pixmap(__DRIbuffer *buffers, int count) -{ - boolean found = FALSE; - boolean is_pixmap = FALSE; - unsigned name; - int i; - - for (i = 0; i < count; i++) { - switch (buffers[i].attachment) { - case __DRI_BUFFER_FRONT_LEFT: - case __DRI_BUFFER_FAKE_FRONT_LEFT: - if (found) { - is_pixmap = buffers[i].name == name; - } else { - name = buffers[i].name; - found = TRUE; - } - default: - continue; - } - } - - return is_pixmap; -} - -/** - * This will be called a drawable is known to have been resized. - */ -void -dri_get_buffers(__DRIdrawable * dPriv) -{ - - struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_surface *surface = NULL; - struct dri_screen *st_screen = dri_screen(drawable->sPriv); - struct pipe_screen *screen = st_screen->pipe_screen; - __DRIbuffer *buffers = NULL; - __DRIscreen *dri_screen = drawable->sPriv; - __DRIdrawable *dri_drawable = drawable->dPriv; - struct drm_api *api = st_screen->api; - boolean have_depth = FALSE; - int i, count; - - if ((dri_screen->dri2.loader - && (dri_screen->dri2.loader->base.version > 2) - && (dri_screen->dri2.loader->getBuffersWithFormat != NULL))) { - buffers = (*dri_screen->dri2.loader->getBuffersWithFormat) - (dri_drawable, &dri_drawable->w, &dri_drawable->h, - drawable->attachments, drawable->num_attachments, - &count, dri_drawable->loaderPrivate); - } else { - assert(dri_screen->dri2.loader); - buffers = (*dri_screen->dri2.loader->getBuffers) (dri_drawable, - &dri_drawable->w, - &dri_drawable->h, - drawable->attachments, - drawable-> - num_attachments, &count, - dri_drawable-> - loaderPrivate); - } - - if (buffers == NULL) { - return; - } - - /* set one cliprect to cover the whole dri_drawable */ - dri_drawable->x = 0; - dri_drawable->y = 0; - dri_drawable->backX = 0; - dri_drawable->backY = 0; - dri_drawable->numClipRects = 1; - dri_drawable->pClipRects[0].x1 = 0; - dri_drawable->pClipRects[0].y1 = 0; - dri_drawable->pClipRects[0].x2 = dri_drawable->w; - dri_drawable->pClipRects[0].y2 = dri_drawable->h; - dri_drawable->numBackClipRects = 1; - dri_drawable->pBackClipRects[0].x1 = 0; - dri_drawable->pBackClipRects[0].y1 = 0; - dri_drawable->pBackClipRects[0].x2 = dri_drawable->w; - dri_drawable->pBackClipRects[0].y2 = dri_drawable->h; - - if (drawable->old_num == count && - drawable->old_w == dri_drawable->w && - drawable->old_h == dri_drawable->h && - memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * count) == 0) { - return; - } else { - drawable->old_num = count; - drawable->old_w = dri_drawable->w; - drawable->old_h = dri_drawable->h; - memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count); - } - - drawable->is_pixmap = dri2_check_if_pixmap(buffers, count); - - for (i = 0; i < count; i++) { - enum pipe_format format = 0; - int index = 0; - - switch (buffers[i].attachment) { - case __DRI_BUFFER_FRONT_LEFT: - if (!st_screen->auto_fake_front) - continue; - /* fallthrough */ - case __DRI_BUFFER_FAKE_FRONT_LEFT: - index = ST_SURFACE_FRONT_LEFT; - format = drawable->color_format; - break; - case __DRI_BUFFER_BACK_LEFT: - index = ST_SURFACE_BACK_LEFT; - format = drawable->color_format; - break; - case __DRI_BUFFER_DEPTH: - case __DRI_BUFFER_DEPTH_STENCIL: - case __DRI_BUFFER_STENCIL: - index = ST_SURFACE_DEPTH; - format = drawable->depth_stencil_format; - break; - case __DRI_BUFFER_ACCUM: - default: - assert(0); - } - - if (index == ST_SURFACE_DEPTH) { - if (have_depth) - continue; - else - have_depth = TRUE; - } - - surface = dri_surface_from_handle(api, - screen, - buffers[i].name, - format, - dri_drawable->w, - dri_drawable->h, buffers[i].pitch); - - switch (buffers[i].attachment) { - case __DRI_BUFFER_FRONT_LEFT: - case __DRI_BUFFER_FAKE_FRONT_LEFT: - case __DRI_BUFFER_BACK_LEFT: - drawable->color_format = surface->format; - break; - case __DRI_BUFFER_DEPTH: - case __DRI_BUFFER_DEPTH_STENCIL: - case __DRI_BUFFER_STENCIL: - drawable->depth_stencil_format = surface->format; - break; - case __DRI_BUFFER_ACCUM: - default: - assert(0); - } - - st_set_framebuffer_surface(drawable->stfb, index, surface); - pipe_surface_reference(&surface, NULL); - } - /* this needed, or else the state tracker fails to pick the new buffers */ - st_resize_framebuffer(drawable->stfb, dri_drawable->w, dri_drawable->h); -} - /** * These are used for GLX_EXT_texture_from_pixmap */ void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, GLint format, __DRIdrawable *dPriv) { + struct dri_context *ctx = dri_context(pDRICtx); struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_surface *ps; + struct pipe_texture *pt = + dri_get_st_framebuffer_texture(drawable->stfb, ST_ATTACHMENT_FRONT_LEFT); - if (!drawable->stfb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer) { - struct gl_renderbuffer *rb = - st_new_renderbuffer_fb(drawable->color_format, 0 /*XXX*/, FALSE); - _mesa_add_renderbuffer(&drawable->stfb->Base, BUFFER_FRONT_LEFT, rb); + if (pt) { + ctx->st->teximage(ctx->st, + (target == GL_TEXTURE_2D) ? ST_TEXTURE_2D : ST_TEXTURE_RECT, + 0, drawable->stvis.color_format, pt, FALSE); } - - dri_get_buffers(drawable->dPriv); - st_get_framebuffer_surface(drawable->stfb, ST_SURFACE_FRONT_LEFT, &ps); - - if (!ps) - return; - - st_bind_texture_surface(ps, target == GL_TEXTURE_2D ? ST_TEXTURE_2D : - ST_TEXTURE_RECT, 0, drawable->color_format); } void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, @@ -285,53 +64,6 @@ void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, dri2_set_tex_buffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); } -void -dri_update_buffer(struct pipe_screen *screen, void *context_private) -{ - struct dri_context *ctx = (struct dri_context *)context_private; - - if (ctx->d_stamp == *ctx->dPriv->pStamp && - ctx->r_stamp == *ctx->rPriv->pStamp) - return; - - ctx->d_stamp = *ctx->dPriv->pStamp; - ctx->r_stamp = *ctx->rPriv->pStamp; - - /* Ask the X server for new renderbuffers. */ - dri_get_buffers(ctx->dPriv); - if (ctx->dPriv != ctx->rPriv) - dri_get_buffers(ctx->rPriv); - -} - -void -dri_flush_frontbuffer(struct pipe_screen *screen, - struct pipe_surface *surf, void *context_private) -{ - struct dri_context *ctx = (struct dri_context *)context_private; - struct dri_drawable *drawable = dri_drawable(ctx->dPriv); - __DRIdrawable *dri_drawable = ctx->dPriv; - __DRIscreen *dri_screen = ctx->sPriv; - - /* XXX Does this function get called with DRI1? */ - - if (ctx->dPriv == NULL) { - debug_printf("%s: no drawable bound to context\n", __func__); - return; - } - -#if 0 - /* TODO if rendering to pixmaps is slow enable this code. */ - if (drawable->is_pixmap) - return; -#else - (void)drawable; -#endif - - (*dri_screen->dri2.loader->flushFrontBuffer)(dri_drawable, - dri_drawable->loaderPrivate); -} - /** * This is called when we need to set up GL rendering to a new X window. */ @@ -342,7 +74,6 @@ dri_create_buffer(__DRIscreen * sPriv, { struct dri_screen *screen = sPriv->private; struct dri_drawable *drawable = NULL; - int i; if (isPixmap) goto fail; /* not implemented */ @@ -351,45 +82,8 @@ dri_create_buffer(__DRIscreen * sPriv, if (drawable == NULL) goto fail; - if (visual->redBits == 8) { - if (visual->alphaBits == 8) - drawable->color_format = PIPE_FORMAT_B8G8R8A8_UNORM; - else - drawable->color_format = PIPE_FORMAT_B8G8R8X8_UNORM; - } else { - drawable->color_format = PIPE_FORMAT_B5G6R5_UNORM; - } - - switch(visual->depthBits) { - default: - case 0: - drawable->depth_stencil_format = PIPE_FORMAT_NONE; - break; - case 16: - drawable->depth_stencil_format = PIPE_FORMAT_Z16_UNORM; - break; - case 24: - if (visual->stencilBits == 0) { - drawable->depth_stencil_format = (screen->d_depth_bits_last) ? - PIPE_FORMAT_Z24X8_UNORM: - PIPE_FORMAT_X8Z24_UNORM; - } else { - drawable->depth_stencil_format = (screen->sd_depth_bits_last) ? - PIPE_FORMAT_Z24S8_UNORM: - PIPE_FORMAT_S8Z24_UNORM; - } - break; - case 32: - drawable->depth_stencil_format = PIPE_FORMAT_Z32_UNORM; - break; - } - - drawable->stfb = st_create_framebuffer(visual, - drawable->color_format, - drawable->depth_stencil_format, - drawable->depth_stencil_format, - dPriv->w, - dPriv->h, (void *)drawable); + dri_fill_st_visual(&drawable->stvis, screen, visual); + drawable->stfb = dri_create_st_framebuffer(drawable); if (drawable->stfb == NULL) goto fail; @@ -397,48 +91,6 @@ dri_create_buffer(__DRIscreen * sPriv, drawable->dPriv = dPriv; dPriv->driverPrivate = (void *)drawable; - /* setup dri2 buffers information */ - /* TODO incase of double buffer visual, delay fake creation */ - i = 0; - if (sPriv->dri2.loader - && (sPriv->dri2.loader->base.version > 2) - && (sPriv->dri2.loader->getBuffersWithFormat != NULL)) { - drawable->attachments[i++] = __DRI_BUFFER_FRONT_LEFT; - drawable->attachments[i++] = visual->rgbBits; - if (!screen->auto_fake_front) { - drawable->attachments[i++] = __DRI_BUFFER_FAKE_FRONT_LEFT; - drawable->attachments[i++] = visual->rgbBits; - } - if (visual->doubleBufferMode) { - drawable->attachments[i++] = __DRI_BUFFER_BACK_LEFT; - drawable->attachments[i++] = visual->rgbBits; - } - if (visual->depthBits && visual->stencilBits) { - drawable->attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL; - drawable->attachments[i++] = visual->depthBits + visual->stencilBits; - } else if (visual->depthBits) { - drawable->attachments[i++] = __DRI_BUFFER_DEPTH; - drawable->attachments[i++] = visual->depthBits; - } else if (visual->stencilBits) { - drawable->attachments[i++] = __DRI_BUFFER_STENCIL; - drawable->attachments[i++] = visual->stencilBits; - } - drawable->num_attachments = i / 2; - } else { - drawable->attachments[i++] = __DRI_BUFFER_FRONT_LEFT; - if (!screen->auto_fake_front) - drawable->attachments[i++] = __DRI_BUFFER_FAKE_FRONT_LEFT; - if (visual->doubleBufferMode) - drawable->attachments[i++] = __DRI_BUFFER_BACK_LEFT; - if (visual->depthBits && visual->stencilBits) - drawable->attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL; - else if (visual->depthBits) - drawable->attachments[i++] = __DRI_BUFFER_DEPTH; - else if (visual->stencilBits) - drawable->attachments[i++] = __DRI_BUFFER_STENCIL; - drawable->num_attachments = i; - } - drawable->desired_fences = 2; return GL_TRUE; @@ -447,319 +99,23 @@ fail: return GL_FALSE; } -static struct pipe_fence_handle * -dri_swap_fences_pop_front(struct dri_drawable *draw) -{ - struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen; - struct pipe_fence_handle *fence = NULL; - - if (draw->cur_fences >= draw->desired_fences) { - screen->fence_reference(screen, &fence, draw->swap_fences[draw->tail]); - screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL); - --draw->cur_fences; - draw->tail &= DRI_SWAP_FENCES_MASK; - } - return fence; -} - -static void -dri_swap_fences_push_back(struct dri_drawable *draw, - struct pipe_fence_handle *fence) -{ - struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen; - - if (!fence) - return; - - if (draw->cur_fences < DRI_SWAP_FENCES_MAX) { - draw->cur_fences++; - screen->fence_reference(screen, &draw->swap_fences[draw->head++], - fence); - draw->head &= DRI_SWAP_FENCES_MASK; - } -} - void dri_destroy_buffer(__DRIdrawable * dPriv) { struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_fence_handle *fence; - struct pipe_screen *screen = dri_screen(drawable->sPriv)->pipe_screen; - - st_unreference_framebuffer(drawable->stfb); - drawable->desired_fences = 0; - while (drawable->cur_fences) { - fence = dri_swap_fences_pop_front(drawable); - screen->fence_reference(screen, &fence, NULL); - } - - FREE(drawable); -} - -static void -dri1_update_drawables_locked(struct dri_context *ctx, - __DRIdrawable * driDrawPriv, - __DRIdrawable * driReadPriv) -{ - if (ctx->stLostLock) { - ctx->stLostLock = FALSE; - if (driDrawPriv == driReadPriv) - DRI_VALIDATE_DRAWABLE_INFO(ctx->sPriv, driDrawPriv); - else - DRI_VALIDATE_TWO_DRAWABLES_INFO(ctx->sPriv, driDrawPriv, - driReadPriv); - } -} - -/** - * This ensures all contexts which bind to a drawable pick up the - * drawable change and signal new buffer state. - * Calling st_resize_framebuffer for each context may seem like overkill, - * but no new buffers will actually be allocated if the dimensions don't - * change. - */ - -static void -dri1_propagate_drawable_change(struct dri_context *ctx) -{ - __DRIdrawable *dPriv = ctx->dPriv; - __DRIdrawable *rPriv = ctx->rPriv; - boolean flushed = FALSE; - - if (dPriv && ctx->d_stamp != dPriv->lastStamp) { - - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - flushed = TRUE; - ctx->d_stamp = dPriv->lastStamp; - st_resize_framebuffer(dri_drawable(dPriv)->stfb, dPriv->w, dPriv->h); - - } - - if (rPriv && dPriv != rPriv && ctx->r_stamp != rPriv->lastStamp) { - - if (!flushed) - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - ctx->r_stamp = rPriv->lastStamp; - st_resize_framebuffer(dri_drawable(rPriv)->stfb, rPriv->w, rPriv->h); - - } else if (rPriv && dPriv == rPriv) { - - ctx->r_stamp = ctx->d_stamp; - - } -} - -void -dri1_update_drawables(struct dri_context *ctx, - struct dri_drawable *draw, struct dri_drawable *read) -{ - dri_lock(ctx); - dri1_update_drawables_locked(ctx, draw->dPriv, read->dPriv); - dri_unlock(ctx); - - dri1_propagate_drawable_change(ctx); -} - -static INLINE boolean -dri1_intersect_src_bbox(struct drm_clip_rect *dst, - int dst_x, - int dst_y, - const struct drm_clip_rect *src, - const struct drm_clip_rect *bbox) -{ - int xy1; - int xy2; - - xy1 = ((int)src->x1 > (int)bbox->x1 + dst_x) ? src->x1 : - (int)bbox->x1 + dst_x; - xy2 = ((int)src->x2 < (int)bbox->x2 + dst_x) ? src->x2 : - (int)bbox->x2 + dst_x; - if (xy1 >= xy2 || xy1 < 0) - return FALSE; - - dst->x1 = xy1; - dst->x2 = xy2; - - xy1 = ((int)src->y1 > (int)bbox->y1 + dst_y) ? src->y1 : - (int)bbox->y1 + dst_y; - xy2 = ((int)src->y2 < (int)bbox->y2 + dst_y) ? src->y2 : - (int)bbox->y2 + dst_y; - if (xy1 >= xy2 || xy1 < 0) - return FALSE; - - dst->y1 = xy1; - dst->y2 = xy2; - return TRUE; -} - -static void -dri1_swap_copy(struct dri_context *ctx, - struct pipe_surface *dst, - struct pipe_surface *src, - __DRIdrawable * dPriv, const struct drm_clip_rect *bbox) -{ - struct pipe_context *pipe = ctx->pipe; - struct drm_clip_rect clip; - struct drm_clip_rect *cur; int i; - cur = dPriv->pClipRects; - - for (i = 0; i < dPriv->numClipRects; ++i) { - if (dri1_intersect_src_bbox(&clip, dPriv->x, dPriv->y, cur++, bbox)) { - if (pipe->surface_copy) { - pipe->surface_copy(pipe, dst, clip.x1, clip.y1, - src, - (int)clip.x1 - dPriv->x, - (int)clip.y1 - dPriv->y, - clip.x2 - clip.x1, clip.y2 - clip.y1); - } else { - util_surface_copy(pipe, FALSE, dst, clip.x1, clip.y1, - src, - (int)clip.x1 - dPriv->x, - (int)clip.y1 - dPriv->y, - clip.x2 - clip.x1, clip.y2 - clip.y1); - } - } - } -} - -static void -dri1_copy_to_front(struct dri_context *ctx, - struct pipe_surface *surf, - __DRIdrawable * dPriv, - const struct drm_clip_rect *sub_box, - struct pipe_fence_handle **fence) -{ - struct pipe_context *pipe = ctx->pipe; - boolean save_lost_lock; - uint cur_w; - uint cur_h; - struct drm_clip_rect bbox; - boolean visible = TRUE; - - *fence = NULL; - - dri_lock(ctx); - save_lost_lock = ctx->stLostLock; - dri1_update_drawables_locked(ctx, dPriv, dPriv); - st_get_framebuffer_dimensions(dri_drawable(dPriv)->stfb, &cur_w, &cur_h); - - bbox.x1 = 0; - bbox.x2 = cur_w; - bbox.y1 = 0; - bbox.y2 = cur_h; - - if (sub_box) - visible = dri1_intersect_src_bbox(&bbox, 0, 0, &bbox, sub_box); - - if (visible && __dri1_api_hooks->present_locked) { - - __dri1_api_hooks->present_locked(pipe, - surf, - dPriv->pClipRects, - dPriv->numClipRects, - dPriv->x, dPriv->y, &bbox, fence); - - } else if (visible && __dri1_api_hooks->front_srf_locked) { - - struct pipe_surface *front = __dri1_api_hooks->front_srf_locked(pipe); + dri1_swap_fences_clear(drawable); - if (front) - dri1_swap_copy(ctx, front, surf, dPriv, &bbox); - - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, fence); - } - - ctx->stLostLock = save_lost_lock; - - /** - * FIXME: Revisit this: Update drawables on copy_sub_buffer ? - */ - - if (!sub_box) - dri1_update_drawables_locked(ctx, ctx->dPriv, ctx->rPriv); - - dri_unlock(ctx); - dri1_propagate_drawable_change(ctx); -} - -void -dri1_flush_frontbuffer(struct pipe_screen *screen, - struct pipe_surface *surf, void *context_private) -{ - struct dri_context *ctx = (struct dri_context *)context_private; - struct pipe_fence_handle *dummy_fence; + pipe_surface_reference(&drawable->dri1_surface, NULL); + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_texture_reference(&drawable->textures[i], NULL); - dri1_copy_to_front(ctx, surf, ctx->dPriv, NULL, &dummy_fence); - screen->fence_reference(screen, &dummy_fence, NULL); + dri_destroy_st_framebuffer(drawable->stfb); - /** - * FIXME: Do we need swap throttling here? - */ -} - -void -dri_swap_buffers(__DRIdrawable * dPriv) -{ - struct dri_context *ctx; - struct pipe_surface *back_surf; - struct dri_drawable *draw = dri_drawable(dPriv); - struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen; - struct pipe_fence_handle *fence; - struct st_context *st = st_get_current(); - - assert(__dri1_api_hooks != NULL); - - if (!st) - return; /* For now */ - - ctx = (struct dri_context *)st->pipe->priv; - - st_get_framebuffer_surface(draw->stfb, ST_SURFACE_BACK_LEFT, &back_surf); - if (back_surf) { - st_notify_swapbuffers(draw->stfb); - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - fence = dri_swap_fences_pop_front(draw); - if (fence) { - (void)screen->fence_finish(screen, fence, 0); - screen->fence_reference(screen, &fence, NULL); - } - dri1_copy_to_front(ctx, back_surf, dPriv, NULL, &fence); - dri_swap_fences_push_back(draw, fence); - screen->fence_reference(screen, &fence, NULL); - } -} - -void -dri_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h) -{ - struct pipe_screen *screen = dri_screen(dPriv->driScreenPriv)->pipe_screen; - struct drm_clip_rect sub_bbox; - struct dri_context *ctx; - struct pipe_surface *back_surf; - struct dri_drawable *draw = dri_drawable(dPriv); - struct pipe_fence_handle *dummy_fence; - struct st_context *st = st_get_current(); - - assert(__dri1_api_hooks != NULL); - - if (!st) - return; - - ctx = (struct dri_context *)st->pipe->priv; - - sub_bbox.x1 = x; - sub_bbox.x2 = x + w; - sub_bbox.y1 = y; - sub_bbox.y2 = y + h; + drawable->desired_fences = 0; - st_get_framebuffer_surface(draw->stfb, ST_SURFACE_BACK_LEFT, &back_surf); - if (back_surf) { - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - dri1_copy_to_front(ctx, back_surf, dPriv, &sub_bbox, &dummy_fence); - screen->fence_reference(screen, &dummy_fence, NULL); - } + FREE(drawable); } /* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_drawable.h b/src/gallium/state_trackers/dri/dri_drawable.h index 8bc59cb4c3..7f687b65f2 100644 --- a/src/gallium/state_trackers/dri/dri_drawable.h +++ b/src/gallium/state_trackers/dri/dri_drawable.h @@ -29,6 +29,8 @@ #define DRI_DRAWABLE_H #include "pipe/p_compiler.h" +#include "pipe/p_format.h" +#include "state_tracker/st_api.h" struct pipe_surface; struct pipe_fence_handle; @@ -44,26 +46,26 @@ struct dri_drawable __DRIdrawable *dPriv; __DRIscreen *sPriv; - unsigned attachments[8]; - unsigned num_attachments; - - boolean is_pixmap; + /* gallium */ + struct st_framebuffer_iface *stfb; + struct st_visual stvis; __DRIbuffer old[8]; unsigned old_num; unsigned old_w; unsigned old_h; - /* gallium */ - struct st_framebuffer *stfb; + struct pipe_texture *textures[ST_ATTACHMENT_COUNT]; + unsigned int texture_mask, texture_stamp; + struct pipe_fence_handle *swap_fences[DRI_SWAP_FENCES_MAX]; unsigned int head; unsigned int tail; unsigned int desired_fences; unsigned int cur_fences; - enum pipe_format color_format; - enum pipe_format depth_stencil_format; + /* used only by DRI1 */ + struct pipe_surface *dri1_surface; }; static INLINE struct dri_drawable * @@ -80,20 +82,6 @@ dri_create_buffer(__DRIscreen * sPriv, __DRIdrawable * dPriv, const __GLcontextModes * visual, boolean isPixmap); -void -dri_update_buffer(struct pipe_screen *screen, void *context_private); - -void -dri_flush_frontbuffer(struct pipe_screen *screen, - struct pipe_surface *surf, void *context_private); - -void dri_swap_buffers(__DRIdrawable * dPriv); - -void -dri_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h); - -void dri_get_buffers(__DRIdrawable * dPriv); - void dri_destroy_buffer(__DRIdrawable * dPriv); void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, @@ -102,13 +90,6 @@ void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv); -void -dri1_update_drawables(struct dri_context *ctx, - struct dri_drawable *draw, struct dri_drawable *read); - -void -dri1_flush_frontbuffer(struct pipe_screen *screen, - struct pipe_surface *surf, void *context_private); #endif /* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_extensions.c b/src/gallium/state_trackers/dri/dri_extensions.c index 800677a2d1..df458e1eb0 100644 --- a/src/gallium/state_trackers/dri/dri_extensions.c +++ b/src/gallium/state_trackers/dri/dri_extensions.c @@ -38,9 +38,11 @@ void dri_init_extensions(struct dri_context *ctx) { + struct st_context *st = (struct st_context *) ctx->st; + /* New extensions should be added in mesa/state_tracker/st_extensions.c * and not in this file. */ - driInitExtensions(ctx->st->ctx, NULL, GL_FALSE); + driInitExtensions(st->ctx, NULL, GL_FALSE); } /* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_screen.c b/src/gallium/state_trackers/dri/dri_screen.c index 7ccad8f5dd..17b9f1c5fa 100644 --- a/src/gallium/state_trackers/dri/dri_screen.c +++ b/src/gallium/state_trackers/dri/dri_screen.c @@ -36,11 +36,13 @@ #include "dri_screen.h" #include "dri_context.h" #include "dri_drawable.h" +#include "dri_st_api.h" +#include "dri1.h" +#include "util/u_inlines.h" #include "pipe/p_screen.h" #include "pipe/p_format.h" #include "state_tracker/drm_api.h" -#include "state_tracker/dri1_api.h" #include "util/u_debug.h" @@ -53,7 +55,7 @@ PUBLIC const char __driConfigOptions[] = DRI_CONF_ALLOW_LARGE_TEXTURES(1) DRI_CONF_SECTION_END DRI_CONF_END; - const uint __driNConfigOptions = 3; +const uint __driNConfigOptions = 3; static const __DRItexBufferExtension dri2TexBufferExtension = { { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, @@ -66,10 +68,23 @@ dri2_flush_drawable(__DRIdrawable *draw) { } +static void +dri2_invalidate_drawable(__DRIdrawable *dPriv) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct dri_context *ctx = dri_context(dPriv->driContextPriv); + + dri2InvalidateDrawable(dPriv); + drawable->dPriv->lastStamp = *drawable->dPriv->pStamp; + + if (ctx) + ctx->st->notify_invalid_framebuffer(ctx->st, drawable->stfb); +} + static const __DRI2flushExtension dri2FlushExtension = { { __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, dri2_flush_drawable, - dri2InvalidateDrawable, + dri2_invalidate_drawable, }; static const __DRIextension *dri_screen_extensions[] = { @@ -83,9 +98,7 @@ static const __DRI2flushExtension dri2FlushExtension = { NULL }; -struct dri1_api *__dri1_api_hooks = NULL; - -static const __DRIconfig ** +const __DRIconfig ** dri_fill_in_modes(struct dri_screen *screen, unsigned pixel_bits) { @@ -229,6 +242,68 @@ dri_fill_in_modes(struct dri_screen *screen, } /** + * Roughly the converse of dri_fill_in_modes. + */ +void +dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen, + const __GLcontextModes *mode) +{ + memset(stvis, 0, sizeof(*stvis)); + + stvis->samples = mode->samples; + stvis->render_buffer = ST_ATTACHMENT_INVALID; + + if (mode->redBits == 8) { + if (mode->alphaBits == 8) + stvis->color_format = PIPE_FORMAT_B8G8R8A8_UNORM; + else + stvis->color_format = PIPE_FORMAT_B8G8R8X8_UNORM; + } else { + stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM; + } + + switch (mode->depthBits) { + default: + case 0: + stvis->depth_stencil_format = PIPE_FORMAT_NONE; + break; + case 16: + stvis->depth_stencil_format = PIPE_FORMAT_Z16_UNORM; + break; + case 24: + if (mode->stencilBits == 0) { + stvis->depth_stencil_format = (screen->d_depth_bits_last) ? + PIPE_FORMAT_Z24X8_UNORM: + PIPE_FORMAT_X8Z24_UNORM; + } else { + stvis->depth_stencil_format = (screen->sd_depth_bits_last) ? + PIPE_FORMAT_Z24S8_UNORM: + PIPE_FORMAT_S8Z24_UNORM; + } + break; + case 32: + stvis->depth_stencil_format = PIPE_FORMAT_Z32_UNORM; + break; + } + + stvis->accum_format = (mode->haveAccumBuffer) ? + PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; + + stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; + if (mode->doubleBufferMode) + stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; + if (mode->stereoMode) { + stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; + if (mode->doubleBufferMode) + stvis->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; + } + + if (mode->haveDepthBuffer || mode->haveStencilBuffer) + stvis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; + /* let the state tracker allocate the accum buffer */ +} + +/** * Get information about previous buffer swaps. */ static int @@ -240,73 +315,31 @@ dri_get_swap_info(__DRIdrawable * dPriv, __DRIswapInfo * sInfo) return 0; } -static INLINE void -dri_copy_version(struct dri1_api_version *dst, - const struct __DRIversionRec *src) -{ - dst->major = src->major; - dst->minor = src->minor; - dst->patch_level = src->patch; -} - -static const __DRIconfig ** -dri_init_screen(__DRIscreen * sPriv) +static void +dri_destroy_screen(__DRIscreen * sPriv) { - struct dri_screen *screen; - const __DRIconfig **configs; - struct dri1_create_screen_arg arg; + struct dri_screen *screen = dri_screen(sPriv); + int i; - screen = CALLOC_STRUCT(dri_screen); - if (!screen) - return NULL; + if (screen->dri1_pipe) + screen->dri1_pipe->destroy(screen->dri1_pipe); - screen->api = drm_api_create(); - screen->sPriv = sPriv; - screen->fd = sPriv->fd; - screen->drmLock = (drmLock *) & sPriv->pSAREA->lock; + if (screen->smapi) + dri_destroy_st_manager(screen->smapi); + if (screen->pipe_screen) + screen->pipe_screen->destroy(screen->pipe_screen); - sPriv->private = (void *)screen; - sPriv->extensions = dri_screen_extensions; - - arg.base.mode = DRM_CREATE_DRI1; - arg.lf = &dri1_lf; - arg.ddx_info = sPriv->pDevPriv; - arg.ddx_info_size = sPriv->devPrivSize; - arg.sarea = sPriv->pSAREA; - dri_copy_version(&arg.ddx_version, &sPriv->ddx_version); - dri_copy_version(&arg.dri_version, &sPriv->dri_version); - dri_copy_version(&arg.drm_version, &sPriv->drm_version); - arg.api = NULL; - - screen->pipe_screen = screen->api->create_screen(screen->api, screen->fd, &arg.base); - - if (!screen->pipe_screen || !arg.api) { - debug_printf("%s: failed to create dri1 screen\n", __FUNCTION__); - goto out_no_screen; + for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) { + FREE(screen->optionCache.info[i].name); + FREE(screen->optionCache.info[i].ranges); } - __dri1_api_hooks = arg.api; - - screen->pipe_screen->flush_frontbuffer = dri1_flush_frontbuffer; - driParseOptionInfo(&screen->optionCache, - __driConfigOptions, __driNConfigOptions); - - /** - * FIXME: If the driver supports format conversion swapbuffer blits, we might - * want to support other color bit depths than the server is currently - * using. - */ - - configs = dri_fill_in_modes(screen, sPriv->fbBPP); - if (!configs) - goto out_no_configs; + FREE(screen->optionCache.info); + FREE(screen->optionCache.values); - return configs; - out_no_configs: - screen->pipe_screen->destroy(screen->pipe_screen); - out_no_screen: FREE(screen); - return NULL; + sPriv->private = NULL; + sPriv->extensions = NULL; } /** @@ -324,7 +357,7 @@ dri_init_screen2(__DRIscreen * sPriv) screen = CALLOC_STRUCT(dri_screen); if (!screen) - goto fail; + return NULL; screen->api = drm_api_create(); screen->sPriv = sPriv; @@ -339,9 +372,9 @@ dri_init_screen2(__DRIscreen * sPriv) goto fail; } - /* We need to hook in here */ - screen->pipe_screen->update_buffer = dri_update_buffer; - screen->pipe_screen->flush_frontbuffer = dri_flush_frontbuffer; + screen->smapi = dri_create_st_manager(screen); + if (!screen->smapi) + goto fail; driParseOptionInfo(&screen->optionCache, __driConfigOptions, __driNConfigOptions); @@ -350,46 +383,27 @@ dri_init_screen2(__DRIscreen * sPriv) dri2_ext->getBuffersWithFormat != NULL; return dri_fill_in_modes(screen, 32); - fail: +fail: + dri_destroy_screen(sPriv); return NULL; } -static void -dri_destroy_screen(__DRIscreen * sPriv) -{ - struct dri_screen *screen = dri_screen(sPriv); - int i; - - screen->pipe_screen->destroy(screen->pipe_screen); - - for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) { - FREE(screen->optionCache.info[i].name); - FREE(screen->optionCache.info[i].ranges); - } - - FREE(screen->optionCache.info); - FREE(screen->optionCache.values); - - FREE(screen); - sPriv->private = NULL; -} - -PUBLIC const struct __DriverAPIRec driDriverAPI = { - .InitScreen = dri_init_screen, +const struct __DriverAPIRec driDriverAPI = { .DestroyScreen = dri_destroy_screen, .CreateContext = dri_create_context, .DestroyContext = dri_destroy_context, .CreateBuffer = dri_create_buffer, .DestroyBuffer = dri_destroy_buffer, - .SwapBuffers = dri_swap_buffers, .MakeCurrent = dri_make_current, .UnbindContext = dri_unbind_context, .GetSwapInfo = dri_get_swap_info, .GetDrawableMSC = driDrawableGetMSC32, .WaitForMSC = driWaitForMSC32, - .CopySubBuffer = dri_copy_sub_buffer, - .InitScreen = dri_init_screen, .InitScreen2 = dri_init_screen2, + + .InitScreen = dri1_init_screen, + .SwapBuffers = dri1_swap_buffers, + .CopySubBuffer = dri1_copy_sub_buffer, }; /* This is the table of extensions that the loader will dlsym() for. */ diff --git a/src/gallium/state_trackers/dri/dri_screen.h b/src/gallium/state_trackers/dri/dri_screen.h index 75a0ee4250..e9944e0f63 100644 --- a/src/gallium/state_trackers/dri/dri_screen.h +++ b/src/gallium/state_trackers/dri/dri_screen.h @@ -36,8 +36,9 @@ #include "xmlconfig.h" #include "pipe/p_compiler.h" - -#include "state_tracker/dri1_api.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "state_tracker/st_api.h" struct dri_screen { @@ -60,6 +61,11 @@ struct dri_screen boolean d_depth_bits_last; boolean sd_depth_bits_last; boolean auto_fake_front; + + struct st_manager *smapi; + + /* used only by DRI1 */ + struct pipe_context *dri1_pipe; }; /** cast wrapper */ @@ -69,11 +75,14 @@ dri_screen(__DRIscreen * sPriv) return (struct dri_screen *)sPriv->private; } -/*********************************************************************** - * dri_screen.c - */ +extern const uint __driNConfigOptions; + +const __DRIconfig ** +dri_fill_in_modes(struct dri_screen *screen, unsigned pixel_bits); -extern struct dri1_api *__dri1_api_hooks; +void +dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen, + const __GLcontextModes *mode); #endif diff --git a/src/gallium/state_trackers/dri/dri_st_api.c b/src/gallium/state_trackers/dri/dri_st_api.c new file mode 100644 index 0000000000..2cde01967d --- /dev/null +++ b/src/gallium/state_trackers/dri/dri_st_api.c @@ -0,0 +1,445 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "util/u_format.h" +#include "util/u_debug.h" +#include "state_tracker/drm_api.h" +#include "state_tracker/st_manager.h" /* for st_manager_create_api */ + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_drawable.h" +#include "dri_st_api.h" +#include "dri1.h" + +static struct { + int32_t refcnt; + struct st_api *stapi; +} dri_st_api; + +/** + * Get the format of an attachment. + */ +static INLINE enum pipe_format +dri_drawable_get_format(struct dri_drawable *drawable, + enum st_attachment_type statt) +{ + enum pipe_format format; + + switch (statt) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_BACK_LEFT: + case ST_ATTACHMENT_FRONT_RIGHT: + case ST_ATTACHMENT_BACK_RIGHT: + format = drawable->stvis.color_format; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + format = drawable->stvis.depth_stencil_format; + break; + default: + format = PIPE_FORMAT_NONE; + break; + } + + return format; +} + +/** + * Process __DRIbuffer and convert them into pipe_textures. + */ +static void +dri_drawable_process_buffers(struct dri_drawable *drawable, + __DRIbuffer *buffers, unsigned count) +{ + struct dri_screen *screen = dri_screen(drawable->sPriv); + __DRIdrawable *dri_drawable = drawable->dPriv; + struct pipe_texture templ; + struct winsys_handle whandle; + boolean have_depth = FALSE; + unsigned i; + + if (drawable->old_num == count && + drawable->old_w == dri_drawable->w && + drawable->old_h == dri_drawable->h && + memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * count) == 0) + return; + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_texture_reference(&drawable->textures[i], NULL); + + memset(&templ, 0, sizeof(templ)); + templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = dri_drawable->w; + templ.height0 = dri_drawable->h; + templ.depth0 = 1; + + memset(&whandle, 0, sizeof(whandle)); + + for (i = 0; i < count; i++) { + __DRIbuffer *buf = &buffers[i]; + enum st_attachment_type statt; + enum pipe_format format; + + switch (buf->attachment) { + case __DRI_BUFFER_FRONT_LEFT: + if (!screen->auto_fake_front) { + statt = ST_ATTACHMENT_INVALID; + break; + } + /* fallthrough */ + case __DRI_BUFFER_FAKE_FRONT_LEFT: + statt = ST_ATTACHMENT_FRONT_LEFT; + break; + case __DRI_BUFFER_BACK_LEFT: + statt = ST_ATTACHMENT_BACK_LEFT; + break; + case __DRI_BUFFER_DEPTH: + case __DRI_BUFFER_DEPTH_STENCIL: + case __DRI_BUFFER_STENCIL: + statt = ST_ATTACHMENT_DEPTH_STENCIL; + /* use only the first depth/stencil buffer */ + if (have_depth) + statt = ST_ATTACHMENT_INVALID; + else + have_depth = TRUE; + break; + default: + statt = ST_ATTACHMENT_INVALID; + break; + } + + format = dri_drawable_get_format(drawable, statt); + if (statt == ST_ATTACHMENT_INVALID || format == PIPE_FORMAT_NONE) + continue; + + templ.format = format; + whandle.handle = buf->name; + whandle.stride = buf->pitch; + + drawable->textures[statt] = + screen->pipe_screen->texture_from_handle(screen->pipe_screen, + &templ, &whandle); + } + + drawable->old_num = count; + drawable->old_w = dri_drawable->w; + drawable->old_h = dri_drawable->h; + memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count); +} + +/** + * Retrieve __DRIbuffer from the DRI loader. + */ +static __DRIbuffer * +dri_drawable_get_buffers(struct dri_drawable *drawable, + const enum st_attachment_type *statts, + unsigned *count) +{ + __DRIdrawable *dri_drawable = drawable->dPriv; + struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader; + boolean with_format; + __DRIbuffer *buffers; + int num_buffers; + unsigned attachments[8]; + unsigned num_attachments, i; + + assert(loader); + with_format = (loader->base.version > 2 && loader->getBuffersWithFormat); + + num_attachments = 0; + for (i = 0; i < *count; i++) { + enum pipe_format format; + int att; + + format = dri_drawable_get_format(drawable, statts[i]); + if (format == PIPE_FORMAT_NONE) + continue; + + switch (statts[i]) { + case ST_ATTACHMENT_FRONT_LEFT: + att = __DRI_BUFFER_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_LEFT: + att = __DRI_BUFFER_BACK_LEFT; + break; + case ST_ATTACHMENT_FRONT_RIGHT: + att = __DRI_BUFFER_FRONT_RIGHT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + att = __DRI_BUFFER_BACK_RIGHT; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + att = __DRI_BUFFER_DEPTH_STENCIL; + break; + default: + att = -1; + break; + } + + if (att >= 0) { + attachments[num_attachments++] = att; + if (with_format) { + attachments[num_attachments++] = + util_format_get_blocksizebits(format); + } + } + } + + if (with_format) { + num_attachments /= 2; + buffers = loader->getBuffersWithFormat(dri_drawable, + &dri_drawable->w, &dri_drawable->h, + attachments, num_attachments, + &num_buffers, dri_drawable->loaderPrivate); + } + else { + buffers = loader->getBuffers(dri_drawable, + &dri_drawable->w, &dri_drawable->h, + attachments, num_attachments, + &num_buffers, dri_drawable->loaderPrivate); + } + + if (buffers) { + /* set one cliprect to cover the whole dri_drawable */ + dri_drawable->x = 0; + dri_drawable->y = 0; + dri_drawable->backX = 0; + dri_drawable->backY = 0; + dri_drawable->numClipRects = 1; + dri_drawable->pClipRects[0].x1 = 0; + dri_drawable->pClipRects[0].y1 = 0; + dri_drawable->pClipRects[0].x2 = dri_drawable->w; + dri_drawable->pClipRects[0].y2 = dri_drawable->h; + dri_drawable->numBackClipRects = 1; + dri_drawable->pBackClipRects[0].x1 = 0; + dri_drawable->pBackClipRects[0].y1 = 0; + dri_drawable->pBackClipRects[0].x2 = dri_drawable->w; + dri_drawable->pBackClipRects[0].y2 = dri_drawable->h; + + *count = num_buffers; + } + + return buffers; +} + +static boolean +dri_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_texture **out) +{ + struct dri_drawable *drawable = + (struct dri_drawable *) stfbi->st_manager_private; + unsigned statt_mask, i; + + statt_mask = 0x0; + for (i = 0; i < count; i++) + statt_mask |= (1 << statts[i]); + + /* + * dPriv->pStamp is the server stamp. It should be accessed with a lock, at + * least for DRI1. dPriv->lastStamp is the client stamp. It has the value + * of the server stamp when last checked. + * + * This function updates the textures and records the stamp of the textures. + */ + if (drawable->texture_stamp != drawable->dPriv->lastStamp || + (statt_mask & ~drawable->texture_mask)) { + if (__dri1_api_hooks) { + dri1_allocate_textures(drawable, + drawable->dPriv->w, drawable->dPriv->h, statt_mask); + } + else { + __DRIbuffer *buffers; + unsigned num_buffers = count; + + buffers = dri_drawable_get_buffers(drawable, statts, &num_buffers); + dri_drawable_process_buffers(drawable, buffers, num_buffers); + } + + drawable->texture_stamp = drawable->dPriv->lastStamp; + drawable->texture_mask = statt_mask; + } + + if (!out) + return TRUE; + + for (i = 0; i < count; i++) { + out[i] = NULL; + pipe_texture_reference(&out[i], drawable->textures[statts[i]]); + } + + return TRUE; +} + +static boolean +dri_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + struct dri_drawable *drawable = + (struct dri_drawable *) stfbi->st_manager_private; + struct __DRIdri2LoaderExtensionRec *loader = + drawable->sPriv->dri2.loader; + + if (__dri1_api_hooks) { + struct pipe_texture *ptex = drawable->textures[statt]; + if (ptex) + dri1_flush_frontbuffer(drawable, ptex); + return TRUE; + } + + if (statt == ST_ATTACHMENT_FRONT_LEFT && loader->flushFrontBuffer) { + loader->flushFrontBuffer(drawable->dPriv, + drawable->dPriv->loaderPrivate); + } + + return TRUE; +} + +/** + * Create a framebuffer from the given drawable. + */ +struct st_framebuffer_iface * +dri_create_st_framebuffer(struct dri_drawable *drawable) +{ + struct st_framebuffer_iface *stfbi; + + stfbi = CALLOC_STRUCT(st_framebuffer_iface); + if (stfbi) { + stfbi->visual = &drawable->stvis; + stfbi->flush_front = dri_st_framebuffer_flush_front; + stfbi->validate = dri_st_framebuffer_validate; + stfbi->st_manager_private = (void *) drawable; + } + + return stfbi; +} + +/** + * Destroy a framebuffer. + */ +void +dri_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + FREE(stfbi); +} + +/** + * Return the texture at an attachment. Allocate the texture if it does not + * exist. + */ +struct pipe_texture * +dri_get_st_framebuffer_texture(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + struct dri_drawable *drawable = + (struct dri_drawable *) stfbi->st_manager_private; + + if (!(drawable->texture_mask & (1 << statt))) { + enum st_attachment_type statts[ST_ATTACHMENT_COUNT]; + unsigned i, count = 0; + + /* make sure DRI2 does not destroy existing buffers */ + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + if (drawable->texture_mask & (1 << i)) { + statts[count++] = i; + } + } + statts[count++] = statt; + + drawable->texture_stamp = drawable->dPriv->lastStamp - 1; + dri_st_framebuffer_validate(stfbi, statts, count, NULL); + } + + return drawable->textures[statt]; +} + +/** + * Add a reference to the st_api of the state tracker. + */ +static void +_dri_get_st_api(void) +{ + p_atomic_inc(&dri_st_api.refcnt); + if (p_atomic_read(&dri_st_api.refcnt) == 1) + dri_st_api.stapi = st_manager_create_api(); +} + +/** + * Remove a reference to the st_api of the state tracker. + */ +static void +_dri_put_st_api(void) +{ + struct st_api *stapi = dri_st_api.stapi; + + if (p_atomic_dec_zero(&dri_st_api.refcnt)) { + stapi->destroy(dri_st_api.stapi); + dri_st_api.stapi = NULL; + } +} + +/** + * Create a state tracker manager from the given screen. + */ +struct st_manager * +dri_create_st_manager(struct dri_screen *screen) +{ + struct st_manager *smapi; + + smapi = CALLOC_STRUCT(st_manager); + if (smapi) { + smapi->screen = screen->pipe_screen; + _dri_get_st_api(); + } + + return smapi; +} + +/** + * Destroy a state tracker manager. + */ +void +dri_destroy_st_manager(struct st_manager *smapi) +{ + _dri_put_st_api(); + FREE(smapi); +} + +/** + * Return the st_api of OpenGL state tracker. + */ +struct st_api * +dri_get_st_api(void) +{ + assert(dri_st_api.stapi); + return dri_st_api.stapi; +} diff --git a/src/gallium/state_trackers/dri/dri_st_api.h b/src/gallium/state_trackers/dri/dri_st_api.h new file mode 100644 index 0000000000..7cf522e469 --- /dev/null +++ b/src/gallium/state_trackers/dri/dri_st_api.h @@ -0,0 +1,55 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#ifndef _DRI_ST_API_H_ +#define _DRI_ST_API_H_ + +#include "state_tracker/st_api.h" + +struct dri_screen; +struct dri_drawable; + +struct st_api * +dri_get_st_api(void); + +struct st_manager * +dri_create_st_manager(struct dri_screen *screen); + +void +dri_destroy_st_manager(struct st_manager *smapi); + +struct st_framebuffer_iface * +dri_create_st_framebuffer(struct dri_drawable *drawable); + +void +dri_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi); + +struct pipe_texture * +dri_get_st_framebuffer_texture(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt); + +#endif /* _DRI_ST_API_H_ */ diff --git a/src/gallium/state_trackers/es/Makefile b/src/gallium/state_trackers/es/Makefile index e33685d247..089d441167 100644 --- a/src/gallium/state_trackers/es/Makefile +++ b/src/gallium/state_trackers/es/Makefile @@ -38,6 +38,7 @@ SYS_LIBS = -lm -pthread INCLUDE_DIRS = \ + -I$(TOP)/include \ -I$(TOP)/src/mesa \ -I$(TOP)/src/gallium/include diff --git a/src/gallium/state_trackers/vega/api_filters.c b/src/gallium/state_trackers/vega/api_filters.c index 01c9896edd..223f16329d 100644 --- a/src/gallium/state_trackers/vega/api_filters.c +++ b/src/gallium/state_trackers/vega/api_filters.c @@ -40,6 +40,7 @@ #include "util/u_format.h" #include "util/u_memory.h" +#include "util/u_sampler.h" #include "asm_filters.h" @@ -53,7 +54,7 @@ struct filter_info { const void *const_buffer; VGint const_buffer_len; VGTilingMode tiling_mode; - struct pipe_resource *extra_texture; + struct pipe_sampler_view *extra_texture_view; }; static INLINE struct pipe_resource *create_texture_1d(struct vg_context *ctx, @@ -91,13 +92,35 @@ static INLINE struct pipe_resource *create_texture_1d(struct vg_context *ctx, return tex; } +static INLINE struct pipe_sampler_view *create_texture_1d_view(struct vg_context *ctx, + const VGuint *color_data, + const VGint color_data_len) +{ + struct pipe_context *pipe = ctx->pipe; + struct pipe_texture *texture; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view; + + texture = create_texture_1d(ctx, color_data, color_data_len); + + if (!texture) + return NULL; + + u_sampler_view_default_template(&view_templ, texture, texture->format); + view = pipe->create_sampler_view(pipe, texture, &view_templ); + /* want the texture to go away if the view is freed */ + pipe_texture_reference(&texture, NULL); + + return view; +} + static INLINE struct pipe_surface * setup_framebuffer(struct vg_image *dst) { struct vg_context *ctx = vg_current_context(); struct pipe_context *pipe = ctx->pipe; struct pipe_framebuffer_state fb; struct pipe_surface *dst_surf = pipe->screen->get_tex_surface( - pipe->screen, dst->texture, 0, 0, 0, + pipe->screen, dst->sampler_view->texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); /* drawing dest */ @@ -168,7 +191,7 @@ static void setup_constant_buffer(struct vg_context *ctx, const void *buffer, static void setup_samplers(struct vg_context *ctx, struct filter_info *info) { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; - struct pipe_resource *textures[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; struct pipe_sampler_state sampler[3]; int num_samplers = 0; int num_textures = 0; @@ -177,10 +200,10 @@ static void setup_samplers(struct vg_context *ctx, struct filter_info *info) samplers[1] = NULL; samplers[2] = NULL; samplers[3] = NULL; - textures[0] = NULL; - textures[1] = NULL; - textures[2] = NULL; - textures[3] = NULL; + sampler_views[0] = NULL; + sampler_views[1] = NULL; + sampler_views[2] = NULL; + sampler_views[3] = NULL; memset(&sampler[0], 0, sizeof(struct pipe_sampler_state)); sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; @@ -215,21 +238,21 @@ static void setup_samplers(struct vg_context *ctx, struct filter_info *info) } samplers[0] = &sampler[0]; - textures[0] = info->src->texture; + sampler_views[0] = info->src->sampler_view; ++num_samplers; ++num_textures; - if (info->extra_texture) { + if (info->extra_texture_view) { memcpy(&sampler[1], &sampler[0], sizeof(struct pipe_sampler_state)); samplers[1] = &sampler[1]; - textures[1] = info->extra_texture; + sampler_views[1] = info->extra_texture_view; ++num_samplers; ++num_textures; } cso_set_samplers(ctx->cso_context, num_samplers, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(ctx->cso_context, num_textures, textures); + cso_set_fragment_sampler_views(ctx->cso_context, num_textures, sampler_views); } static struct vg_shader * setup_color_matrix(struct vg_context *ctx, void *user_data) @@ -308,7 +331,7 @@ static void execute_filter(struct vg_context *ctx, cso_save_viewport(ctx->cso_context); cso_save_blend(ctx->cso_context); cso_save_samplers(ctx->cso_context); - cso_save_sampler_textures(ctx->cso_context); + cso_save_fragment_sampler_views(ctx->cso_context); dst_surf = setup_framebuffer(info->dst); setup_viewport(info->dst); @@ -318,7 +341,7 @@ static void execute_filter(struct vg_context *ctx, setup_samplers(ctx, info); renderer_draw_texture(ctx->renderer, - info->src->texture, + info->src->sampler_view->texture, info->dst->x, info->dst->y, info->dst->x + info->dst->width, info->dst->y + info->dst->height, @@ -331,7 +354,7 @@ static void execute_filter(struct vg_context *ctx, cso_restore_viewport(ctx->cso_context); cso_restore_blend(ctx->cso_context); cso_restore_samplers(ctx->cso_context); - cso_restore_sampler_textures(ctx->cso_context); + cso_restore_fragment_sampler_views(ctx->cso_context); vg_shader_destroy(ctx, shader); @@ -369,7 +392,7 @@ void vgColorMatrix(VGImage dst, VGImage src, info.const_buffer = matrix; info.const_buffer_len = 20 * sizeof(VGfloat); info.tiling_mode = VG_TILE_PAD; - info.extra_texture = 0; + info.extra_texture_view = NULL; execute_filter(ctx, &info); } @@ -479,7 +502,7 @@ void vgConvolve(VGImage dst, VGImage src, info.const_buffer = buffer; info.const_buffer_len = buffer_len * sizeof(VGfloat); info.tiling_mode = tilingMode; - info.extra_texture = 0; + info.extra_texture_view = NULL; execute_filter(ctx, &info); free(buffer); @@ -669,7 +692,7 @@ void vgGaussianBlur(VGImage dst, VGImage src, info.const_buffer = buffer; info.const_buffer_len = buffer_len * sizeof(VGfloat); info.tiling_mode = tilingMode; - info.extra_texture = 0; + info.extra_texture_view = NULL; execute_filter(ctx, &info); free(buffer); @@ -688,7 +711,7 @@ void vgLookup(VGImage dst, VGImage src, struct vg_image *d, *s; VGuint color_data[256]; VGint i; - struct pipe_resource *lut_texture; + struct pipe_sampler_view *lut_texture_view; VGfloat buffer[4]; struct filter_info info; @@ -714,7 +737,7 @@ void vgLookup(VGImage dst, VGImage src, color_data[i] = blueLUT[i] << 24 | greenLUT[i] << 16 | redLUT[i] << 8 | alphaLUT[i]; } - lut_texture = create_texture_1d(ctx, color_data, 255); + lut_texture_view = create_texture_1d_view(ctx, color_data, 255); buffer[0] = 0.f; buffer[1] = 0.f; @@ -728,11 +751,11 @@ void vgLookup(VGImage dst, VGImage src, info.const_buffer = buffer; info.const_buffer_len = 4 * sizeof(VGfloat); info.tiling_mode = VG_TILE_PAD; - info.extra_texture = lut_texture; + info.extra_texture_view = lut_texture_view; execute_filter(ctx, &info); - pipe_resource_reference(&lut_texture, NULL); + pipe_sampler_view_reference(&lut_texture_view, NULL); } void vgLookupSingle(VGImage dst, VGImage src, @@ -743,7 +766,7 @@ void vgLookupSingle(VGImage dst, VGImage src, { struct vg_context *ctx = vg_current_context(); struct vg_image *d, *s; - struct pipe_resource *lut_texture; + struct pipe_sampler_view *lut_texture_view; VGfloat buffer[4]; struct filter_info info; VGuint color_data[256]; @@ -783,7 +806,7 @@ void vgLookupSingle(VGImage dst, VGImage src, color_data[i] = blue << 24 | green << 16 | red << 8 | alpha; } - lut_texture = create_texture_1d(ctx, color_data, 256); + lut_texture_view = create_texture_1d_view(ctx, color_data, 256); buffer[0] = 0.f; buffer[1] = 0.f; @@ -797,9 +820,9 @@ void vgLookupSingle(VGImage dst, VGImage src, info.const_buffer = buffer; info.const_buffer_len = 4 * sizeof(VGfloat); info.tiling_mode = VG_TILE_PAD; - info.extra_texture = lut_texture; + info.extra_texture_view = lut_texture_view; execute_filter(ctx, &info); - pipe_resource_reference(&lut_texture, NULL); + pipe_sampler_view_reference(&lut_texture_view, NULL); } diff --git a/src/gallium/state_trackers/vega/image.c b/src/gallium/state_trackers/vega/image.c index 2f55d80601..197593b267 100644 --- a/src/gallium/state_trackers/vega/image.c +++ b/src/gallium/state_trackers/vega/image.c @@ -43,6 +43,7 @@ #include "util/u_tile.h" #include "util/u_memory.h" #include "util/u_math.h" +#include "util/u_sampler.h" static enum pipe_format vg_format_to_pipe(VGImageFormat format) { @@ -81,7 +82,7 @@ static INLINE void vg_sync_size(VGfloat *src_loc, VGfloat *dst_loc) static void vg_copy_texture(struct vg_context *ctx, struct pipe_resource *dst, VGint dx, VGint dy, - struct pipe_resource *src, VGint sx, VGint sy, + struct pipe_sampler_view *src, VGint sx, VGint sy, VGint width, VGint height) { VGfloat dst_loc[4], src_loc[4]; @@ -103,8 +104,8 @@ static void vg_copy_texture(struct vg_context *ctx, src_loc[3] = height; src_bounds[0] = 0.f; src_bounds[1] = 0.f; - src_bounds[2] = src->width0; - src_bounds[3] = src->height0; + src_bounds[2] = src->texture->width0; + src_bounds[3] = src->texture->height0; vg_bound_rect(src_loc, src_bounds, src_shift); vg_bound_rect(dst_loc, dst_bounds, dst_shift); @@ -218,7 +219,7 @@ void vg_copy_surface(struct vg_context *ctx, static struct pipe_resource *image_texture(struct vg_image *img) { - struct pipe_resource *tex = img->texture; + struct pipe_resource *tex = img->sampler_view->texture; return tex; } @@ -247,9 +248,12 @@ struct vg_image * image_create(VGImageFormat format, VGint width, VGint height) { struct vg_context *ctx = vg_current_context(); + struct pipe_context *pipe = ctx->pipe; struct vg_image *image = CALLOC_STRUCT(vg_image); enum pipe_format pformat = vg_format_to_pipe(format); struct pipe_resource pt, *newtex; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view; struct pipe_screen *screen = ctx->pipe->screen; vg_init_object(&image->base, ctx, VG_OBJECT_IMAGE); @@ -281,7 +285,12 @@ struct vg_image * image_create(VGImageFormat format, debug_assert(newtex); - image->texture = newtex; + u_sampler_view_default_template(&view_templ, newtex, newtex->format); + view = pipe->create_sampler_view(pipe, newtex, &view_templ); + /* want the texture to go away if the view is freed */ + pipe_texture_reference(&newtex, NULL); + + image->sampler_view = view; vg_context_add_object(ctx, VG_OBJECT_IMAGE, image); @@ -345,7 +354,7 @@ void image_destroy(struct vg_image *img) array_destroy(img->children_array); } - pipe_resource_reference(&img->texture, NULL); + pipe_sampler_view_reference(&img->sampler_view, NULL); free(img); } @@ -444,7 +453,7 @@ void image_get_sub_data(struct vg_image * image, { struct pipe_transfer *transfer = pipe_get_transfer(pipe, - image->texture, 0, 0, 0, + image->sampler_view->texture, 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, image->x + image->width, @@ -478,9 +487,9 @@ struct vg_image * image_child_image(struct vg_image *parent, image->width = width; image->height = height; image->parent = parent; - image->texture = 0; - pipe_resource_reference(&image->texture, - parent->texture); + image->sampler_view = NULL; + pipe_sampler_view_reference(&image->sampler_view, + parent->sampler_view); image->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; image->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; @@ -514,8 +523,8 @@ void image_copy(struct vg_image *dst, VGint dx, VGint dy, } /* make sure rendering has completed */ ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL); - vg_copy_texture(ctx, dst->texture, dst->x + dx, dst->y + dy, - src->texture, src->x + sx, src->y + sy, width, height); + vg_copy_texture(ctx, dst->sampler_view->texture, dst->x + dx, dst->y + dy, + src->sampler_view, src->x + sx, src->y + sy, width, height); } void image_draw(struct vg_image *img) @@ -624,12 +633,12 @@ VGboolean vg_image_overlaps(struct vg_image *dst, } VGint image_bind_samplers(struct vg_image *img, struct pipe_sampler_state **samplers, - struct pipe_resource **textures) + struct pipe_sampler_view **sampler_views) { img->sampler.min_img_filter = image_sampler_filter(img->base.ctx); img->sampler.mag_img_filter = image_sampler_filter(img->base.ctx); samplers[3] = &img->sampler; - textures[3] = img->texture; + sampler_views[3] = img->sampler_view; return 1; } diff --git a/src/gallium/state_trackers/vega/image.h b/src/gallium/state_trackers/vega/image.h index 8dcaf131b6..a990c9c587 100644 --- a/src/gallium/state_trackers/vega/image.h +++ b/src/gallium/state_trackers/vega/image.h @@ -43,7 +43,7 @@ struct vg_image { struct vg_image *parent; - struct pipe_resource *texture; + struct pipe_sampler_view *sampler_view; struct pipe_sampler_state sampler; struct array *children_array; @@ -89,7 +89,7 @@ void image_get_pixels(struct vg_image *dst, VGint dx, VGint dy, VGint width, VGint height); VGint image_bind_samplers(struct vg_image *dst, struct pipe_sampler_state **samplers, - struct pipe_resource **textures); + struct pipe_sampler_view **sampler_views); VGboolean vg_image_overlaps(struct vg_image *dst, struct vg_image *src); diff --git a/src/gallium/state_trackers/vega/mask.c b/src/gallium/state_trackers/vega/mask.c index 379e46b275..41bfd97ed0 100644 --- a/src/gallium/state_trackers/vega/mask.c +++ b/src/gallium/state_trackers/vega/mask.c @@ -45,7 +45,7 @@ struct vg_mask_layer { VGint width; VGint height; - struct pipe_resource *texture; + struct pipe_sampler_view *sampler_view; }; static INLINE struct pipe_surface * @@ -54,7 +54,7 @@ alpha_mask_surface(struct vg_context *ctx, int usage) struct pipe_screen *screen = ctx->pipe->screen; struct st_framebuffer *stfb = ctx->draw_buffer; return screen->get_tex_surface(screen, - stfb->alpha_mask, + stfb->alpha_mask_view->texture, 0, 0, 0, usage); } @@ -284,35 +284,33 @@ static void setup_mask_operation(VGMaskOperation operation) cso_set_fragment_shader_handle(ctx->cso_context, shader); } -static void setup_mask_samplers(struct pipe_resource *umask) +static void setup_mask_samplers(struct pipe_sampler_view *umask) { struct vg_context *ctx = vg_current_context(); struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; - struct pipe_resource *textures[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; struct st_framebuffer *fb_buffers = ctx->draw_buffer; - struct pipe_resource *uprev = NULL; + struct pipe_sampler_view *uprev = NULL; struct pipe_sampler_state sampler; - uprev = fb_buffers->blend_texture; + uprev = fb_buffers->blend_texture_view; sampler = ctx->mask.sampler; sampler.normalized_coords = 1; samplers[0] = NULL; samplers[1] = NULL; - samplers[2] = NULL; - textures[0] = NULL; - textures[1] = NULL; - textures[2] = NULL; + sampler_views[0] = NULL; + sampler_views[1] = NULL; samplers[0] = &sampler; samplers[1] = &ctx->mask.sampler; - textures[0] = umask; - textures[1] = uprev; + sampler_views[0] = umask; + sampler_views[1] = uprev; cso_set_samplers(ctx->cso_context, 2, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(ctx->cso_context, 2, textures); + cso_set_fragment_sampler_views(ctx->cso_context, 2, sampler_views); } @@ -411,12 +409,13 @@ static void surface_fill(struct pipe_surface *surf, } -static void mask_using_texture(struct pipe_resource *texture, +static void mask_using_texture(struct pipe_sampler_view *sampler_view, VGMaskOperation operation, VGint x, VGint y, VGint width, VGint height) { struct vg_context *ctx = vg_current_context(); + struct pipe_texture *texture = sampler_view->texture; struct pipe_surface *surface = alpha_mask_surface(ctx, PIPE_BUFFER_USAGE_GPU_WRITE); VGint offsets[4], loc[4]; @@ -439,13 +438,13 @@ static void mask_using_texture(struct pipe_resource *texture, vg_prepare_blend_surface_from_mask(ctx); cso_save_samplers(ctx->cso_context); - cso_save_sampler_textures(ctx->cso_context); + cso_save_fragment_sampler_views(ctx->cso_context); cso_save_framebuffer(ctx->cso_context); cso_save_blend(ctx->cso_context); cso_save_fragment_shader(ctx->cso_context); cso_save_viewport(ctx->cso_context); - setup_mask_samplers(texture); + setup_mask_samplers(sampler_view); setup_mask_blend(); setup_mask_operation(operation); setup_mask_framebuffer(surface, surface->width, surface->height); @@ -463,7 +462,7 @@ static void mask_using_texture(struct pipe_resource *texture, cso_restore_framebuffer(ctx->cso_context); cso_restore_fragment_shader(ctx->cso_context); cso_restore_samplers(ctx->cso_context); - cso_restore_sampler_textures(ctx->cso_context); + cso_restore_fragment_sampler_views(ctx->cso_context); cso_restore_viewport(ctx->cso_context); pipe_surface_reference(&surface, NULL); @@ -484,7 +483,11 @@ struct vg_mask_layer * mask_layer_create(VGint width, VGint height) { struct pipe_resource pt; + struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = ctx->pipe->screen; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view = NULL; + struct pipe_texture *texture; memset(&pt, 0, sizeof(pt)); pt.target = PIPE_TEXTURE_2D; @@ -496,7 +499,14 @@ struct vg_mask_layer * mask_layer_create(VGint width, VGint height) pt.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; pt.compressed = 0; - mask->texture = screen->resource_create(screen, &pt); + texture = screen->resource_create(screen, &pt); + + if (texture) { + u_sampler_view_default_template(&view_templ, texture, texture->format); + view = pipe->create_sampler_view(pipe, texture, &view_templ); + } + pipe_resource_reference(&texture, NULL); + mask->sampler_view = view; } vg_context_add_object(ctx, VG_OBJECT_MASK, mask); @@ -525,7 +535,7 @@ void mask_layer_fill(struct vg_mask_layer *layer, alpha_color[3] = value; surface = ctx->pipe->screen->get_tex_surface( - ctx->pipe->screen, layer->texture, + ctx->pipe->screen, layer->sampler_view->texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); @@ -545,10 +555,10 @@ void mask_copy(struct vg_mask_layer *layer, struct st_framebuffer *fb_buffers = ctx->draw_buffer; renderer_copy_texture(ctx->renderer, - layer->texture, + layer->sampler_view, sx, sy, sx + width, sy + height, - fb_buffers->alpha_mask, + fb_buffers->alpha_mask_view->texture, dx, dy, dx + width, dy + height); } @@ -562,7 +572,7 @@ static void mask_layer_render_to(struct vg_mask_layer *layer, struct pipe_screen *screen = ctx->pipe->screen; struct pipe_surface *surface; - surface = screen->get_tex_surface(screen, layer->texture, 0, 0, 0, + surface = screen->get_tex_surface(screen, layer->sampler_view->texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); cso_save_framebuffer(ctx->cso_context); @@ -604,8 +614,8 @@ void mask_render_to(struct path *path, struct vg_mask_layer *temp_layer; VGint width, height; - width = fb_buffers->alpha_mask->width0; - height = fb_buffers->alpha_mask->width0; + width = fb_buffers->alpha_mask_view->texture->width0; + height = fb_buffers->alpha_mask_view->texture->width0; temp_layer = mask_layer_create(width, height); @@ -622,7 +632,7 @@ void mask_using_layer(struct vg_mask_layer *layer, VGint x, VGint y, VGint width, VGint height) { - mask_using_texture(layer->texture, operation, + mask_using_texture(layer->sampler_view, operation, x, y, width, height); } @@ -644,7 +654,7 @@ void mask_using_image(struct vg_image *image, VGint x, VGint y, VGint width, VGint height) { - mask_using_texture(image->texture, operation, + mask_using_texture(image->sampler_view, operation, x, y, width, height); } @@ -672,7 +682,7 @@ void mask_fill(VGint x, VGint y, VGint width, VGint height, } VGint mask_bind_samplers(struct pipe_sampler_state **samplers, - struct pipe_resource **textures) + struct pipe_sampler_view **sampler_views) { struct vg_context *ctx = vg_current_context(); @@ -680,7 +690,7 @@ VGint mask_bind_samplers(struct pipe_sampler_state **samplers, struct st_framebuffer *fb_buffers = ctx->draw_buffer; samplers[1] = &ctx->mask.sampler; - textures[1] = fb_buffers->alpha_mask; + sampler_views[1] = fb_buffers->alpha_mask_view; return 1; } else return 0; diff --git a/src/gallium/state_trackers/vega/mask.h b/src/gallium/state_trackers/vega/mask.h index 1489257193..c626402c86 100644 --- a/src/gallium/state_trackers/vega/mask.h +++ b/src/gallium/state_trackers/vega/mask.h @@ -63,6 +63,6 @@ void mask_fill(VGint x, VGint y, VGfloat value); VGint mask_bind_samplers(struct pipe_sampler_state **samplers, - struct pipe_resource **textures); + struct pipe_sampler_view **sampler_views); #endif diff --git a/src/gallium/state_trackers/vega/paint.c b/src/gallium/state_trackers/vega/paint.c index 5c1482cb07..2aa8b254c9 100644 --- a/src/gallium/state_trackers/vega/paint.c +++ b/src/gallium/state_trackers/vega/paint.c @@ -37,6 +37,7 @@ #include "util/u_format.h" #include "util/u_memory.h" #include "util/u_math.h" +#include "util/u_sampler.h" #include "cso_cache/cso_context.h" @@ -61,7 +62,7 @@ struct vg_paint { VGfloat vals[5]; VGint valsi[5]; } radial; - struct pipe_resource *texture; + struct pipe_sampler_view *sampler_view; struct pipe_sampler_state sampler; VGfloat *ramp_stops; @@ -72,7 +73,7 @@ struct vg_paint { } gradient; struct { - struct pipe_resource *texture; + struct pipe_sampler_view *sampler_view; VGTilingMode tiling_mode; struct pipe_sampler_state sampler; } pattern; @@ -173,6 +174,26 @@ static INLINE struct pipe_resource *create_gradient_texture(struct vg_paint *p) return tex; } +static INLINE struct pipe_sampler_view *create_gradient_sampler_view(struct vg_paint *p) +{ + struct pipe_context *pipe = p->base.ctx->pipe; + struct pipe_texture *texture; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view; + + texture = create_gradient_texture(p); + + if (!texture) + return NULL; + + u_sampler_view_default_template(&view_templ, texture, texture->format); + view = pipe->create_sampler_view(pipe, texture, &view_templ); + /* want the texture to go away if the view is freed */ + pipe_texture_reference(&texture, NULL); + + return view; +} + struct vg_paint * paint_create(struct vg_context *ctx) { struct vg_paint *paint = CALLOC_STRUCT(vg_paint); @@ -207,8 +228,9 @@ struct vg_paint * paint_create(struct vg_context *ctx) void paint_destroy(struct vg_paint *paint) { struct vg_context *ctx = paint->base.ctx; - if (paint->pattern.texture) - pipe_resource_reference(&paint->pattern.texture, NULL); + pipe_sampler_view_reference(&paint->gradient.sampler_view, NULL); + if (paint->pattern.sampler_view) + pipe_sampler_view_reference(&paint->pattern.sampler_view, NULL); if (ctx) vg_context_remove_object(ctx, VG_OBJECT_PAINT, paint); @@ -329,8 +351,8 @@ static INLINE void paint_pattern_buffer(struct vg_paint *paint, void *buffer) map[4] = 0.f; map[5] = 1.f; - map[6] = paint->pattern.texture->width0; - map[7] = paint->pattern.texture->height0; + map[6] = paint->pattern.sampler_view->texture->width0; + map[7] = paint->pattern.sampler_view->texture->height0; { struct matrix mat; memcpy(&mat, &ctx->state.vg.fill_paint_to_user_matrix, @@ -394,12 +416,12 @@ void paint_set_ramp_stops(struct vg_paint *paint, const VGfloat *stops, create_gradient_data(stops, num / 5, paint->gradient.color_data, 1024); - if (paint->gradient.texture) { - pipe_resource_reference(&paint->gradient.texture, NULL); - paint->gradient.texture = 0; + if (paint->gradient.sampler_view) { + pipe_sampler_view_reference(&paint->gradient.sampler_view, NULL); + paint->gradient.sampler_view = NULL; } - paint->gradient.texture = create_gradient_texture(paint); + paint->gradient.sampler_view = create_gradient_sampler_view(paint); } void paint_set_colori(struct vg_paint *p, @@ -459,12 +481,12 @@ void paint_set_radial_gradient(struct vg_paint *paint, void paint_set_pattern(struct vg_paint *paint, struct vg_image *img) { - if (paint->pattern.texture) - pipe_resource_reference(&paint->pattern.texture, NULL); + if (paint->pattern.sampler_view) + pipe_sampler_view_reference(&paint->pattern.sampler_view, NULL); - paint->pattern.texture = 0; - pipe_resource_reference(&paint->pattern.texture, - img->texture); + paint->pattern.sampler_view = NULL; + pipe_sampler_view_reference(&paint->pattern.sampler_view, + img->sampler_view); } void paint_set_pattern_tiling(struct vg_paint *paint, @@ -611,18 +633,18 @@ VGTilingMode paint_pattern_tiling(struct vg_paint *paint) } VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers, - struct pipe_resource **textures) + struct pipe_sampler_view **sampler_views) { struct vg_context *ctx = vg_current_context(); switch(paint->type) { case VG_PAINT_TYPE_LINEAR_GRADIENT: case VG_PAINT_TYPE_RADIAL_GRADIENT: { - if (paint->gradient.texture) { + if (paint->gradient.sampler_view) { paint->gradient.sampler.min_img_filter = image_sampler_filter(ctx); paint->gradient.sampler.mag_img_filter = image_sampler_filter(ctx); samplers[0] = &paint->gradient.sampler; - textures[0] = paint->gradient.texture; + sampler_views[0] = paint->gradient.sampler_view; return 1; } } @@ -634,7 +656,7 @@ VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **sa paint->pattern.sampler.min_img_filter = image_sampler_filter(ctx); paint->pattern.sampler.mag_img_filter = image_sampler_filter(ctx); samplers[0] = &paint->pattern.sampler; - textures[0] = paint->pattern.texture; + sampler_views[0] = paint->pattern.sampler_view; return 1; } break; @@ -647,7 +669,7 @@ VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **sa void paint_resolve_type(struct vg_paint *paint) { if (paint->type == VG_PAINT_TYPE_PATTERN && - !paint->pattern.texture) { + !paint->pattern.sampler_view) { paint->type = VG_PAINT_TYPE_COLOR; } } diff --git a/src/gallium/state_trackers/vega/paint.h b/src/gallium/state_trackers/vega/paint.h index cf9a701c35..012cd3e561 100644 --- a/src/gallium/state_trackers/vega/paint.h +++ b/src/gallium/state_trackers/vega/paint.h @@ -108,7 +108,7 @@ VGboolean paint_color_ramp_premultiplied(struct vg_paint *paint); VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers, - struct pipe_resource **textures); + struct pipe_sampler_view **sampler_views); VGint paint_constant_buffer_size(struct vg_paint *paint); void paint_fill_constant_buffer(struct vg_paint *paint, diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c index 415dd5e1a8..b9ace37ce4 100644 --- a/src/gallium/state_trackers/vega/renderer.c +++ b/src/gallium/state_trackers/vega/renderer.c @@ -39,6 +39,7 @@ #include "util/u_simple_shaders.h" #include "util/u_memory.h" #include "util/u_rect.h" +#include "util/u_sampler.h" #include "cso_cache/cso_context.h" @@ -266,7 +267,7 @@ void renderer_draw_texture(struct renderer *r, } void renderer_copy_texture(struct renderer *ctx, - struct pipe_resource *src, + struct pipe_sampler_view *src, VGfloat sx1, VGfloat sy1, VGfloat sx2, VGfloat sy2, struct pipe_resource *dst, @@ -275,6 +276,7 @@ void renderer_copy_texture(struct renderer *ctx, { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; + struct pipe_resource *tex = src->texture; struct pipe_resource *buf; struct pipe_surface *dst_surf = screen->get_tex_surface( screen, dst, 0, 0, 0, @@ -282,8 +284,8 @@ void renderer_copy_texture(struct renderer *ctx, struct pipe_framebuffer_state fb; float s0, t0, s1, t1; - assert(src->width0 != 0); - assert(src->height0 != 0); + assert(tex->width0 != 0); + assert(tex->height0 != 0); assert(dst->width0 != 0); assert(dst->height0 != 0); @@ -293,10 +295,10 @@ void renderer_copy_texture(struct renderer *ctx, #endif #if 1 - s0 = sx1 / src->width0; - s1 = sx2 / src->width0; - t0 = sy1 / src->height0; - t1 = sy2 / src->height0; + s0 = sx1 / tex->width0; + s1 = sx2 / tex->width0; + t0 = sy1 / tex->height0; + t1 = sy2 / tex->height0; #else s0 = 0; s1 = 1; @@ -310,7 +312,7 @@ void renderer_copy_texture(struct renderer *ctx, /* save state (restored below) */ cso_save_blend(ctx->cso); cso_save_samplers(ctx->cso); - cso_save_sampler_textures(ctx->cso); + cso_save_fragment_sampler_views(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); @@ -348,7 +350,7 @@ void renderer_copy_texture(struct renderer *ctx, vg_set_viewport(ctx->owner, VEGA_Y0_TOP); /* texture */ - cso_set_sampler_textures(ctx->cso, 1, &src); + cso_set_fragment_sampler_views(ctx->cso, 1, &src); /* shaders */ cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner)); @@ -388,7 +390,7 @@ void renderer_copy_texture(struct renderer *ctx, /* restore state we changed */ cso_restore_blend(ctx->cso); cso_restore_samplers(ctx->cso); - cso_restore_sampler_textures(ctx->cso); + cso_restore_fragment_sampler_views(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_vertex_shader(ctx->cso); cso_restore_fragment_shader(ctx->cso); @@ -409,6 +411,8 @@ void renderer_copy_surface(struct renderer *ctx, struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_resource *buf; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view; struct pipe_resource texTemp, *tex; struct pipe_surface *texSurf; struct pipe_framebuffer_state fb; @@ -460,6 +464,12 @@ void renderer_copy_surface(struct renderer *ctx, if (!tex) return; + u_sampler_view_default_template(&view_templ, tex, tex->format); + view = pipe->create_sampler_view(pipe, tex, &view_templ); + + if (!view) + return; + texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); @@ -482,7 +492,7 @@ void renderer_copy_surface(struct renderer *ctx, /* save state (restored below) */ cso_save_blend(ctx->cso); cso_save_samplers(ctx->cso); - cso_save_sampler_textures(ctx->cso); + cso_save_fragment_sampler_views(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); @@ -518,7 +528,7 @@ void renderer_copy_surface(struct renderer *ctx, } /* texture */ - cso_set_sampler_textures(ctx->cso, 1, &tex); + cso_set_fragment_sampler_views(ctx->cso, 1, &view); /* shaders */ cso_set_fragment_shader_handle(ctx->cso, ctx->fs); @@ -555,13 +565,14 @@ void renderer_copy_surface(struct renderer *ctx, /* restore state we changed */ cso_restore_blend(ctx->cso); cso_restore_samplers(ctx->cso); - cso_restore_sampler_textures(ctx->cso); + cso_restore_fragment_sampler_views(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_vertex_shader(ctx->cso); cso_restore_viewport(ctx->cso); pipe_resource_reference(&tex, NULL); + pipe_sampler_view_reference(&view, NULL); } void renderer_texture_quad(struct renderer *r, diff --git a/src/gallium/state_trackers/vega/renderer.h b/src/gallium/state_trackers/vega/renderer.h index 6afb3097f3..b1a9fb58be 100644 --- a/src/gallium/state_trackers/vega/renderer.h +++ b/src/gallium/state_trackers/vega/renderer.h @@ -33,6 +33,7 @@ struct renderer; struct vg_context; struct pipe_resource; +struct pipe_sampler_view; struct pipe_surface; struct renderer *renderer_create(struct vg_context *owner); @@ -57,7 +58,7 @@ void renderer_texture_quad(struct renderer *, VGfloat x3, VGfloat y3, VGfloat x4, VGfloat y4); void renderer_copy_texture(struct renderer *r, - struct pipe_resource *src, + struct pipe_sampler_view *src, VGfloat sx1, VGfloat sy1, VGfloat sx2, VGfloat sy2, struct pipe_resource *dst, diff --git a/src/gallium/state_trackers/vega/shader.c b/src/gallium/state_trackers/vega/shader.c index e1a3676612..288515d9ad 100644 --- a/src/gallium/state_trackers/vega/shader.c +++ b/src/gallium/state_trackers/vega/shader.c @@ -120,7 +120,7 @@ static void setup_constant_buffer(struct shader *shader) static VGint blend_bind_samplers(struct vg_context *ctx, struct pipe_sampler_state **samplers, - struct pipe_resource **textures) + struct pipe_sampler_view **sampler_views) { VGBlendMode bmode = ctx->state.vg.blend_mode; @@ -133,15 +133,15 @@ static VGint blend_bind_samplers(struct vg_context *ctx, vg_prepare_blend_surface(ctx); samplers[2] = &ctx->blend_sampler; - textures[2] = stfb->blend_texture; + sampler_views[2] = stfb->blend_texture_view; - if (!samplers[0] || !textures[0]) { + if (!samplers[0] || !sampler_views[0]) { samplers[0] = samplers[2]; - textures[0] = textures[2]; + sampler_views[0] = sampler_views[2]; } - if (!samplers[1] || !textures[1]) { + if (!samplers[1] || !sampler_views[1]) { samplers[1] = samplers[0]; - textures[1] = textures[0]; + sampler_views[1] = sampler_views[0]; } return 1; @@ -152,7 +152,7 @@ static VGint blend_bind_samplers(struct vg_context *ctx, static void setup_samplers(struct shader *shader) { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; - struct pipe_resource *textures[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; struct vg_context *ctx = shader->context; /* a little wonky: we use the num as a boolean that just says * whether any sampler/textures have been set. the actual numbering @@ -168,20 +168,20 @@ static void setup_samplers(struct shader *shader) samplers[1] = NULL; samplers[2] = NULL; samplers[3] = NULL; - textures[0] = NULL; - textures[1] = NULL; - textures[2] = NULL; - textures[3] = NULL; - - num += paint_bind_samplers(shader->paint, samplers, textures); - num += mask_bind_samplers(samplers, textures); - num += blend_bind_samplers(ctx, samplers, textures); + sampler_views[0] = NULL; + sampler_views[1] = NULL; + sampler_views[2] = NULL; + sampler_views[3] = NULL; + + num += paint_bind_samplers(shader->paint, samplers, sampler_views); + num += mask_bind_samplers(samplers, sampler_views); + num += blend_bind_samplers(ctx, samplers, sampler_views); if (shader->drawing_image && shader->image) - num += image_bind_samplers(shader->image, samplers, textures); + num += image_bind_samplers(shader->image, samplers, sampler_views); if (num) { cso_set_samplers(ctx->cso_context, 4, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(ctx->cso_context, 4, textures); + cso_set_fragment_sampler_views(ctx->cso_context, 4, sampler_views); } } diff --git a/src/gallium/state_trackers/vega/vg_context.c b/src/gallium/state_trackers/vega/vg_context.c index 94e9ae5dad..f6a7cc638a 100644 --- a/src/gallium/state_trackers/vega/vg_context.c +++ b/src/gallium/state_trackers/vega/vg_context.c @@ -43,6 +43,7 @@ #include "util/u_simple_shaders.h" #include "util/u_memory.h" #include "util/u_blit.h" +#include "util/u_sampler.h" struct vg_context *_vg_context = 0; @@ -436,19 +437,24 @@ void vg_prepare_blend_surface(struct vg_context *ctx) { struct pipe_surface *dest_surface = NULL; struct pipe_context *pipe = ctx->pipe; + struct pipe_sampler_view *view; + struct pipe_sampler_view view_templ; struct st_framebuffer *stfb = ctx->draw_buffer; struct st_renderbuffer *strb = stfb->strb; /* first finish all pending rendering */ vgFinish(); + u_sampler_view_default_template(&view_templ, strb->texture, strb->texture->format); + view = pipe->create_sampler_view(pipe, strb->texture, &view_templ); + dest_surface = pipe->screen->get_tex_surface(pipe->screen, - stfb->blend_texture, + stfb->blend_texture_view->texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); /* flip it, because we want to use it as a sampler */ util_blit_pixels_tex(ctx->blit, - strb->texture, + view, 0, strb->height, strb->width, 0, dest_surface, @@ -461,6 +467,8 @@ void vg_prepare_blend_surface(struct vg_context *ctx) /* make sure it's complete */ vgFinish(); + + pipe_sampler_view_reference(&view, NULL); } @@ -477,13 +485,13 @@ void vg_prepare_blend_surface_from_mask(struct vg_context *ctx) vgFinish(); dest_surface = pipe->screen->get_tex_surface(pipe->screen, - stfb->blend_texture, + stfb->blend_texture_view->texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); /* flip it, because we want to use it as a sampler */ util_blit_pixels_tex(ctx->blit, - stfb->alpha_mask, + stfb->alpha_mask_view, 0, strb->height, strb->width, 0, dest_surface, diff --git a/src/gallium/state_trackers/vega/vg_context.h b/src/gallium/state_trackers/vega/vg_context.h index 52c291fbce..dac67192a5 100644 --- a/src/gallium/state_trackers/vega/vg_context.h +++ b/src/gallium/state_trackers/vega/vg_context.h @@ -55,9 +55,10 @@ struct st_framebuffer { struct st_renderbuffer *strb; struct st_renderbuffer *dsrb; - struct pipe_resource *alpha_mask; + struct pipe_sampler_view *alpha_mask_view; + + struct pipe_sampler_view *blend_texture_view; - struct pipe_resource *blend_texture; struct st_framebuffer_iface *iface; enum st_attachment_type strb_att; diff --git a/src/gallium/state_trackers/vega/vg_tracker.c b/src/gallium/state_trackers/vega/vg_tracker.c index 4e5921632e..e0a9d2bb65 100644 --- a/src/gallium/state_trackers/vega/vg_tracker.c +++ b/src/gallium/state_trackers/vega/vg_tracker.c @@ -32,6 +32,7 @@ #include "util/u_inlines.h" #include "pipe/p_screen.h" #include "util/u_format.h" +#include "util/u_sampler.h" #include "util/u_memory.h" #include "util/u_math.h" #include "util/u_rect.h" @@ -41,7 +42,7 @@ PUBLIC const int st_api_OpenVG = 1; static struct pipe_resource * create_texture(struct pipe_context *pipe, enum pipe_format format, - VGint width, VGint height) + VGint width, VGint height) { struct pipe_resource templ; @@ -71,6 +72,27 @@ create_texture(struct pipe_context *pipe, enum pipe_format format, return pipe->screen->resource_create(pipe->screen, &templ); } +static struct pipe_sampler_view * +create_tex_and_view(struct pipe_context *pipe, enum pipe_format format, + VGint width, VGint height) +{ + struct pipe_resource *texture; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view; + + texture = create_texture(pipe, format, width, height); + + if (!texture) + return NULL; + + u_sampler_view_default_template(&view_templ, texture, texture->format); + view = pipe->create_sampler_view(pipe, texture, &view_templ); + /* want the texture to go away if the view is freed */ + pipe_resource_reference(&texture, NULL); + + return view; +} + /** * Allocate a renderbuffer for a an on-screen window (not a user-created * renderbuffer). The window system code determines the format. @@ -115,8 +137,8 @@ st_renderbuffer_alloc_storage(struct vg_context * ctx, surface_usage = (PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE); - strb->texture = create_texture(pipe, strb->format, - width, height); + strb->texture = create_texture(pipe, strb->format, width, height); + if (!strb->texture) return FALSE; @@ -191,7 +213,7 @@ struct st_framebuffer * st_create_framebuffer(const void *visual, /*### currently we always allocate it but it's possible it's not necessary if EGL_ALPHA_MASK_SIZE was 0 */ - stfb->alpha_mask = 0; + stfb->alpha_mask_view = NULL; stfb->width = width; stfb->height = height; @@ -206,19 +228,19 @@ static void setup_new_alpha_mask(struct vg_context *ctx, uint width, uint height) { struct pipe_context *pipe = ctx->pipe; - struct pipe_resource *old_texture = stfb->alpha_mask; + struct pipe_sampler_view *old_sampler_view = stfb->alpha_mask_view; /* we use PIPE_FORMAT_B8G8R8A8_UNORM because we want to render to this texture and use it as a sampler, so while this wastes some space it makes both of those a lot simpler */ - stfb->alpha_mask = - create_texture(pipe, PIPE_FORMAT_B8G8R8A8_UNORM, width, height); + stfb->alpha_mask_view = + create_tex_and_view(pipe, PIPE_FORMAT_B8G8R8A8_UNORM, width, height); - if (!stfb->alpha_mask) { - if (old_texture) - pipe_resource_reference(&old_texture, NULL); + if (!stfb->alpha_mask_view) { + if (old_sampler_view) + pipe_sampler_view_reference(&old_sampler_view, NULL); return; } @@ -228,15 +250,15 @@ static void setup_new_alpha_mask(struct vg_context *ctx, mask_fill(0, 0, width, height, 1.f); /* if we had an old surface copy it over */ - if (old_texture) { + if (old_sampler_view) { struct pipe_surface *surface = pipe->screen->get_tex_surface( pipe->screen, - stfb->alpha_mask, + stfb->alpha_mask_view->texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); struct pipe_surface *old_surface = pipe->screen->get_tex_surface( pipe->screen, - old_texture, + old_sampler_view->texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ); if (pipe->surface_copy) { @@ -264,8 +286,8 @@ static void setup_new_alpha_mask(struct vg_context *ctx, /* Free the old texture */ - if (old_texture) - pipe_resource_reference(&old_texture, NULL); + if (old_sampler_view) + pipe_sampler_view_reference(&old_sampler_view, NULL); } void st_resize_framebuffer(struct st_framebuffer *stfb, @@ -326,9 +348,9 @@ void st_resize_framebuffer(struct st_framebuffer *stfb, setup_new_alpha_mask(ctx, stfb, width, height); - pipe_resource_reference( &stfb->blend_texture, NULL ); - stfb->blend_texture = create_texture(ctx->pipe, PIPE_FORMAT_B8G8R8A8_UNORM, - width, height); + pipe_sampler_view_reference( &stfb->blend_texture_view, NULL ); + stfb->blend_texture_view = create_tex_and_view(ctx->pipe, PIPE_FORMAT_B8G8R8A8_UNORM, + width, height); } void st_set_framebuffer_surface(struct st_framebuffer *stfb, diff --git a/src/gallium/winsys/drm/radeon/core/radeon_drm_buffer.c b/src/gallium/winsys/drm/radeon/core/radeon_drm_buffer.c index 9b763ec07e..bdaf95d793 100644 --- a/src/gallium/winsys/drm/radeon/core/radeon_drm_buffer.c +++ b/src/gallium/winsys/drm/radeon/core/radeon_drm_buffer.c @@ -22,7 +22,6 @@ struct radeon_drm_buffer { boolean flinked; uint32_t flink; - boolean mapped; struct radeon_drm_buffer *next, *prev; }; @@ -55,10 +54,10 @@ radeon_drm_buffer_destroy(struct pb_buffer *_buf) { struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf); - if (buf->mapped) { + if (buf->bo->ptr != NULL) { remove_from_list(buf); radeon_bo_unmap(buf->bo); - buf->mapped = false; + buf->bo->ptr = NULL; } radeon_bo_unref(buf->bo); @@ -72,7 +71,7 @@ radeon_drm_buffer_map(struct pb_buffer *_buf, struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf); int write; - if (buf->mapped) + if (buf->bo->ptr != NULL) return buf->bo->ptr; if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) { @@ -94,7 +93,6 @@ radeon_drm_buffer_map(struct pb_buffer *_buf, if (radeon_bo_map(buf->bo, write)) { return NULL; } - buf->mapped = true; insert_at_tail(&buf->mgr->buffer_map_list, buf); return buf->bo->ptr; } @@ -288,7 +286,7 @@ boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf, retval = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink); if (retval) { - return false; + return FALSE; } buf->flinked = TRUE; @@ -305,13 +303,21 @@ boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf, void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf, boolean microtiled, boolean macrotiled, uint32_t pitch) { struct radeon_drm_buffer *buf = get_drm_buffer(_buf); - uint32_t flags = 0; - + uint32_t flags = 0, old_flags, old_pitch; if (microtiled) flags |= RADEON_BO_FLAGS_MICRO_TILE; if (macrotiled) flags |= RADEON_BO_FLAGS_MACRO_TILE; + radeon_bo_get_tiling(buf->bo, &old_flags, &old_pitch); + + if (flags != old_flags || pitch != old_pitch) { + /* Tiling determines how DRM treats the buffer data. + * We must flush CS when changing it if the buffer is referenced. */ + if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) { + buf->mgr->rws->flush_cb(buf->mgr->rws->flush_data); + } + } radeon_bo_set_tiling(buf->bo, flags, pitch); } @@ -322,7 +328,7 @@ boolean radeon_drm_bufmgr_add_buffer(struct pb_buffer *_buf, struct radeon_drm_buffer *buf = get_drm_buffer(_buf); radeon_cs_space_add_persistent_bo(buf->mgr->rws->cs, buf->bo, rd, wd); - return true; + return TRUE; } void radeon_drm_bufmgr_write_reloc(struct pb_buffer *_buf, @@ -356,12 +362,10 @@ void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr) struct radeon_drm_buffer *rpb, *t_rpb; foreach_s(rpb, t_rpb, &mgr->buffer_map_list) { - rpb->mapped = 0; radeon_bo_unmap(rpb->bo); + rpb->bo->ptr = NULL; remove_from_list(rpb); } make_empty_list(&mgr->buffer_map_list); - - } |