Home | History | Annotate | Download | only in state_tracker
      1 /**************************************************************************
      2  *
      3  * Copyright (C) 2015 Advanced Micro Devices, Inc.
      4  * Copyright 2007 VMware, Inc.
      5  * All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the
      9  * "Software"), to deal in the Software without restriction, including
     10  * without limitation the rights to use, copy, modify, merge, publish,
     11  * distribute, sub license, and/or sell copies of the Software, and to
     12  * permit persons to whom the Software is furnished to do so, subject to
     13  * the following conditions:
     14  *
     15  * The above copyright notice and this permission notice (including the
     16  * next paragraph) shall be included in all copies or substantial portions
     17  * of the Software.
     18  *
     19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
     22  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
     23  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     24  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     25  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     26  *
     27  **************************************************************************/
     28 
     29 #include "st_cb_drawpixels.h"
     30 #include "tgsi/tgsi_transform.h"
     31 #include "tgsi/tgsi_scan.h"
     32 
     33 struct tgsi_drawpix_transform {
     34    struct tgsi_transform_context base;
     35    struct tgsi_shader_info info;
     36    bool use_texcoord;
     37    bool scale_and_bias;
     38    bool pixel_maps;
     39    bool first_instruction_emitted;
     40    unsigned scale_const;
     41    unsigned bias_const;
     42    unsigned color_temp;
     43    unsigned drawpix_sampler;
     44    unsigned pixelmap_sampler;
     45    unsigned texcoord_const;
     46    unsigned tex_target;
     47 };
     48 
     49 static inline struct tgsi_drawpix_transform *
     50 tgsi_drawpix_transform(struct tgsi_transform_context *tctx)
     51 {
     52    return (struct tgsi_drawpix_transform *)tctx;
     53 }
     54 
     55 static void
     56 set_src(struct tgsi_full_instruction *inst, unsigned i, unsigned file, unsigned index,
     57         unsigned x, unsigned y, unsigned z, unsigned w)
     58 {
     59    inst->Src[i].Register.File  = file;
     60    inst->Src[i].Register.Index = index;
     61    inst->Src[i].Register.SwizzleX = x;
     62    inst->Src[i].Register.SwizzleY = y;
     63    inst->Src[i].Register.SwizzleZ = z;
     64    inst->Src[i].Register.SwizzleW = w;
     65 }
     66 
     67 #define SET_SRC(inst, i, file, index, x, y, z, w) \
     68    set_src(inst, i, file, index, TGSI_SWIZZLE_##x, TGSI_SWIZZLE_##y, \
     69            TGSI_SWIZZLE_##z, TGSI_SWIZZLE_##w)
     70 
     71 static void
     72 transform_instr(struct tgsi_transform_context *tctx,
     73 		struct tgsi_full_instruction *current_inst)
     74 {
     75    struct tgsi_drawpix_transform *ctx = tgsi_drawpix_transform(tctx);
     76    const unsigned tgsi_tex_target = ctx->tex_target == PIPE_TEXTURE_2D
     77       ? TGSI_TEXTURE_2D : TGSI_TEXTURE_RECT;
     78    unsigned i, sem_texcoord = ctx->use_texcoord ? TGSI_SEMANTIC_TEXCOORD :
     79                                                   TGSI_SEMANTIC_GENERIC;
     80    int texcoord_index = -1;
     81 
     82    if (ctx->first_instruction_emitted)
     83       goto transform_inst;
     84 
     85    ctx->first_instruction_emitted = true;
     86 
     87    /* Add scale and bias constants. */
     88    if (ctx->scale_and_bias) {
     89       if (ctx->info.const_file_max[0] < (int)ctx->scale_const) {
     90          tgsi_transform_const_decl(tctx, ctx->scale_const, ctx->scale_const);
     91       }
     92 
     93       if (ctx->info.const_file_max[0] < (int)ctx->bias_const) {
     94          tgsi_transform_const_decl(tctx, ctx->bias_const, ctx->bias_const);
     95       }
     96    }
     97 
     98    if (ctx->info.const_file_max[0] < (int)ctx->texcoord_const) {
     99       tgsi_transform_const_decl(tctx, ctx->texcoord_const, ctx->texcoord_const);
    100    }
    101 
    102    /* Add a new temp. */
    103    ctx->color_temp = ctx->info.file_max[TGSI_FILE_TEMPORARY] + 1;
    104    tgsi_transform_temp_decl(tctx, ctx->color_temp);
    105 
    106    /* Add TEXCOORD[texcoord_slot] if it's missing. */
    107    for (i = 0; i < ctx->info.num_inputs; i++) {
    108       if (ctx->info.input_semantic_name[i] == sem_texcoord &&
    109           ctx->info.input_semantic_index[i] == 0) {
    110          texcoord_index = i;
    111          break;
    112       }
    113    }
    114 
    115    if (texcoord_index == -1) {
    116       texcoord_index = ctx->info.num_inputs;
    117       tgsi_transform_input_decl(tctx, texcoord_index, sem_texcoord, 0,
    118                                 TGSI_INTERPOLATE_PERSPECTIVE);
    119    }
    120 
    121    /* Declare the drawpix sampler if it's missing. */
    122    if (!(ctx->info.samplers_declared & (1 << ctx->drawpix_sampler))) {
    123       tgsi_transform_sampler_decl(tctx, ctx->drawpix_sampler);
    124 
    125       /* emit sampler view declaration */
    126       tgsi_transform_sampler_view_decl(tctx, ctx->drawpix_sampler,
    127                                        tgsi_tex_target, TGSI_RETURN_TYPE_FLOAT);
    128    }
    129 
    130    /* Declare the pixel map sampler if it's missing. */
    131    if (ctx->pixel_maps &&
    132        !(ctx->info.samplers_declared & (1 << ctx->pixelmap_sampler))) {
    133       tgsi_transform_sampler_decl(tctx, ctx->pixelmap_sampler);
    134 
    135       /* emit sampler view declaration */
    136       tgsi_transform_sampler_view_decl(tctx, ctx->pixelmap_sampler,
    137                                        TGSI_TEXTURE_2D, TGSI_RETURN_TYPE_FLOAT);
    138    }
    139 
    140    /* Get initial pixel color from the texture.
    141     * TEX temp, fragment.texcoord[0], texture[0], 2D;
    142     */
    143    tgsi_transform_tex_inst(tctx, TGSI_FILE_TEMPORARY, ctx->color_temp,
    144                            TGSI_FILE_INPUT, texcoord_index,
    145                            tgsi_tex_target, ctx->drawpix_sampler);
    146 
    147    /* Apply the scale and bias. */
    148    if (ctx->scale_and_bias) {
    149       /* MAD temp, temp, scale, bias; */
    150       tgsi_transform_op3_inst(tctx, TGSI_OPCODE_MAD,
    151                               TGSI_FILE_TEMPORARY, ctx->color_temp,
    152                               TGSI_WRITEMASK_XYZW,
    153                               TGSI_FILE_TEMPORARY, ctx->color_temp,
    154                               TGSI_FILE_CONSTANT, ctx->scale_const,
    155                               TGSI_FILE_CONSTANT, ctx->bias_const);
    156    }
    157 
    158    if (ctx->pixel_maps) {
    159       /* do four pixel map look-ups with two TEX instructions: */
    160       struct tgsi_full_instruction inst;
    161 
    162       /* TEX temp.xy, temp.xyyy, texture[1], 2D; */
    163       inst = tgsi_default_full_instruction();
    164       inst.Instruction.Opcode = TGSI_OPCODE_TEX;
    165       inst.Instruction.Texture = 1;
    166       inst.Texture.Texture = TGSI_TEXTURE_2D;
    167 
    168       inst.Instruction.NumDstRegs = 1;
    169       inst.Dst[0].Register.File  = TGSI_FILE_TEMPORARY;
    170       inst.Dst[0].Register.Index = ctx->color_temp;
    171       inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XY;
    172 
    173       inst.Instruction.NumSrcRegs = 2;
    174       SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->color_temp, X, Y, Y, Y);
    175       inst.Src[1].Register.File  = TGSI_FILE_SAMPLER;
    176       inst.Src[1].Register.Index = ctx->pixelmap_sampler;
    177 
    178       tctx->emit_instruction(tctx, &inst);
    179 
    180       /* TEX temp.zw, temp.zwww, texture[1], 2D; */
    181       inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_ZW;
    182       SET_SRC(&inst, 0, TGSI_FILE_TEMPORARY, ctx->color_temp, Z, W, W, W);
    183       tctx->emit_instruction(tctx, &inst);
    184    }
    185 
    186    /* Now, "color_temp" should be used in place of IN:COLOR0,
    187     * and CONST[texcoord_slot] should be used in place of IN:TEXCOORD0.
    188     */
    189 
    190 transform_inst:
    191 
    192    for (i = 0; i < current_inst->Instruction.NumSrcRegs; i++) {
    193       struct tgsi_full_src_register *src = &current_inst->Src[i];
    194       unsigned reg = src->Register.Index;
    195 
    196       if (src->Register.File != TGSI_FILE_INPUT || src->Register.Indirect)
    197          continue;
    198 
    199       if (ctx->info.input_semantic_name[reg] == TGSI_SEMANTIC_COLOR &&
    200           ctx->info.input_semantic_index[reg] == 0) {
    201          src->Register.File = TGSI_FILE_TEMPORARY;
    202          src->Register.Index = ctx->color_temp;
    203       } else if (ctx->info.input_semantic_name[reg] == sem_texcoord &&
    204                  ctx->info.input_semantic_index[reg] == 0) {
    205          src->Register.File = TGSI_FILE_CONSTANT;
    206          src->Register.Index = ctx->texcoord_const;
    207       }
    208    }
    209 
    210    tctx->emit_instruction(tctx, current_inst);
    211 }
    212 
    213 const struct tgsi_token *
    214 st_get_drawpix_shader(const struct tgsi_token *tokens, bool use_texcoord,
    215                       bool scale_and_bias, unsigned scale_const,
    216                       unsigned bias_const, bool pixel_maps,
    217                       unsigned drawpix_sampler, unsigned pixelmap_sampler,
    218                       unsigned texcoord_const, unsigned tex_target)
    219 {
    220    struct tgsi_drawpix_transform ctx;
    221    struct tgsi_token *newtoks;
    222    int newlen;
    223 
    224    assert(tex_target == PIPE_TEXTURE_2D ||
    225           tex_target == PIPE_TEXTURE_RECT);
    226 
    227    memset(&ctx, 0, sizeof(ctx));
    228    ctx.base.transform_instruction = transform_instr;
    229    ctx.use_texcoord = use_texcoord;
    230    ctx.scale_and_bias = scale_and_bias;
    231    ctx.scale_const = scale_const;
    232    ctx.bias_const = bias_const;
    233    ctx.pixel_maps = pixel_maps;
    234    ctx.drawpix_sampler = drawpix_sampler;
    235    ctx.pixelmap_sampler = pixelmap_sampler;
    236    ctx.texcoord_const = texcoord_const;
    237    ctx.tex_target = tex_target;
    238    tgsi_scan_shader(tokens, &ctx.info);
    239 
    240    newlen = tgsi_num_tokens(tokens) + 60;
    241    newtoks = tgsi_alloc_tokens(newlen);
    242    if (!newtoks)
    243       return NULL;
    244 
    245    tgsi_transform_shader(tokens, newtoks, newlen, &ctx.base);
    246    return newtoks;
    247 }
    248