Path: blob/21.2-virgl/src/gallium/frontends/xa/xa_tgsi.c
4561 views
/**********************************************************1* Copyright 2009-2011 VMware, Inc. All rights reserved.2*3* Permission is hereby granted, free of charge, to any person4* obtaining a copy of this software and associated documentation5* files (the "Software"), to deal in the Software without6* restriction, including without limitation the rights to use, copy,7* modify, merge, publish, distribute, sublicense, and/or sell copies8* of the Software, and to permit persons to whom the Software is9* furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice shall be12* included in all copies or substantial portions of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,15* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF16* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND17* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS18* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN19* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN20* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*23*********************************************************24* Authors:25* Zack Rusin <zackr-at-vmware-dot-com>26*/27#include "xa_priv.h"2829#include "pipe/p_format.h"30#include "pipe/p_context.h"31#include "pipe/p_state.h"32#include "pipe/p_shader_tokens.h"3334#include "util/u_memory.h"3536#include "tgsi/tgsi_ureg.h"3738#include "cso_cache/cso_context.h"39#include "cso_cache/cso_hash.h"4041/* Vertex shader:42* IN[0] = vertex pos43* IN[1] = src tex coord | solid fill color44* IN[2] = mask tex coord45* IN[3] = dst tex coord46* CONST[0] = (2/dst_width, 2/dst_height, 1, 1)47* CONST[1] = (-1, -1, 0, 0)48*49* OUT[0] = vertex pos50* OUT[1] = src tex coord51* OUT[2] = mask tex coord52* OUT[3] = dst tex coord53*/5455/* Fragment shader. Samplers are allocated when needed.56* SAMP[0] = sampler for first texture (src or mask if src is solid)57* SAMP[1] = sampler for second texture (mask or none)58* IN[0] = first texture coordinates if present59* IN[1] = second texture coordinates if present60* CONST[0] = Solid color (src if src solid or mask if mask solid61* or src in mask if both solid).62*63* OUT[0] = color64*/6566static void67print_fs_traits(int fs_traits)68{69const char *strings[] = {70"FS_COMPOSITE", /* = 1 << 0, */71"FS_MASK", /* = 1 << 1, */72"FS_SRC_SRC", /* = 1 << 2, */73"FS_MASK_SRC", /* = 1 << 3, */74"FS_YUV", /* = 1 << 4, */75"FS_SRC_REPEAT_NONE", /* = 1 << 5, */76"FS_MASK_REPEAT_NONE", /* = 1 << 6, */77"FS_SRC_SWIZZLE_RGB", /* = 1 << 7, */78"FS_MASK_SWIZZLE_RGB", /* = 1 << 8, */79"FS_SRC_SET_ALPHA", /* = 1 << 9, */80"FS_MASK_SET_ALPHA", /* = 1 << 10, */81"FS_SRC_LUMINANCE", /* = 1 << 11, */82"FS_MASK_LUMINANCE", /* = 1 << 12, */83"FS_DST_LUMINANCE", /* = 1 << 13, */84"FS_CA", /* = 1 << 14, */85};86int i, k;8788debug_printf("%s: ", __func__);8990for (i = 0, k = 1; k < (1 << 16); i++, k <<= 1) {91if (fs_traits & k)92debug_printf("%s, ", strings[i]);93}9495debug_printf("\n");96}9798struct xa_shaders {99struct xa_context *r;100101struct cso_hash vs_hash;102struct cso_hash fs_hash;103};104105static inline void106src_in_mask(struct ureg_program *ureg,107struct ureg_dst dst,108struct ureg_src src,109struct ureg_src mask,110unsigned mask_luminance, boolean component_alpha)111{112if (mask_luminance)113if (component_alpha) {114ureg_MOV(ureg, dst, src);115ureg_MUL(ureg, ureg_writemask(dst, TGSI_WRITEMASK_W),116src, ureg_scalar(mask, TGSI_SWIZZLE_X));117} else {118ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_X));119}120else if (!component_alpha)121ureg_MUL(ureg, dst, src, ureg_scalar(mask, TGSI_SWIZZLE_W));122else123ureg_MUL(ureg, dst, src, mask);124}125126static struct ureg_src127vs_normalize_coords(struct ureg_program *ureg,128struct ureg_src coords,129struct ureg_src const0, struct ureg_src const1)130{131struct ureg_dst tmp = ureg_DECL_temporary(ureg);132struct ureg_src ret;133134ureg_MAD(ureg, tmp, coords, const0, const1);135ret = ureg_src(tmp);136ureg_release_temporary(ureg, tmp);137return ret;138}139140static void *141create_vs(struct pipe_context *pipe, unsigned vs_traits)142{143struct ureg_program *ureg;144struct ureg_src src;145struct ureg_dst dst;146struct ureg_src const0, const1;147boolean is_composite = (vs_traits & VS_COMPOSITE) != 0;148boolean has_mask = (vs_traits & VS_MASK) != 0;149boolean is_yuv = (vs_traits & VS_YUV) != 0;150boolean is_src_src = (vs_traits & VS_SRC_SRC) != 0;151boolean is_mask_src = (vs_traits & VS_MASK_SRC) != 0;152unsigned input_slot = 0;153154ureg = ureg_create(PIPE_SHADER_VERTEX);155if (ureg == NULL)156return 0;157158const0 = ureg_DECL_constant(ureg, 0);159const1 = ureg_DECL_constant(ureg, 1);160161/* it has to be either a fill or a composite op */162src = ureg_DECL_vs_input(ureg, input_slot++);163dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);164src = vs_normalize_coords(ureg, src, const0, const1);165ureg_MOV(ureg, dst, src);166167if (is_yuv) {168src = ureg_DECL_vs_input(ureg, input_slot++);169dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);170ureg_MOV(ureg, dst, src);171}172173if (is_composite) {174if (!is_src_src || (has_mask && !is_mask_src)) {175src = ureg_DECL_vs_input(ureg, input_slot++);176dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 0);177ureg_MOV(ureg, dst, src);178}179180if (!is_src_src && (has_mask && !is_mask_src)) {181src = ureg_DECL_vs_input(ureg, input_slot++);182dst = ureg_DECL_output(ureg, TGSI_SEMANTIC_GENERIC, 1);183ureg_MOV(ureg, dst, src);184}185}186187ureg_END(ureg);188189return ureg_create_shader_and_destroy(ureg, pipe);190}191192static void *193create_yuv_shader(struct pipe_context *pipe, struct ureg_program *ureg)194{195struct ureg_src y_sampler, u_sampler, v_sampler;196struct ureg_src pos;197struct ureg_src matrow0, matrow1, matrow2, matrow3;198struct ureg_dst y, u, v, rgb;199struct ureg_dst out = ureg_DECL_output(ureg,200TGSI_SEMANTIC_COLOR,2010);202203pos = ureg_DECL_fs_input(ureg,204TGSI_SEMANTIC_GENERIC, 0,205TGSI_INTERPOLATE_PERSPECTIVE);206207rgb = ureg_DECL_temporary(ureg);208y = ureg_DECL_temporary(ureg);209u = ureg_DECL_temporary(ureg);210v = ureg_DECL_temporary(ureg);211212y_sampler = ureg_DECL_sampler(ureg, 0);213u_sampler = ureg_DECL_sampler(ureg, 1);214v_sampler = ureg_DECL_sampler(ureg, 2);215216ureg_DECL_sampler_view(ureg, 0, TGSI_TEXTURE_2D,217TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,218TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);219ureg_DECL_sampler_view(ureg, 1, TGSI_TEXTURE_2D,220TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,221TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);222ureg_DECL_sampler_view(ureg, 2, TGSI_TEXTURE_2D,223TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,224TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);225226matrow0 = ureg_DECL_constant(ureg, 0);227matrow1 = ureg_DECL_constant(ureg, 1);228matrow2 = ureg_DECL_constant(ureg, 2);229matrow3 = ureg_DECL_constant(ureg, 3);230231ureg_TEX(ureg, y, TGSI_TEXTURE_2D, pos, y_sampler);232ureg_TEX(ureg, u, TGSI_TEXTURE_2D, pos, u_sampler);233ureg_TEX(ureg, v, TGSI_TEXTURE_2D, pos, v_sampler);234235ureg_MOV(ureg, rgb, matrow3);236ureg_MAD(ureg, rgb,237ureg_scalar(ureg_src(y), TGSI_SWIZZLE_X), matrow0, ureg_src(rgb));238ureg_MAD(ureg, rgb,239ureg_scalar(ureg_src(u), TGSI_SWIZZLE_X), matrow1, ureg_src(rgb));240ureg_MAD(ureg, rgb,241ureg_scalar(ureg_src(v), TGSI_SWIZZLE_X), matrow2, ureg_src(rgb));242243ureg_MOV(ureg, out, ureg_src(rgb));244245ureg_release_temporary(ureg, rgb);246ureg_release_temporary(ureg, y);247ureg_release_temporary(ureg, u);248ureg_release_temporary(ureg, v);249250ureg_END(ureg);251252return ureg_create_shader_and_destroy(ureg, pipe);253}254255static inline void256xrender_tex(struct ureg_program *ureg,257struct ureg_dst dst,258struct ureg_src coords,259struct ureg_src sampler,260const struct ureg_src *imm0,261boolean repeat_none, boolean swizzle, boolean set_alpha)262{263if (repeat_none) {264struct ureg_dst tmp0 = ureg_DECL_temporary(ureg);265struct ureg_dst tmp1 = ureg_DECL_temporary(ureg);266267ureg_SGT(ureg, tmp1, ureg_swizzle(coords,268TGSI_SWIZZLE_X,269TGSI_SWIZZLE_Y,270TGSI_SWIZZLE_X,271TGSI_SWIZZLE_Y), ureg_scalar(*imm0,272TGSI_SWIZZLE_X));273ureg_SLT(ureg, tmp0,274ureg_swizzle(coords, TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y,275TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y), ureg_scalar(*imm0,276TGSI_SWIZZLE_W));277ureg_MIN(ureg, tmp0, ureg_src(tmp0), ureg_src(tmp1));278ureg_MIN(ureg, tmp0, ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_X),279ureg_scalar(ureg_src(tmp0), TGSI_SWIZZLE_Y));280ureg_TEX(ureg, tmp1, TGSI_TEXTURE_2D, coords, sampler);281if (swizzle)282ureg_MOV(ureg, tmp1, ureg_swizzle(ureg_src(tmp1),283TGSI_SWIZZLE_Z,284TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X,285TGSI_SWIZZLE_W));286if (set_alpha)287ureg_MOV(ureg,288ureg_writemask(tmp1, TGSI_WRITEMASK_W),289ureg_scalar(*imm0, TGSI_SWIZZLE_W));290ureg_MUL(ureg, dst, ureg_src(tmp1), ureg_src(tmp0));291ureg_release_temporary(ureg, tmp0);292ureg_release_temporary(ureg, tmp1);293} else {294if (swizzle) {295struct ureg_dst tmp = ureg_DECL_temporary(ureg);296297ureg_TEX(ureg, tmp, TGSI_TEXTURE_2D, coords, sampler);298ureg_MOV(ureg, dst, ureg_swizzle(ureg_src(tmp),299TGSI_SWIZZLE_Z,300TGSI_SWIZZLE_Y, TGSI_SWIZZLE_X,301TGSI_SWIZZLE_W));302ureg_release_temporary(ureg, tmp);303} else {304ureg_TEX(ureg, dst, TGSI_TEXTURE_2D, coords, sampler);305}306if (set_alpha)307ureg_MOV(ureg,308ureg_writemask(dst, TGSI_WRITEMASK_W),309ureg_scalar(*imm0, TGSI_SWIZZLE_W));310}311}312313static void314read_input(struct ureg_program *ureg,315struct ureg_dst dst,316const struct ureg_src *imm0,317boolean repeat_none, boolean swizzle, boolean set_alpha,318boolean is_src, unsigned *cur_constant, unsigned *cur_sampler)319{320struct ureg_src input, sampler;321322if (is_src) {323input = ureg_DECL_constant(ureg, (*cur_constant)++);324ureg_MOV(ureg, dst, input);325} else {326sampler = ureg_DECL_sampler(ureg, *cur_sampler);327ureg_DECL_sampler_view(ureg, *cur_sampler, TGSI_TEXTURE_2D,328TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT,329TGSI_RETURN_TYPE_FLOAT, TGSI_RETURN_TYPE_FLOAT);330input = ureg_DECL_fs_input(ureg,331TGSI_SEMANTIC_GENERIC, (*cur_sampler)++,332TGSI_INTERPOLATE_PERSPECTIVE);333xrender_tex(ureg, dst, input, sampler, imm0,334repeat_none, swizzle, set_alpha);335}336}337338static void *339create_fs(struct pipe_context *pipe, unsigned fs_traits)340{341struct ureg_program *ureg;342struct ureg_dst src, mask;343struct ureg_dst out;344struct ureg_src imm0 = { 0 };345unsigned has_mask = (fs_traits & FS_MASK) != 0;346unsigned is_yuv = (fs_traits & FS_YUV) != 0;347unsigned src_repeat_none = (fs_traits & FS_SRC_REPEAT_NONE) != 0;348unsigned mask_repeat_none = (fs_traits & FS_MASK_REPEAT_NONE) != 0;349unsigned src_swizzle = (fs_traits & FS_SRC_SWIZZLE_RGB) != 0;350unsigned mask_swizzle = (fs_traits & FS_MASK_SWIZZLE_RGB) != 0;351unsigned src_set_alpha = (fs_traits & FS_SRC_SET_ALPHA) != 0;352unsigned mask_set_alpha = (fs_traits & FS_MASK_SET_ALPHA) != 0;353unsigned src_luminance = (fs_traits & FS_SRC_LUMINANCE) != 0;354unsigned mask_luminance = (fs_traits & FS_MASK_LUMINANCE) != 0;355unsigned dst_luminance = (fs_traits & FS_DST_LUMINANCE) != 0;356unsigned is_src_src = (fs_traits & FS_SRC_SRC) != 0;357unsigned is_mask_src = (fs_traits & FS_MASK_SRC) != 0;358boolean component_alpha = (fs_traits & FS_CA) != 0;359unsigned cur_sampler = 0;360unsigned cur_constant = 0;361362#if 0363print_fs_traits(fs_traits);364#else365(void)print_fs_traits;366#endif367368ureg = ureg_create(PIPE_SHADER_FRAGMENT);369if (ureg == NULL)370return 0;371372if (is_yuv)373return create_yuv_shader(pipe, ureg);374375out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);376377if (src_repeat_none || mask_repeat_none ||378src_set_alpha || mask_set_alpha || src_luminance) {379imm0 = ureg_imm4f(ureg, 0, 0, 0, 1);380}381382src = (has_mask || src_luminance || dst_luminance) ?383ureg_DECL_temporary(ureg) : out;384385read_input(ureg, src, &imm0, src_repeat_none, src_swizzle,386src_set_alpha, is_src_src, &cur_constant, &cur_sampler);387388if (src_luminance) {389ureg_MOV(ureg, src, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_X));390ureg_MOV(ureg, ureg_writemask(src, TGSI_WRITEMASK_XYZ),391ureg_scalar(imm0, TGSI_SWIZZLE_X));392if (!has_mask && !dst_luminance)393ureg_MOV(ureg, out, ureg_src(src));394}395396if (has_mask) {397mask = ureg_DECL_temporary(ureg);398read_input(ureg, mask, &imm0, mask_repeat_none,399mask_swizzle, mask_set_alpha, is_mask_src, &cur_constant,400&cur_sampler);401402src_in_mask(ureg, (dst_luminance) ? src : out, ureg_src(src),403ureg_src(mask), mask_luminance, component_alpha);404405ureg_release_temporary(ureg, mask);406}407408if (dst_luminance) {409/*410* Make sure the alpha channel goes into the output L8 surface.411*/412ureg_MOV(ureg, out, ureg_scalar(ureg_src(src), TGSI_SWIZZLE_W));413}414415ureg_END(ureg);416417return ureg_create_shader_and_destroy(ureg, pipe);418}419420struct xa_shaders *421xa_shaders_create(struct xa_context *r)422{423struct xa_shaders *sc = CALLOC_STRUCT(xa_shaders);424425sc->r = r;426cso_hash_init(&sc->vs_hash);427cso_hash_init(&sc->fs_hash);428429return sc;430}431432static void433cache_destroy(struct pipe_context *pipe,434struct cso_hash *hash, unsigned processor)435{436struct cso_hash_iter iter = cso_hash_first_node(hash);437438while (!cso_hash_iter_is_null(iter)) {439void *shader = (void *)cso_hash_iter_data(iter);440441if (processor == PIPE_SHADER_FRAGMENT) {442pipe->delete_fs_state(pipe, shader);443} else if (processor == PIPE_SHADER_VERTEX) {444pipe->delete_vs_state(pipe, shader);445}446iter = cso_hash_erase(hash, iter);447}448cso_hash_deinit(hash);449}450451void452xa_shaders_destroy(struct xa_shaders *sc)453{454cache_destroy(sc->r->pipe, &sc->vs_hash, PIPE_SHADER_VERTEX);455cache_destroy(sc->r->pipe, &sc->fs_hash, PIPE_SHADER_FRAGMENT);456457FREE(sc);458}459460static inline void *461shader_from_cache(struct pipe_context *pipe,462unsigned type, struct cso_hash *hash, unsigned key)463{464void *shader = 0;465466struct cso_hash_iter iter = cso_hash_find(hash, key);467468if (cso_hash_iter_is_null(iter)) {469if (type == PIPE_SHADER_VERTEX)470shader = create_vs(pipe, key);471else472shader = create_fs(pipe, key);473cso_hash_insert(hash, key, shader);474} else475shader = (void *)cso_hash_iter_data(iter);476477return shader;478}479480struct xa_shader481xa_shaders_get(struct xa_shaders *sc, unsigned vs_traits, unsigned fs_traits)482{483struct xa_shader shader = { NULL, NULL };484void *vs, *fs;485486vs = shader_from_cache(sc->r->pipe, PIPE_SHADER_VERTEX,487&sc->vs_hash, vs_traits);488fs = shader_from_cache(sc->r->pipe, PIPE_SHADER_FRAGMENT,489&sc->fs_hash, fs_traits);490491debug_assert(vs && fs);492if (!vs || !fs)493return shader;494495shader.vs = vs;496shader.fs = fs;497498return shader;499}500501502