Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2008 VMware, Inc.
  4.  * All Rights Reserved.
  5.  * Copyright 2009 Marek Olšák <maraeo@gmail.com>
  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. /**
  30.  * @file
  31.  * Simple vertex/fragment shader generators.
  32.  *  
  33.  * @author Brian Paul
  34.            Marek Olšák
  35.  */
  36.  
  37.  
  38. #include "pipe/p_context.h"
  39. #include "pipe/p_shader_tokens.h"
  40. #include "pipe/p_state.h"
  41. #include "util/u_simple_shaders.h"
  42. #include "util/u_debug.h"
  43. #include "util/u_memory.h"
  44. #include "tgsi/tgsi_dump.h"
  45. #include "tgsi/tgsi_strings.h"
  46. #include "tgsi/tgsi_ureg.h"
  47. #include "tgsi/tgsi_text.h"
  48. #include <stdio.h> /* include last */
  49.  
  50.  
  51.  
  52. /**
  53.  * Make simple vertex pass-through shader.
  54.  * \param num_attribs  number of attributes to pass through
  55.  * \param semantic_names  array of semantic names for each attribute
  56.  * \param semantic_indexes  array of semantic indexes for each attribute
  57.  */
  58. void *
  59. util_make_vertex_passthrough_shader(struct pipe_context *pipe,
  60.                                     uint num_attribs,
  61.                                     const uint *semantic_names,
  62.                                     const uint *semantic_indexes,
  63.                                     bool window_space)
  64. {
  65.    return util_make_vertex_passthrough_shader_with_so(pipe, num_attribs,
  66.                                                       semantic_names,
  67.                                                       semantic_indexes,
  68.                                                       window_space, NULL);
  69. }
  70.  
  71. void *
  72. util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe,
  73.                                     uint num_attribs,
  74.                                     const uint *semantic_names,
  75.                                     const uint *semantic_indexes,
  76.                                     bool window_space,
  77.                                     const struct pipe_stream_output_info *so)
  78. {
  79.    struct ureg_program *ureg;
  80.    uint i;
  81.  
  82.    ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
  83.    if (ureg == NULL)
  84.       return NULL;
  85.  
  86.    if (window_space)
  87.       ureg_property(ureg, TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION, TRUE);
  88.  
  89.    for (i = 0; i < num_attribs; i++) {
  90.       struct ureg_src src;
  91.       struct ureg_dst dst;
  92.  
  93.       src = ureg_DECL_vs_input( ureg, i );
  94.      
  95.       dst = ureg_DECL_output( ureg,
  96.                               semantic_names[i],
  97.                               semantic_indexes[i]);
  98.      
  99.       ureg_MOV( ureg, dst, src );
  100.    }
  101.  
  102.    ureg_END( ureg );
  103.  
  104.    return ureg_create_shader_with_so_and_destroy( ureg, pipe, so );
  105. }
  106.  
  107.  
  108. void *util_make_layered_clear_vertex_shader(struct pipe_context *pipe)
  109. {
  110.    static const char text[] =
  111.          "VERT\n"
  112.          "DCL IN[0]\n"
  113.          "DCL IN[1]\n"
  114.          "DCL SV[0], INSTANCEID\n"
  115.          "DCL OUT[0], POSITION\n"
  116.          "DCL OUT[1], GENERIC[0]\n"
  117.          "DCL OUT[2], LAYER\n"
  118.  
  119.          "MOV OUT[0], IN[0]\n"
  120.          "MOV OUT[1], IN[1]\n"
  121.          "MOV OUT[2], SV[0]\n"
  122.          "END\n";
  123.    struct tgsi_token tokens[1000];
  124.    struct pipe_shader_state state = {tokens};
  125.  
  126.    if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
  127.       assert(0);
  128.       return NULL;
  129.    }
  130.    return pipe->create_vs_state(pipe, &state);
  131. }
  132.  
  133. /**
  134.  * Takes position and color, and outputs position, color, and instance id.
  135.  */
  136. void *util_make_layered_clear_helper_vertex_shader(struct pipe_context *pipe)
  137. {
  138.    static const char text[] =
  139.          "VERT\n"
  140.          "DCL IN[0]\n"
  141.          "DCL IN[1]\n"
  142.          "DCL SV[0], INSTANCEID\n"
  143.          "DCL OUT[0], POSITION\n"
  144.          "DCL OUT[1], GENERIC[0]\n"
  145.          "DCL OUT[2], GENERIC[1]\n"
  146.  
  147.          "MOV OUT[0], IN[0]\n"
  148.          "MOV OUT[1], IN[1]\n"
  149.          "MOV OUT[2].x, SV[0].xxxx\n"
  150.          "END\n";
  151.    struct tgsi_token tokens[1000];
  152.    struct pipe_shader_state state = {tokens};
  153.  
  154.    if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
  155.       assert(0);
  156.       return NULL;
  157.    }
  158.    return pipe->create_vs_state(pipe, &state);
  159. }
  160.  
  161. /**
  162.  * Takes position, color, and target layer, and emits vertices on that target
  163.  * layer, with the specified color.
  164.  */
  165. void *util_make_layered_clear_geometry_shader(struct pipe_context *pipe)
  166. {
  167.    static const char text[] =
  168.       "GEOM\n"
  169.       "PROPERTY GS_INPUT_PRIMITIVE TRIANGLES\n"
  170.       "PROPERTY GS_OUTPUT_PRIMITIVE TRIANGLE_STRIP\n"
  171.       "PROPERTY GS_MAX_OUTPUT_VERTICES 3\n"
  172.       "PROPERTY GS_INVOCATIONS 1\n"
  173.       "DCL IN[][0], POSITION\n" /* position */
  174.       "DCL IN[][1], GENERIC[0]\n" /* color */
  175.       "DCL IN[][2], GENERIC[1]\n" /* vs invocation */
  176.       "DCL OUT[0], POSITION\n"
  177.       "DCL OUT[1], GENERIC[0]\n"
  178.       "DCL OUT[2], LAYER\n"
  179.       "IMM[0] INT32 {0, 0, 0, 0}\n"
  180.  
  181.       "MOV OUT[0], IN[0][0]\n"
  182.       "MOV OUT[1], IN[0][1]\n"
  183.       "MOV OUT[2].x, IN[0][2].xxxx\n"
  184.       "EMIT IMM[0].xxxx\n"
  185.       "MOV OUT[0], IN[1][0]\n"
  186.       "MOV OUT[1], IN[1][1]\n"
  187.       "MOV OUT[2].x, IN[1][2].xxxx\n"
  188.       "EMIT IMM[0].xxxx\n"
  189.       "MOV OUT[0], IN[2][0]\n"
  190.       "MOV OUT[1], IN[2][1]\n"
  191.       "MOV OUT[2].x, IN[2][2].xxxx\n"
  192.       "EMIT IMM[0].xxxx\n"
  193.       "END\n";
  194.    struct tgsi_token tokens[1000];
  195.    struct pipe_shader_state state = {tokens};
  196.  
  197.    if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
  198.       assert(0);
  199.       return NULL;
  200.    }
  201.    return pipe->create_gs_state(pipe, &state);
  202. }
  203.  
  204. /**
  205.  * Make simple fragment texture shader:
  206.  *  IMM {0,0,0,1}                         // (if writemask != 0xf)
  207.  *  MOV OUT[0], IMM[0]                    // (if writemask != 0xf)
  208.  *  TEX OUT[0].writemask, IN[0], SAMP[0], 2D;
  209.  *  END;
  210.  *
  211.  * \param tex_target  one of PIPE_TEXTURE_x
  212.  * \parma interp_mode  either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE
  213.  * \param writemask  mask of TGSI_WRITEMASK_x
  214.  */
  215. void *
  216. util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
  217.                                         unsigned tex_target,
  218.                                         unsigned interp_mode,
  219.                                         unsigned writemask )
  220. {
  221.    struct ureg_program *ureg;
  222.    struct ureg_src sampler;
  223.    struct ureg_src tex;
  224.    struct ureg_dst out;
  225.  
  226.    assert(interp_mode == TGSI_INTERPOLATE_LINEAR ||
  227.           interp_mode == TGSI_INTERPOLATE_PERSPECTIVE);
  228.  
  229.    ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
  230.    if (ureg == NULL)
  231.       return NULL;
  232.    
  233.    sampler = ureg_DECL_sampler( ureg, 0 );
  234.  
  235.    tex = ureg_DECL_fs_input( ureg,
  236.                              TGSI_SEMANTIC_GENERIC, 0,
  237.                              interp_mode );
  238.  
  239.    out = ureg_DECL_output( ureg,
  240.                            TGSI_SEMANTIC_COLOR,
  241.                            0 );
  242.  
  243.    if (writemask != TGSI_WRITEMASK_XYZW) {
  244.       struct ureg_src imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
  245.  
  246.       ureg_MOV( ureg, out, imm );
  247.    }
  248.  
  249.    if (tex_target == TGSI_TEXTURE_BUFFER)
  250.       ureg_TXF(ureg,
  251.                ureg_writemask(out, writemask),
  252.                tex_target, tex, sampler);
  253.    else
  254.       ureg_TEX(ureg,
  255.                ureg_writemask(out, writemask),
  256.                tex_target, tex, sampler);
  257.  
  258.    ureg_END( ureg );
  259.  
  260.    return ureg_create_shader_and_destroy( ureg, pipe );
  261. }
  262.  
  263.  
  264. /**
  265.  * Make a simple fragment shader that sets the output color to a color
  266.  * taken from a texture.
  267.  * \param tex_target  one of PIPE_TEXTURE_x
  268.  */
  269. void *
  270. util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target,
  271.                               unsigned interp_mode)
  272. {
  273.    return util_make_fragment_tex_shader_writemask( pipe,
  274.                                                    tex_target,
  275.                                                    interp_mode,
  276.                                                    TGSI_WRITEMASK_XYZW );
  277. }
  278.  
  279.  
  280. /**
  281.  * Make a simple fragment texture shader which reads an X component from
  282.  * a texture and writes it as depth.
  283.  */
  284. void *
  285. util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
  286.                                          unsigned tex_target,
  287.                                          unsigned interp_mode)
  288. {
  289.    struct ureg_program *ureg;
  290.    struct ureg_src sampler;
  291.    struct ureg_src tex;
  292.    struct ureg_dst out, depth;
  293.    struct ureg_src imm;
  294.  
  295.    ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
  296.    if (ureg == NULL)
  297.       return NULL;
  298.  
  299.    sampler = ureg_DECL_sampler( ureg, 0 );
  300.  
  301.    tex = ureg_DECL_fs_input( ureg,
  302.                              TGSI_SEMANTIC_GENERIC, 0,
  303.                              interp_mode );
  304.  
  305.    out = ureg_DECL_output( ureg,
  306.                            TGSI_SEMANTIC_COLOR,
  307.                            0 );
  308.  
  309.    depth = ureg_DECL_output( ureg,
  310.                              TGSI_SEMANTIC_POSITION,
  311.                              0 );
  312.  
  313.    imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
  314.  
  315.    ureg_MOV( ureg, out, imm );
  316.  
  317.    ureg_TEX( ureg,
  318.              ureg_writemask(depth, TGSI_WRITEMASK_Z),
  319.              tex_target, tex, sampler );
  320.    ureg_END( ureg );
  321.  
  322.    return ureg_create_shader_and_destroy( ureg, pipe );
  323. }
  324.  
  325.  
  326. /**
  327.  * Make a simple fragment texture shader which reads the texture unit 0 and 1
  328.  * and writes it as depth and stencil, respectively.
  329.  */
  330. void *
  331. util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe,
  332.                                                 unsigned tex_target,
  333.                                                 unsigned interp_mode)
  334. {
  335.    struct ureg_program *ureg;
  336.    struct ureg_src depth_sampler, stencil_sampler;
  337.    struct ureg_src tex;
  338.    struct ureg_dst out, depth, stencil;
  339.    struct ureg_src imm;
  340.  
  341.    ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
  342.    if (ureg == NULL)
  343.       return NULL;
  344.  
  345.    depth_sampler = ureg_DECL_sampler( ureg, 0 );
  346.    stencil_sampler = ureg_DECL_sampler( ureg, 1 );
  347.  
  348.    tex = ureg_DECL_fs_input( ureg,
  349.                              TGSI_SEMANTIC_GENERIC, 0,
  350.                              interp_mode );
  351.  
  352.    out = ureg_DECL_output( ureg,
  353.                            TGSI_SEMANTIC_COLOR,
  354.                            0 );
  355.  
  356.    depth = ureg_DECL_output( ureg,
  357.                              TGSI_SEMANTIC_POSITION,
  358.                              0 );
  359.  
  360.    stencil = ureg_DECL_output( ureg,
  361.                              TGSI_SEMANTIC_STENCIL,
  362.                              0 );
  363.  
  364.    imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
  365.  
  366.    ureg_MOV( ureg, out, imm );
  367.  
  368.    ureg_TEX( ureg,
  369.              ureg_writemask(depth, TGSI_WRITEMASK_Z),
  370.              tex_target, tex, depth_sampler );
  371.    ureg_TEX( ureg,
  372.              ureg_writemask(stencil, TGSI_WRITEMASK_Y),
  373.              tex_target, tex, stencil_sampler );
  374.    ureg_END( ureg );
  375.  
  376.    return ureg_create_shader_and_destroy( ureg, pipe );
  377. }
  378.  
  379.  
  380. /**
  381.  * Make a simple fragment texture shader which reads a texture and writes it
  382.  * as stencil.
  383.  */
  384. void *
  385. util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe,
  386.                                            unsigned tex_target,
  387.                                            unsigned interp_mode)
  388. {
  389.    struct ureg_program *ureg;
  390.    struct ureg_src stencil_sampler;
  391.    struct ureg_src tex;
  392.    struct ureg_dst out, stencil;
  393.    struct ureg_src imm;
  394.  
  395.    ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
  396.    if (ureg == NULL)
  397.       return NULL;
  398.  
  399.    stencil_sampler = ureg_DECL_sampler( ureg, 0 );
  400.  
  401.    tex = ureg_DECL_fs_input( ureg,
  402.                              TGSI_SEMANTIC_GENERIC, 0,
  403.                              interp_mode );
  404.  
  405.    out = ureg_DECL_output( ureg,
  406.                            TGSI_SEMANTIC_COLOR,
  407.                            0 );
  408.  
  409.    stencil = ureg_DECL_output( ureg,
  410.                              TGSI_SEMANTIC_STENCIL,
  411.                              0 );
  412.  
  413.    imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
  414.  
  415.    ureg_MOV( ureg, out, imm );
  416.  
  417.    ureg_TEX( ureg,
  418.              ureg_writemask(stencil, TGSI_WRITEMASK_Y),
  419.              tex_target, tex, stencil_sampler );
  420.    ureg_END( ureg );
  421.  
  422.    return ureg_create_shader_and_destroy( ureg, pipe );
  423. }
  424.  
  425.  
  426. /**
  427.  * Make simple fragment color pass-through shader that replicates OUT[0]
  428.  * to all bound colorbuffers.
  429.  */
  430. void *
  431. util_make_fragment_passthrough_shader(struct pipe_context *pipe,
  432.                                       int input_semantic,
  433.                                       int input_interpolate,
  434.                                       boolean write_all_cbufs)
  435. {
  436.    static const char shader_templ[] =
  437.          "FRAG\n"
  438.          "%s"
  439.          "DCL IN[0], %s[0], %s\n"
  440.          "DCL OUT[0], COLOR[0]\n"
  441.  
  442.          "MOV OUT[0], IN[0]\n"
  443.          "END\n";
  444.  
  445.    char text[sizeof(shader_templ)+100];
  446.    struct tgsi_token tokens[1000];
  447.    struct pipe_shader_state state = {tokens};
  448.  
  449.    sprintf(text, shader_templ,
  450.            write_all_cbufs ? "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" : "",
  451.            tgsi_semantic_names[input_semantic],
  452.            tgsi_interpolate_names[input_interpolate]);
  453.  
  454.    if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
  455.       assert(0);
  456.       return NULL;
  457.    }
  458. #if 0
  459.    tgsi_dump(state.tokens, 0);
  460. #endif
  461.  
  462.    return pipe->create_fs_state(pipe, &state);
  463. }
  464.  
  465.  
  466. void *
  467. util_make_empty_fragment_shader(struct pipe_context *pipe)
  468. {
  469.    struct ureg_program *ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
  470.    if (ureg == NULL)
  471.       return NULL;
  472.  
  473.    ureg_END(ureg);
  474.    return ureg_create_shader_and_destroy(ureg, pipe);
  475. }
  476.  
  477.  
  478. /**
  479.  * Make a fragment shader that copies the input color to N output colors.
  480.  */
  481. void *
  482. util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs,
  483.                                      int input_semantic,
  484.                                      int input_interpolate)
  485. {
  486.    struct ureg_program *ureg;
  487.    struct ureg_src src;
  488.    struct ureg_dst dst[PIPE_MAX_COLOR_BUFS];
  489.    int i;
  490.  
  491.    assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
  492.  
  493.    ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
  494.    if (ureg == NULL)
  495.       return NULL;
  496.  
  497.    src = ureg_DECL_fs_input( ureg, input_semantic, 0,
  498.                              input_interpolate );
  499.  
  500.    for (i = 0; i < num_cbufs; i++)
  501.       dst[i] = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, i );
  502.  
  503.    for (i = 0; i < num_cbufs; i++)
  504.       ureg_MOV( ureg, dst[i], src );
  505.  
  506.    ureg_END( ureg );
  507.  
  508.    return ureg_create_shader_and_destroy( ureg, pipe );
  509. }
  510.  
  511.  
  512. static void *
  513. util_make_fs_blit_msaa_gen(struct pipe_context *pipe,
  514.                            unsigned tgsi_tex,
  515.                            const char *output_semantic,
  516.                            const char *output_mask)
  517. {
  518.    static const char shader_templ[] =
  519.          "FRAG\n"
  520.          "DCL IN[0], GENERIC[0], LINEAR\n"
  521.          "DCL SAMP[0]\n"
  522.          "DCL OUT[0], %s\n"
  523.          "DCL TEMP[0]\n"
  524.  
  525.          "F2U TEMP[0], IN[0]\n"
  526.          "TXF OUT[0]%s, TEMP[0], SAMP[0], %s\n"
  527.          "END\n";
  528.  
  529.    const char *type = tgsi_texture_names[tgsi_tex];
  530.    char text[sizeof(shader_templ)+100];
  531.    struct tgsi_token tokens[1000];
  532.    struct pipe_shader_state state = {tokens};
  533.  
  534.    assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
  535.           tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
  536.  
  537.    sprintf(text, shader_templ, output_semantic, output_mask, type);
  538.  
  539.    if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
  540.       puts(text);
  541.       assert(0);
  542.       return NULL;
  543.    }
  544. #if 0
  545.    tgsi_dump(state.tokens, 0);
  546. #endif
  547.  
  548.    return pipe->create_fs_state(pipe, &state);
  549. }
  550.  
  551.  
  552. /**
  553.  * Make a fragment shader that sets the output color to a color
  554.  * fetched from a multisample texture.
  555.  * \param tex_target  one of PIPE_TEXTURE_x
  556.  */
  557. void *
  558. util_make_fs_blit_msaa_color(struct pipe_context *pipe,
  559.                              unsigned tgsi_tex)
  560. {
  561.    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex,
  562.                                      "COLOR[0]", "");
  563. }
  564.  
  565.  
  566. /**
  567.  * Make a fragment shader that sets the output depth to a depth value
  568.  * fetched from a multisample texture.
  569.  * \param tex_target  one of PIPE_TEXTURE_x
  570.  */
  571. void *
  572. util_make_fs_blit_msaa_depth(struct pipe_context *pipe,
  573.                              unsigned tgsi_tex)
  574. {
  575.    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex,
  576.                                      "POSITION", ".z");
  577. }
  578.  
  579.  
  580. /**
  581.  * Make a fragment shader that sets the output stencil to a stencil value
  582.  * fetched from a multisample texture.
  583.  * \param tex_target  one of PIPE_TEXTURE_x
  584.  */
  585. void *
  586. util_make_fs_blit_msaa_stencil(struct pipe_context *pipe,
  587.                                unsigned tgsi_tex)
  588. {
  589.    return util_make_fs_blit_msaa_gen(pipe, tgsi_tex,
  590.                                      "STENCIL", ".y");
  591. }
  592.  
  593.  
  594. /**
  595.  * Make a fragment shader that sets the output depth and stencil to depth
  596.  * and stencil values fetched from two multisample textures / samplers.
  597.  * The sizes of both textures should match (it should be one depth-stencil
  598.  * texture).
  599.  * \param tex_target  one of PIPE_TEXTURE_x
  600.  */
  601. void *
  602. util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe,
  603.                                     unsigned tgsi_tex)
  604. {
  605.    static const char shader_templ[] =
  606.          "FRAG\n"
  607.          "DCL IN[0], GENERIC[0], LINEAR\n"
  608.          "DCL SAMP[0..1]\n"
  609.          "DCL OUT[0], POSITION\n"
  610.          "DCL OUT[1], STENCIL\n"
  611.          "DCL TEMP[0]\n"
  612.  
  613.          "F2U TEMP[0], IN[0]\n"
  614.          "TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
  615.          "TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
  616.          "END\n";
  617.  
  618.    const char *type = tgsi_texture_names[tgsi_tex];
  619.    char text[sizeof(shader_templ)+100];
  620.    struct tgsi_token tokens[1000];
  621.    struct pipe_shader_state state = {tokens};
  622.  
  623.    assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
  624.           tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
  625.  
  626.    sprintf(text, shader_templ, type, type);
  627.  
  628.    if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
  629.       assert(0);
  630.       return NULL;
  631.    }
  632. #if 0
  633.    tgsi_dump(state.tokens, 0);
  634. #endif
  635.  
  636.    return pipe->create_fs_state(pipe, &state);
  637. }
  638.  
  639.  
  640. void *
  641. util_make_fs_msaa_resolve(struct pipe_context *pipe,
  642.                           unsigned tgsi_tex, unsigned nr_samples,
  643.                           boolean is_uint, boolean is_sint)
  644. {
  645.    struct ureg_program *ureg;
  646.    struct ureg_src sampler, coord;
  647.    struct ureg_dst out, tmp_sum, tmp_coord, tmp;
  648.    int i;
  649.  
  650.    ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
  651.    if (!ureg)
  652.       return NULL;
  653.  
  654.    /* Declarations. */
  655.    sampler = ureg_DECL_sampler(ureg, 0);
  656.    coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0,
  657.                               TGSI_INTERPOLATE_LINEAR);
  658.    out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
  659.    tmp_sum = ureg_DECL_temporary(ureg);
  660.    tmp_coord = ureg_DECL_temporary(ureg);
  661.    tmp = ureg_DECL_temporary(ureg);
  662.  
  663.    /* Instructions. */
  664.    ureg_MOV(ureg, tmp_sum, ureg_imm1f(ureg, 0));
  665.    ureg_F2U(ureg, tmp_coord, coord);
  666.  
  667.    for (i = 0; i < nr_samples; i++) {
  668.       /* Read one sample. */
  669.       ureg_MOV(ureg, ureg_writemask(tmp_coord, TGSI_WRITEMASK_W),
  670.                ureg_imm1u(ureg, i));
  671.       ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord), sampler);
  672.  
  673.       if (is_uint)
  674.          ureg_U2F(ureg, tmp, ureg_src(tmp));
  675.       else if (is_sint)
  676.          ureg_I2F(ureg, tmp, ureg_src(tmp));
  677.  
  678.       /* Add it to the sum.*/
  679.       ureg_ADD(ureg, tmp_sum, ureg_src(tmp_sum), ureg_src(tmp));
  680.    }
  681.  
  682.    /* Calculate the average and return. */
  683.    ureg_MUL(ureg, tmp_sum, ureg_src(tmp_sum),
  684.             ureg_imm1f(ureg, 1.0 / nr_samples));
  685.  
  686.    if (is_uint)
  687.       ureg_F2U(ureg, out, ureg_src(tmp_sum));
  688.    else if (is_sint)
  689.       ureg_F2I(ureg, out, ureg_src(tmp_sum));
  690.    else
  691.       ureg_MOV(ureg, out, ureg_src(tmp_sum));
  692.  
  693.    ureg_END(ureg);
  694.  
  695.    return ureg_create_shader_and_destroy(ureg, pipe);
  696. }
  697.  
  698.  
  699. void *
  700. util_make_fs_msaa_resolve_bilinear(struct pipe_context *pipe,
  701.                                    unsigned tgsi_tex, unsigned nr_samples,
  702.                                    boolean is_uint, boolean is_sint)
  703. {
  704.    struct ureg_program *ureg;
  705.    struct ureg_src sampler, coord;
  706.    struct ureg_dst out, tmp, top, bottom;
  707.    struct ureg_dst tmp_coord[4], tmp_sum[4];
  708.    int i, c;
  709.  
  710.    ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
  711.    if (!ureg)
  712.       return NULL;
  713.  
  714.    /* Declarations. */
  715.    sampler = ureg_DECL_sampler(ureg, 0);
  716.    coord = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_GENERIC, 0,
  717.                               TGSI_INTERPOLATE_LINEAR);
  718.    out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
  719.    for (c = 0; c < 4; c++)
  720.       tmp_sum[c] = ureg_DECL_temporary(ureg);
  721.    for (c = 0; c < 4; c++)
  722.       tmp_coord[c] = ureg_DECL_temporary(ureg);
  723.    tmp = ureg_DECL_temporary(ureg);
  724.    top = ureg_DECL_temporary(ureg);
  725.    bottom = ureg_DECL_temporary(ureg);
  726.  
  727.    /* Instructions. */
  728.    for (c = 0; c < 4; c++)
  729.       ureg_MOV(ureg, tmp_sum[c], ureg_imm1f(ureg, 0));
  730.  
  731.    /* Get 4 texture coordinates for the bilinear filter. */
  732.    ureg_F2U(ureg, tmp_coord[0], coord); /* top-left */
  733.    ureg_UADD(ureg, tmp_coord[1], ureg_src(tmp_coord[0]),
  734.              ureg_imm4u(ureg, 1, 0, 0, 0)); /* top-right */
  735.    ureg_UADD(ureg, tmp_coord[2], ureg_src(tmp_coord[0]),
  736.              ureg_imm4u(ureg, 0, 1, 0, 0)); /* bottom-left */
  737.    ureg_UADD(ureg, tmp_coord[3], ureg_src(tmp_coord[0]),
  738.              ureg_imm4u(ureg, 1, 1, 0, 0)); /* bottom-right */
  739.  
  740.    for (i = 0; i < nr_samples; i++) {
  741.       for (c = 0; c < 4; c++) {
  742.          /* Read one sample. */
  743.          ureg_MOV(ureg, ureg_writemask(tmp_coord[c], TGSI_WRITEMASK_W),
  744.                   ureg_imm1u(ureg, i));
  745.          ureg_TXF(ureg, tmp, tgsi_tex, ureg_src(tmp_coord[c]), sampler);
  746.  
  747.          if (is_uint)
  748.             ureg_U2F(ureg, tmp, ureg_src(tmp));
  749.          else if (is_sint)
  750.             ureg_I2F(ureg, tmp, ureg_src(tmp));
  751.  
  752.          /* Add it to the sum.*/
  753.          ureg_ADD(ureg, tmp_sum[c], ureg_src(tmp_sum[c]), ureg_src(tmp));
  754.       }
  755.    }
  756.  
  757.    /* Calculate the average. */
  758.    for (c = 0; c < 4; c++)
  759.       ureg_MUL(ureg, tmp_sum[c], ureg_src(tmp_sum[c]),
  760.                ureg_imm1f(ureg, 1.0 / nr_samples));
  761.  
  762.    /* Take the 4 average values and apply a standard bilinear filter. */
  763.    ureg_FRC(ureg, tmp, coord);
  764.  
  765.    ureg_LRP(ureg, top,
  766.             ureg_scalar(ureg_src(tmp), 0),
  767.             ureg_src(tmp_sum[1]),
  768.             ureg_src(tmp_sum[0]));
  769.  
  770.    ureg_LRP(ureg, bottom,
  771.             ureg_scalar(ureg_src(tmp), 0),
  772.             ureg_src(tmp_sum[3]),
  773.             ureg_src(tmp_sum[2]));
  774.  
  775.    ureg_LRP(ureg, tmp,
  776.             ureg_scalar(ureg_src(tmp), 1),
  777.             ureg_src(bottom),
  778.             ureg_src(top));
  779.  
  780.    /* Convert to the texture format and return. */
  781.    if (is_uint)
  782.       ureg_F2U(ureg, out, ureg_src(tmp));
  783.    else if (is_sint)
  784.       ureg_F2I(ureg, out, ureg_src(tmp));
  785.    else
  786.       ureg_MOV(ureg, out, ureg_src(tmp));
  787.  
  788.    ureg_END(ureg);
  789.  
  790.    return ureg_create_shader_and_destroy(ureg, pipe);
  791. }
  792.