diff options
Diffstat (limited to 'src/gallium/state_trackers/xorg/xorg_exa_tgsi.c')
-rw-r--r-- | src/gallium/state_trackers/xorg/xorg_exa_tgsi.c | 298 |
1 files changed, 253 insertions, 45 deletions
diff --git a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c index bb5a42af37..bed17caab7 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c +++ b/src/gallium/state_trackers/xorg/xorg_exa_tgsi.c @@ -43,33 +43,67 @@ * OUT[0] = color */ +static void +print_fs_traits(int fs_traits) +{ + const char *strings[] = { + "FS_COMPOSITE", /* = 1 << 0, */ + "FS_MASK", /* = 1 << 1, */ + "FS_SOLID_FILL", /* = 1 << 2, */ + "FS_LINGRAD_FILL", /* = 1 << 3, */ + "FS_RADGRAD_FILL", /* = 1 << 4, */ + "FS_CA_FULL", /* = 1 << 5, */ /* src.rgba * mask.rgba */ + "FS_CA_SRCALPHA", /* = 1 << 6, */ /* src.aaaa * mask.rgba */ + "FS_YUV", /* = 1 << 7, */ + "FS_SRC_REPEAT_NONE", /* = 1 << 8, */ + "FS_MASK_REPEAT_NONE",/* = 1 << 9, */ + "FS_SRC_SWIZZLE_RGB", /* = 1 << 10, */ + "FS_MASK_SWIZZLE_RGB",/* = 1 << 11, */ + "FS_SRC_SET_ALPHA", /* = 1 << 12, */ + "FS_MASK_SET_ALPHA", /* = 1 << 13, */ + "FS_SRC_LUMINANCE", /* = 1 << 14, */ + "FS_MASK_LUMINANCE", /* = 1 << 15, */ + }; + int i, k; + debug_printf("%s: ", __func__); + + for (i = 0, k = 1; k < (1 << 16); i++, k <<= 1) { + if (fs_traits & k) + debug_printf("%s, ", strings[i]); + } + + debug_printf("\n"); +} + struct xorg_shaders { - struct exa_context *exa; + struct xorg_renderer *r; struct cso_hash *vs_hash; struct cso_hash *fs_hash; }; -static const char over_op[] = - "SUB TEMP[3], CONST[0].wwww, TEMP[1].wwww\n" - "MAD TEMP[3], TEMP[0], TEMP[3], TEMP[0]\n"; - - -static INLINE void -create_preamble(struct ureg_program *ureg) -{ -} - - static INLINE void src_in_mask(struct ureg_program *ureg, struct ureg_dst dst, struct ureg_src src, - struct ureg_src mask) + struct ureg_src mask, + unsigned component_alpha, + unsigned mask_luminance) { - /* MUL dst, src, mask.wwww */ - ureg_MUL(ureg, dst, src, - ureg_scalar(mask, TGSI_SWIZZLE_W)); + if (component_alpha == FS_CA_FULL) { + ureg_MUL(ureg, dst, src, mask); + } else if (component_alpha == FS_CA_SRCALPHA) { + ureg_MUL(ureg, dst, + ureg_scalar(src, TGSI_SWIZZLE_W), mask); + } + else { + if (mask_luminance) + ureg_MUL(ureg, dst, src, + ureg_scalar(mask, TGSI_SWIZZLE_X)); + else + ureg_MUL(ureg, dst, src, + ureg_scalar(mask, TGSI_SWIZZLE_W)); + } } static struct ureg_src @@ -236,9 +270,10 @@ create_vs(struct pipe_context *pipe, struct ureg_src src; struct ureg_dst dst; struct ureg_src const0, const1; - boolean is_fill = vs_traits & VS_FILL; - boolean is_composite = vs_traits & VS_COMPOSITE; - boolean has_mask = vs_traits & VS_MASK; + boolean is_fill = (vs_traits & VS_FILL) != 0; + boolean is_composite = (vs_traits & VS_COMPOSITE) != 0; + boolean has_mask = (vs_traits & VS_MASK) != 0; + boolean is_yuv = (vs_traits & VS_YUV) != 0; unsigned input_slot = 0; ureg = ureg_create(TGSI_PROCESSOR_VERTEX); @@ -249,7 +284,7 @@ create_vs(struct pipe_context *pipe, const1 = ureg_DECL_constant(ureg, 1); /* it has to be either a fill or a composite op */ - debug_assert(is_fill ^ is_composite); + debug_assert((is_fill ^ is_composite) ^ is_yuv); src = ureg_DECL_vs_input(ureg, input_slot++); dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); @@ -257,6 +292,12 @@ create_vs(struct pipe_context *pipe, const0, const1); ureg_MOV(ureg, dst, src); + if (is_yuv) { + src = ureg_DECL_vs_input(ureg, input_slot++); + dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0); + ureg_MOV(ureg, dst, src); + } + if (is_composite) { src = ureg_DECL_vs_input(ureg, input_slot++); dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0); @@ -271,7 +312,7 @@ create_vs(struct pipe_context *pipe, if (has_mask) { src = ureg_DECL_vs_input(ureg, input_slot++); - dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 2); + dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1); ureg_MOV(ureg, dst, src); } @@ -281,6 +322,138 @@ create_vs(struct pipe_context *pipe, } static void * +create_yuv_shader(struct pipe_context *pipe, struct ureg_program *ureg) +{ + struct ureg_src y_sampler, u_sampler, v_sampler; + struct ureg_src pos; + struct ureg_src matrow0, matrow1, matrow2; + struct ureg_dst y, u, v, rgb; + struct ureg_dst out = ureg_DECL_output(ureg, + TGSI_SEMANTIC_COLOR, + 0); + + pos = ureg_DECL_fs_input(ureg, + TGSI_SEMANTIC_GENERIC, + 0, + TGSI_INTERPOLATE_PERSPECTIVE); + + rgb = ureg_DECL_temporary(ureg); + y = ureg_DECL_temporary(ureg); + u = ureg_DECL_temporary(ureg); + v = ureg_DECL_temporary(ureg); + + y_sampler = ureg_DECL_sampler(ureg, 0); + u_sampler = ureg_DECL_sampler(ureg, 1); + v_sampler = ureg_DECL_sampler(ureg, 2); + + matrow0 = ureg_DECL_constant(ureg, 0); + matrow1 = ureg_DECL_constant(ureg, 1); + matrow2 = ureg_DECL_constant(ureg, 2); + + ureg_TEX(ureg, y, + TGSI_TEXTURE_2D, pos, y_sampler); + ureg_TEX(ureg, u, + TGSI_TEXTURE_2D, pos, u_sampler); + ureg_TEX(ureg, v, + TGSI_TEXTURE_2D, pos, v_sampler); + + ureg_SUB(ureg, u, ureg_src(u), + ureg_scalar(matrow0, TGSI_SWIZZLE_W)); + ureg_SUB(ureg, v, ureg_src(v), + ureg_scalar(matrow0, TGSI_SWIZZLE_W)); + + ureg_MUL(ureg, rgb, + ureg_scalar(ureg_src(y), TGSI_SWIZZLE_X), + matrow0); + ureg_MAD(ureg, rgb, + ureg_scalar(ureg_src(u), TGSI_SWIZZLE_X), + matrow1, + ureg_src(rgb)); + ureg_MAD(ureg, rgb, + ureg_scalar(ureg_src(v), TGSI_SWIZZLE_X), + matrow2, + ureg_src(rgb)); + + /* rgb.a = 1; */ + ureg_MOV(ureg, ureg_writemask(rgb, TGSI_WRITEMASK_W), + ureg_scalar(matrow0, TGSI_SWIZZLE_X)); + + ureg_MOV(ureg, out, ureg_src(rgb)); + + ureg_release_temporary(ureg, rgb); + ureg_release_temporary(ureg, y); + ureg_release_temporary(ureg, u); + ureg_release_temporary(ureg, v); + + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, pipe); +} + + +static INLINE void +xrender_tex(struct ureg_program *ureg, + struct ureg_dst dst, + struct ureg_src coords, + struct ureg_src sampler, + struct ureg_src imm0, + boolean repeat_none, + boolean swizzle, + boolean set_alpha) +{ + if (repeat_none) { + struct ureg_dst tmp0 = ureg_DECL_temporary(ureg); + struct ureg_dst tmp1 = ureg_DECL_temporary(ureg); + ureg_SGT(ureg, tmp1, ureg_swizzle(coords, + TGSI_SWIZZLE_X, + TGSI_SWIZZLE_Y, + TGSI_SWIZZLE_X, + TGSI_SWIZZLE_Y), + ureg_scalar(imm0, TGSI_SWIZZLE_X)); + ureg_SLT(ureg, tmp0, ureg_swizzle(coords, + TGSI_SWIZZLE_X, + TGSI_SWIZZLE_Y, + TGSI_SWIZZLE_X, + TGSI_SWIZZLE_Y), + ureg_scalar(imm0, TGSI_SWIZZLE_W)); + ureg_MIN(ureg, tmp0, ureg_src(tmp0), ureg_src(tmp1)); + ureg_MIN(ureg, tmp0, ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_X), + ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_Y)); + ureg_TEX(ureg, tmp1, TGSI_TEXTURE_2D, coords, sampler); + if (swizzle) + ureg_MOV(ureg, tmp1, ureg_swizzle(ureg_src(tmp1), + TGSI_SWIZZLE_Z, + TGSI_SWIZZLE_Y, + TGSI_SWIZZLE_X, + TGSI_SWIZZLE_W)); + if (set_alpha) + ureg_MOV(ureg, + ureg_writemask(tmp1, TGSI_WRITEMASK_W), + ureg_scalar(imm0, TGSI_SWIZZLE_W)); + ureg_MUL(ureg, dst, ureg_src(tmp1), ureg_src(tmp0)); + ureg_release_temporary(ureg, tmp0); + ureg_release_temporary(ureg, tmp1); + } else { + if (swizzle) { + struct ureg_dst tmp = ureg_DECL_temporary(ureg); + ureg_TEX(ureg, tmp, TGSI_TEXTURE_2D, coords, sampler); + ureg_MOV(ureg, dst, ureg_swizzle(ureg_src(tmp), + TGSI_SWIZZLE_Z, + TGSI_SWIZZLE_Y, + TGSI_SWIZZLE_X, + TGSI_SWIZZLE_W)); + ureg_release_temporary(ureg, tmp); + } else { + ureg_TEX(ureg, dst, TGSI_TEXTURE_2D, coords, sampler); + } + if (set_alpha) + ureg_MOV(ureg, + ureg_writemask(dst, TGSI_WRITEMASK_W), + ureg_scalar(imm0, TGSI_SWIZZLE_W)); + } +} + +static void * create_fs(struct pipe_context *pipe, unsigned fs_traits) { @@ -289,32 +462,54 @@ create_fs(struct pipe_context *pipe, struct ureg_src /*dst_pos,*/ src_input, mask_pos; struct ureg_dst src, mask; struct ureg_dst out; - boolean has_mask = fs_traits & FS_MASK; - boolean is_fill = fs_traits & FS_FILL; - boolean is_composite = fs_traits & FS_COMPOSITE; - boolean is_solid = fs_traits & FS_SOLID_FILL; - boolean is_lingrad = fs_traits & FS_LINGRAD_FILL; - boolean is_radgrad = fs_traits & FS_RADGRAD_FILL; + struct ureg_src imm0 = { 0 }; + unsigned has_mask = (fs_traits & FS_MASK) != 0; + unsigned is_fill = (fs_traits & FS_FILL) != 0; + unsigned is_composite = (fs_traits & FS_COMPOSITE) != 0; + unsigned is_solid = (fs_traits & FS_SOLID_FILL) != 0; + unsigned is_lingrad = (fs_traits & FS_LINGRAD_FILL) != 0; + unsigned is_radgrad = (fs_traits & FS_RADGRAD_FILL) != 0; + unsigned comp_alpha_mask = fs_traits & FS_COMPONENT_ALPHA; + unsigned is_yuv = (fs_traits & FS_YUV) != 0; + unsigned src_repeat_none = (fs_traits & FS_SRC_REPEAT_NONE) != 0; + unsigned mask_repeat_none = (fs_traits & FS_MASK_REPEAT_NONE) != 0; + unsigned src_swizzle = (fs_traits & FS_SRC_SWIZZLE_RGB) != 0; + unsigned mask_swizzle = (fs_traits & FS_MASK_SWIZZLE_RGB) != 0; + unsigned src_set_alpha = (fs_traits & FS_SRC_SET_ALPHA) != 0; + unsigned mask_set_alpha = (fs_traits & FS_MASK_SET_ALPHA) != 0; + unsigned src_luminance = (fs_traits & FS_SRC_LUMINANCE) != 0; + unsigned mask_luminance = (fs_traits & FS_MASK_LUMINANCE) != 0; + +#if 0 + print_fs_traits(fs_traits); +#else + (void)print_fs_traits; +#endif ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); if (ureg == NULL) return 0; - /* it has to be either a fill or a composite op */ - debug_assert(is_fill ^ is_composite); + /* it has to be either a fill, a composite op or a yuv conversion */ + debug_assert((is_fill ^ is_composite) ^ is_yuv); + (void) is_yuv; out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); + if (src_repeat_none || mask_repeat_none || + src_set_alpha || mask_set_alpha || + src_luminance) { + imm0 = ureg_imm4f(ureg, 0, 0, 0, 1); + } if (is_composite) { src_sampler = ureg_DECL_sampler(ureg, 0); src_input = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0, TGSI_INTERPOLATE_PERSPECTIVE); - } else { - debug_assert(is_fill); + } else if (is_fill) { if (is_solid) src_input = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_COLOR, @@ -325,6 +520,9 @@ create_fs(struct pipe_context *pipe, TGSI_SEMANTIC_POSITION, 0, TGSI_INTERPOLATE_PERSPECTIVE); + } else { + debug_assert(is_yuv); + return create_yuv_shader(pipe, ureg); } if (has_mask) { @@ -343,16 +541,17 @@ create_fs(struct pipe_context *pipe, TGSI_INTERPOLATE_PERSPECTIVE); #endif + if (is_composite) { - if (has_mask) + if (has_mask || src_luminance) src = ureg_DECL_temporary(ureg); else src = out; - ureg_TEX(ureg, src, - TGSI_TEXTURE_2D, src_input, src_sampler); + xrender_tex(ureg, src, src_input, src_sampler, imm0, + src_repeat_none, src_swizzle, src_set_alpha); } else if (is_fill) { if (is_solid) { - if (has_mask) + if (has_mask || src_luminance) src = ureg_dst(src_input); else ureg_MOV(ureg, out, src_input); @@ -360,7 +559,7 @@ create_fs(struct pipe_context *pipe, struct ureg_src coords, const0124, matrow0, matrow1, matrow2; - if (has_mask) + if (has_mask || src_luminance) src = ureg_DECL_temporary(ureg); else src = out; @@ -385,13 +584,22 @@ create_fs(struct pipe_context *pipe, } else debug_assert(!"Unknown fill type!"); } + if (src_luminance) { + ureg_MOV(ureg, src, + ureg_scalar(ureg_src(src), TGSI_SWIZZLE_X)); + ureg_MOV(ureg, ureg_writemask(src, TGSI_WRITEMASK_XYZ), + ureg_scalar(imm0, TGSI_SWIZZLE_X)); + if (!has_mask) + ureg_MOV(ureg, out, ureg_src(src)); + } if (has_mask) { mask = ureg_DECL_temporary(ureg); - ureg_TEX(ureg, mask, - TGSI_TEXTURE_2D, mask_pos, mask_sampler); + xrender_tex(ureg, mask, mask_pos, mask_sampler, imm0, + mask_repeat_none, mask_swizzle, mask_set_alpha); /* src IN mask */ - src_in_mask(ureg, out, ureg_src(src), ureg_src(mask)); + src_in_mask(ureg, out, ureg_src(src), ureg_src(mask), + comp_alpha_mask, mask_luminance); ureg_release_temporary(ureg, mask); } @@ -400,11 +608,11 @@ create_fs(struct pipe_context *pipe, return ureg_create_shader_and_destroy(ureg, pipe); } -struct xorg_shaders * xorg_shaders_create(struct exa_context *exa) +struct xorg_shaders * xorg_shaders_create(struct xorg_renderer *r) { struct xorg_shaders *sc = CALLOC_STRUCT(xorg_shaders); - sc->exa = exa; + sc->r = r; sc->vs_hash = cso_hash_create(); sc->fs_hash = cso_hash_create(); @@ -431,9 +639,9 @@ cache_destroy(struct cso_context *cso, void xorg_shaders_destroy(struct xorg_shaders *sc) { - cache_destroy(sc->exa->cso, sc->vs_hash, + cache_destroy(sc->r->cso, sc->vs_hash, PIPE_SHADER_VERTEX); - cache_destroy(sc->exa->cso, sc->fs_hash, + cache_destroy(sc->r->cso, sc->fs_hash, PIPE_SHADER_FRAGMENT); free(sc); @@ -468,9 +676,9 @@ struct xorg_shader xorg_shaders_get(struct xorg_shaders *sc, struct xorg_shader shader = { NULL, NULL }; void *vs, *fs; - vs = shader_from_cache(sc->exa->pipe, PIPE_SHADER_VERTEX, + vs = shader_from_cache(sc->r->pipe, PIPE_SHADER_VERTEX, sc->vs_hash, vs_traits); - fs = shader_from_cache(sc->exa->pipe, PIPE_SHADER_FRAGMENT, + fs = shader_from_cache(sc->r->pipe, PIPE_SHADER_FRAGMENT, sc->fs_hash, fs_traits); debug_assert(vs && fs); |