Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2008 VMware, Inc.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. /**
  29.  * Polygon stipple stage:  implement polygon stipple with texture map and
  30.  * fragment program.  The fragment program samples the texture using the
  31.  * fragment window coordinate register and does a fragment kill for the
  32.  * stipple-failing fragments.
  33.  *
  34.  * Authors:  Brian Paul
  35.  */
  36.  
  37.  
  38. #include "pipe/p_context.h"
  39. #include "pipe/p_defines.h"
  40. #include "pipe/p_shader_tokens.h"
  41. #include "util/u_inlines.h"
  42.  
  43. #include "util/u_format.h"
  44. #include "util/u_math.h"
  45. #include "util/u_memory.h"
  46. #include "util/u_sampler.h"
  47.  
  48. #include "tgsi/tgsi_transform.h"
  49. #include "tgsi/tgsi_dump.h"
  50.  
  51. #include "draw_context.h"
  52. #include "draw_pipe.h"
  53.  
  54.  
  55. /** Approx number of new tokens for instructions in pstip_transform_inst() */
  56. #define NUM_NEW_TOKENS 50
  57.  
  58.  
  59. /**
  60.  * Subclass of pipe_shader_state to carry extra fragment shader info.
  61.  */
  62. struct pstip_fragment_shader
  63. {
  64.    struct pipe_shader_state state;
  65.    void *driver_fs;
  66.    void *pstip_fs;
  67.    uint sampler_unit;
  68. };
  69.  
  70.  
  71. /**
  72.  * Subclass of draw_stage
  73.  */
  74. struct pstip_stage
  75. {
  76.    struct draw_stage stage;
  77.  
  78.    void *sampler_cso;
  79.    struct pipe_resource *texture;
  80.    struct pipe_sampler_view *sampler_view;
  81.    uint num_samplers;
  82.    uint num_sampler_views;
  83.  
  84.    /*
  85.     * Currently bound state
  86.     */
  87.    struct pstip_fragment_shader *fs;
  88.    struct {
  89.       void *samplers[PIPE_MAX_SAMPLERS];
  90.       struct pipe_sampler_view *sampler_views[PIPE_MAX_SHADER_SAMPLER_VIEWS];
  91.       const struct pipe_poly_stipple *stipple;
  92.    } state;
  93.  
  94.    /*
  95.     * Driver interface/override functions
  96.     */
  97.    void * (*driver_create_fs_state)(struct pipe_context *,
  98.                                     const struct pipe_shader_state *);
  99.    void (*driver_bind_fs_state)(struct pipe_context *, void *);
  100.    void (*driver_delete_fs_state)(struct pipe_context *, void *);
  101.  
  102.    void (*driver_bind_sampler_states)(struct pipe_context *, unsigned,
  103.                                       unsigned, unsigned, void **);
  104.  
  105.    void (*driver_set_sampler_views)(struct pipe_context *,
  106.                                     unsigned shader, unsigned start,
  107.                                     unsigned count,
  108.                                     struct pipe_sampler_view **);
  109.  
  110.    void (*driver_set_polygon_stipple)(struct pipe_context *,
  111.                                       const struct pipe_poly_stipple *);
  112.  
  113.    struct pipe_context *pipe;
  114. };
  115.  
  116.  
  117.  
  118. /**
  119.  * Subclass of tgsi_transform_context, used for transforming the
  120.  * user's fragment shader to add the extra texture sample and fragment kill
  121.  * instructions.
  122.  */
  123. struct pstip_transform_context {
  124.    struct tgsi_transform_context base;
  125.    uint tempsUsed;  /**< bitmask */
  126.    int wincoordInput;
  127.    int maxInput;
  128.    uint samplersUsed;  /**< bitfield of samplers used */
  129.    int freeSampler;  /** an available sampler for the pstipple */
  130.    int texTemp;  /**< temp registers */
  131.    int numImmed;
  132. };
  133.  
  134.  
  135. /**
  136.  * TGSI declaration transform callback.
  137.  * Look for a free sampler, a free input attrib, and two free temp regs.
  138.  */
  139. static void
  140. pstip_transform_decl(struct tgsi_transform_context *ctx,
  141.                      struct tgsi_full_declaration *decl)
  142. {
  143.    struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
  144.  
  145.    if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
  146.       uint i;
  147.       for (i = decl->Range.First;
  148.            i <= decl->Range.Last; i++) {
  149.          pctx->samplersUsed |= 1 << i;
  150.       }
  151.    }
  152.    else if (decl->Declaration.File == TGSI_FILE_INPUT) {
  153.       pctx->maxInput = MAX2(pctx->maxInput, (int) decl->Range.Last);
  154.       if (decl->Semantic.Name == TGSI_SEMANTIC_POSITION)
  155.          pctx->wincoordInput = (int) decl->Range.First;
  156.    }
  157.    else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
  158.       uint i;
  159.       for (i = decl->Range.First;
  160.            i <= decl->Range.Last; i++) {
  161.          pctx->tempsUsed |= (1 << i);
  162.       }
  163.    }
  164.  
  165.    ctx->emit_declaration(ctx, decl);
  166. }
  167.  
  168.  
  169. /**
  170.  * TGSI immediate declaration transform callback.
  171.  * We're just counting the number of immediates here.
  172.  */
  173. static void
  174. pstip_transform_immed(struct tgsi_transform_context *ctx,
  175.                       struct tgsi_full_immediate *immed)
  176. {
  177.    struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
  178.    ctx->emit_immediate(ctx, immed); /* emit to output shader */
  179.    pctx->numImmed++;
  180. }
  181.  
  182.  
  183. /**
  184.  * Find the lowest zero bit in the given word, or -1 if bitfield is all ones.
  185.  */
  186. static int
  187. free_bit(uint bitfield)
  188. {
  189.    return ffs(~bitfield) - 1;
  190. }
  191.  
  192.  
  193. /**
  194.  * TGSI transform prolog callback.
  195.  */
  196. static void
  197. pstip_transform_prolog(struct tgsi_transform_context *ctx)
  198. {
  199.    struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
  200.    uint i;
  201.    int wincoordInput;
  202.  
  203.    /* find free sampler */
  204.    pctx->freeSampler = free_bit(pctx->samplersUsed);
  205.    if (pctx->freeSampler >= PIPE_MAX_SAMPLERS)
  206.       pctx->freeSampler = PIPE_MAX_SAMPLERS - 1;
  207.  
  208.    if (pctx->wincoordInput < 0)
  209.       wincoordInput = pctx->maxInput + 1;
  210.    else
  211.       wincoordInput = pctx->wincoordInput;
  212.  
  213.    /* find one free temp reg */
  214.    for (i = 0; i < 32; i++) {
  215.       if ((pctx->tempsUsed & (1 << i)) == 0) {
  216.       /* found a free temp */
  217.       if (pctx->texTemp < 0)
  218.          pctx->texTemp  = i;
  219.       else
  220.          break;
  221.       }
  222.    }
  223.    assert(pctx->texTemp >= 0);
  224.  
  225.    if (pctx->wincoordInput < 0) {
  226.       /* declare new position input reg */
  227.       tgsi_transform_input_decl(ctx, wincoordInput,
  228.                                 TGSI_SEMANTIC_POSITION, 1,
  229.                                 TGSI_INTERPOLATE_LINEAR);
  230.    }
  231.  
  232.    /* declare new sampler */
  233.    tgsi_transform_sampler_decl(ctx, pctx->freeSampler);
  234.  
  235.    /* declare new temp regs */
  236.    tgsi_transform_temp_decl(ctx, pctx->texTemp);
  237.  
  238.    /* emit immediate = {1/32, 1/32, 1, 1}
  239.     * The index/position of this immediate will be pctx->numImmed
  240.     */
  241.    tgsi_transform_immediate_decl(ctx, 1.0/32.0, 1.0/32.0, 1.0, 1.0);
  242.  
  243.    /*
  244.     * Insert new MUL/TEX/KILL_IF instructions at start of program
  245.     * Take gl_FragCoord, divide by 32 (stipple size), sample the
  246.     * texture and kill fragment if needed.
  247.     *
  248.     * We'd like to use non-normalized texcoords to index into a RECT
  249.     * texture, but we can only use GL_REPEAT wrap mode with normalized
  250.     * texcoords.  Darn.
  251.     */
  252.  
  253.    /* MUL texTemp, INPUT[wincoord], 1/32; */
  254.    tgsi_transform_op2_inst(ctx, TGSI_OPCODE_MUL,
  255.                            TGSI_FILE_TEMPORARY, pctx->texTemp,
  256.                            TGSI_WRITEMASK_XYZW,
  257.                            TGSI_FILE_INPUT, wincoordInput,
  258.                            TGSI_FILE_IMMEDIATE, pctx->numImmed);
  259.  
  260.    /* TEX texTemp, texTemp, sampler; */
  261.    tgsi_transform_tex_2d_inst(ctx,
  262.                               TGSI_FILE_TEMPORARY, pctx->texTemp,
  263.                               TGSI_FILE_TEMPORARY, pctx->texTemp,
  264.                               pctx->freeSampler);
  265.  
  266.    /* KILL_IF -texTemp.wwww;   # if -texTemp < 0, KILL fragment */
  267.    tgsi_transform_kill_inst(ctx,
  268.                             TGSI_FILE_TEMPORARY, pctx->texTemp, TGSI_SWIZZLE_W);
  269. }
  270.  
  271.  
  272.  
  273. /**
  274.  * Generate the frag shader we'll use for doing polygon stipple.
  275.  * This will be the user's shader prefixed with a TEX and KIL instruction.
  276.  */
  277. static boolean
  278. generate_pstip_fs(struct pstip_stage *pstip)
  279. {
  280.    const struct pipe_shader_state *orig_fs = &pstip->fs->state;
  281.    /*struct draw_context *draw = pstip->stage.draw;*/
  282.    struct pipe_shader_state pstip_fs;
  283.    struct pstip_transform_context transform;
  284.    const uint newLen = tgsi_num_tokens(orig_fs->tokens) + NUM_NEW_TOKENS;
  285.  
  286.    pstip_fs = *orig_fs; /* copy to init */
  287.    pstip_fs.tokens = tgsi_alloc_tokens(newLen);
  288.    if (pstip_fs.tokens == NULL)
  289.       return FALSE;
  290.  
  291.    memset(&transform, 0, sizeof(transform));
  292.    transform.wincoordInput = -1;
  293.    transform.maxInput = -1;
  294.    transform.texTemp = -1;
  295.    transform.base.prolog = pstip_transform_prolog;
  296.    transform.base.transform_declaration = pstip_transform_decl;
  297.    transform.base.transform_immediate = pstip_transform_immed;
  298.  
  299.    tgsi_transform_shader(orig_fs->tokens,
  300.                          (struct tgsi_token *) pstip_fs.tokens,
  301.                          newLen, &transform.base);
  302.  
  303. #if 0 /* DEBUG */
  304.    tgsi_dump(orig_fs->tokens, 0);
  305.    tgsi_dump(pstip_fs.tokens, 0);
  306. #endif
  307.  
  308.    assert(pstip->fs);
  309.  
  310.    pstip->fs->sampler_unit = transform.freeSampler;
  311.    assert(pstip->fs->sampler_unit < PIPE_MAX_SAMPLERS);
  312.  
  313.    pstip->fs->pstip_fs = pstip->driver_create_fs_state(pstip->pipe, &pstip_fs);
  314.    
  315.    FREE((void *)pstip_fs.tokens);
  316.  
  317.    if (!pstip->fs->pstip_fs)
  318.       return FALSE;
  319.  
  320.    return TRUE;
  321. }
  322.  
  323.  
  324. /**
  325.  * Load texture image with current stipple pattern.
  326.  */
  327. static void
  328. pstip_update_texture(struct pstip_stage *pstip)
  329. {
  330.    static const uint bit31 = 1 << 31;
  331.    struct pipe_context *pipe = pstip->pipe;
  332.    struct pipe_transfer *transfer;
  333.    const uint *stipple = pstip->state.stipple->stipple;
  334.    uint i, j;
  335.    ubyte *data;
  336.  
  337.    data = pipe_transfer_map(pipe, pstip->texture, 0, 0,
  338.                                 PIPE_TRANSFER_WRITE, 0, 0, 32, 32, &transfer);
  339.  
  340.    /*
  341.     * Load alpha texture.
  342.     * Note: 0 means keep the fragment, 255 means kill it.
  343.     * We'll negate the texel value and use KILL_IF which kills if value
  344.     * is negative.
  345.     */
  346.    for (i = 0; i < 32; i++) {
  347.       for (j = 0; j < 32; j++) {
  348.          if (stipple[i] & (bit31 >> j)) {
  349.             /* fragment "on" */
  350.             data[i * transfer->stride + j] = 0;
  351.          }
  352.          else {
  353.             /* fragment "off" */
  354.             data[i * transfer->stride + j] = 255;
  355.          }
  356.       }
  357.    }
  358.  
  359.    /* unmap */
  360.    pipe_transfer_unmap(pipe, transfer);
  361. }
  362.  
  363.  
  364. /**
  365.  * Create the texture map we'll use for stippling.
  366.  */
  367. static boolean
  368. pstip_create_texture(struct pstip_stage *pstip)
  369. {
  370.    struct pipe_context *pipe = pstip->pipe;
  371.    struct pipe_screen *screen = pipe->screen;
  372.    struct pipe_resource texTemp;
  373.    struct pipe_sampler_view viewTempl;
  374.  
  375.    memset(&texTemp, 0, sizeof(texTemp));
  376.    texTemp.target = PIPE_TEXTURE_2D;
  377.    texTemp.format = PIPE_FORMAT_A8_UNORM; /* XXX verify supported by driver! */
  378.    texTemp.last_level = 0;
  379.    texTemp.width0 = 32;
  380.    texTemp.height0 = 32;
  381.    texTemp.depth0 = 1;
  382.    texTemp.array_size = 1;
  383.    texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
  384.  
  385.    pstip->texture = screen->resource_create(screen, &texTemp);
  386.    if (pstip->texture == NULL)
  387.       return FALSE;
  388.  
  389.    u_sampler_view_default_template(&viewTempl,
  390.                                    pstip->texture,
  391.                                    pstip->texture->format);
  392.    pstip->sampler_view = pipe->create_sampler_view(pipe,
  393.                                                    pstip->texture,
  394.                                                    &viewTempl);
  395.    if (!pstip->sampler_view) {
  396.       return FALSE;
  397.    }
  398.  
  399.    return TRUE;
  400. }
  401.  
  402.  
  403. /**
  404.  * Create the sampler CSO that'll be used for stippling.
  405.  */
  406. static boolean
  407. pstip_create_sampler(struct pstip_stage *pstip)
  408. {
  409.    struct pipe_sampler_state sampler;
  410.    struct pipe_context *pipe = pstip->pipe;
  411.  
  412.    memset(&sampler, 0, sizeof(sampler));
  413.    sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
  414.    sampler.wrap_t = PIPE_TEX_WRAP_REPEAT;
  415.    sampler.wrap_r = PIPE_TEX_WRAP_REPEAT;
  416.    sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
  417.    sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
  418.    sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
  419.    sampler.normalized_coords = 1;
  420.    sampler.min_lod = 0.0f;
  421.    sampler.max_lod = 0.0f;
  422.  
  423.    pstip->sampler_cso = pipe->create_sampler_state(pipe, &sampler);
  424.    if (pstip->sampler_cso == NULL)
  425.       return FALSE;
  426.    
  427.    return TRUE;
  428. }
  429.  
  430.  
  431. /**
  432.  * When we're about to draw our first stipple polygon in a batch, this function
  433.  * is called to tell the driver to bind our modified fragment shader.
  434.  */
  435. static boolean
  436. bind_pstip_fragment_shader(struct pstip_stage *pstip)
  437. {
  438.    struct draw_context *draw = pstip->stage.draw;
  439.    if (!pstip->fs->pstip_fs &&
  440.        !generate_pstip_fs(pstip))
  441.       return FALSE;
  442.  
  443.    draw->suspend_flushing = TRUE;
  444.    pstip->driver_bind_fs_state(pstip->pipe, pstip->fs->pstip_fs);
  445.    draw->suspend_flushing = FALSE;
  446.    return TRUE;
  447. }
  448.  
  449.  
  450. static INLINE struct pstip_stage *
  451. pstip_stage( struct draw_stage *stage )
  452. {
  453.    return (struct pstip_stage *) stage;
  454. }
  455.  
  456.  
  457. static void
  458. pstip_first_tri(struct draw_stage *stage, struct prim_header *header)
  459. {
  460.    struct pstip_stage *pstip = pstip_stage(stage);
  461.    struct pipe_context *pipe = pstip->pipe;
  462.    struct draw_context *draw = stage->draw;
  463.    uint num_samplers;
  464.  
  465.    assert(stage->draw->rasterizer->poly_stipple_enable);
  466.  
  467.    /* bind our fragprog */
  468.    if (!bind_pstip_fragment_shader(pstip)) {
  469.       stage->tri = draw_pipe_passthrough_tri;
  470.       stage->tri(stage, header);
  471.       return;
  472.    }
  473.      
  474.  
  475.    /* how many samplers? */
  476.    /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */
  477.    num_samplers = MAX2(pstip->num_sampler_views, pstip->num_samplers);
  478.    num_samplers = MAX2(num_samplers, pstip->fs->sampler_unit + 1);
  479.  
  480.    /* plug in our sampler, texture */
  481.    pstip->state.samplers[pstip->fs->sampler_unit] = pstip->sampler_cso;
  482.    pipe_sampler_view_reference(&pstip->state.sampler_views[pstip->fs->sampler_unit],
  483.                                pstip->sampler_view);
  484.  
  485.    assert(num_samplers <= PIPE_MAX_SAMPLERS);
  486.  
  487.    draw->suspend_flushing = TRUE;
  488.  
  489.    pstip->driver_bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0,
  490.                                      num_samplers, pstip->state.samplers);
  491.  
  492.    pstip->driver_set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0,
  493.                                    num_samplers, pstip->state.sampler_views);
  494.  
  495.    draw->suspend_flushing = FALSE;
  496.  
  497.    /* now really draw first triangle */
  498.    stage->tri = draw_pipe_passthrough_tri;
  499.    stage->tri(stage, header);
  500. }
  501.  
  502.  
  503. static void
  504. pstip_flush(struct draw_stage *stage, unsigned flags)
  505. {
  506.    struct draw_context *draw = stage->draw;
  507.    struct pstip_stage *pstip = pstip_stage(stage);
  508.    struct pipe_context *pipe = pstip->pipe;
  509.  
  510.    stage->tri = pstip_first_tri;
  511.    stage->next->flush( stage->next, flags );
  512.  
  513.    /* restore original frag shader, texture, sampler state */
  514.    draw->suspend_flushing = TRUE;
  515.    pstip->driver_bind_fs_state(pipe, pstip->fs ? pstip->fs->driver_fs : NULL);
  516.  
  517.    pstip->driver_bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0,
  518.                                      pstip->num_samplers,
  519.                                      pstip->state.samplers);
  520.  
  521.    pstip->driver_set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0,
  522.                                    pstip->num_sampler_views,
  523.                                    pstip->state.sampler_views);
  524.  
  525.    draw->suspend_flushing = FALSE;
  526. }
  527.  
  528.  
  529. static void
  530. pstip_reset_stipple_counter(struct draw_stage *stage)
  531. {
  532.    stage->next->reset_stipple_counter( stage->next );
  533. }
  534.  
  535.  
  536. static void
  537. pstip_destroy(struct draw_stage *stage)
  538. {
  539.    struct pstip_stage *pstip = pstip_stage(stage);
  540.    uint i;
  541.  
  542.    for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) {
  543.       pipe_sampler_view_reference(&pstip->state.sampler_views[i], NULL);
  544.    }
  545.  
  546.    pstip->pipe->delete_sampler_state(pstip->pipe, pstip->sampler_cso);
  547.  
  548.    pipe_resource_reference(&pstip->texture, NULL);
  549.  
  550.    if (pstip->sampler_view) {
  551.       pipe_sampler_view_reference(&pstip->sampler_view, NULL);
  552.    }
  553.  
  554.    draw_free_temp_verts( stage );
  555.    FREE( stage );
  556. }
  557.  
  558.  
  559. /** Create a new polygon stipple drawing stage object */
  560. static struct pstip_stage *
  561. draw_pstip_stage(struct draw_context *draw, struct pipe_context *pipe)
  562. {
  563.    struct pstip_stage *pstip = CALLOC_STRUCT(pstip_stage);
  564.    if (pstip == NULL)
  565.       goto fail;
  566.  
  567.    pstip->pipe = pipe;
  568.  
  569.    pstip->stage.draw = draw;
  570.    pstip->stage.name = "pstip";
  571.    pstip->stage.next = NULL;
  572.    pstip->stage.point = draw_pipe_passthrough_point;
  573.    pstip->stage.line = draw_pipe_passthrough_line;
  574.    pstip->stage.tri = pstip_first_tri;
  575.    pstip->stage.flush = pstip_flush;
  576.    pstip->stage.reset_stipple_counter = pstip_reset_stipple_counter;
  577.    pstip->stage.destroy = pstip_destroy;
  578.  
  579.    if (!draw_alloc_temp_verts( &pstip->stage, 8 ))
  580.       goto fail;
  581.  
  582.    return pstip;
  583.  
  584. fail:
  585.    if (pstip)
  586.       pstip->stage.destroy( &pstip->stage );
  587.  
  588.    return NULL;
  589. }
  590.  
  591.  
  592. static struct pstip_stage *
  593. pstip_stage_from_pipe(struct pipe_context *pipe)
  594. {
  595.    struct draw_context *draw = (struct draw_context *) pipe->draw;
  596.    return pstip_stage(draw->pipeline.pstipple);
  597. }
  598.  
  599.  
  600. /**
  601.  * This function overrides the driver's create_fs_state() function and
  602.  * will typically be called by the state tracker.
  603.  */
  604. static void *
  605. pstip_create_fs_state(struct pipe_context *pipe,
  606.                        const struct pipe_shader_state *fs)
  607. {
  608.    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
  609.    struct pstip_fragment_shader *pstipfs = CALLOC_STRUCT(pstip_fragment_shader);
  610.  
  611.    if (pstipfs) {
  612.       pstipfs->state.tokens = tgsi_dup_tokens(fs->tokens);
  613.  
  614.       /* pass-through */
  615.       pstipfs->driver_fs = pstip->driver_create_fs_state(pstip->pipe, fs);
  616.    }
  617.  
  618.    return pstipfs;
  619. }
  620.  
  621.  
  622. static void
  623. pstip_bind_fs_state(struct pipe_context *pipe, void *fs)
  624. {
  625.    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
  626.    struct pstip_fragment_shader *pstipfs = (struct pstip_fragment_shader *) fs;
  627.    /* save current */
  628.    pstip->fs = pstipfs;
  629.    /* pass-through */
  630.    pstip->driver_bind_fs_state(pstip->pipe,
  631.                                (pstipfs ? pstipfs->driver_fs : NULL));
  632. }
  633.  
  634.  
  635. static void
  636. pstip_delete_fs_state(struct pipe_context *pipe, void *fs)
  637. {
  638.    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
  639.    struct pstip_fragment_shader *pstipfs = (struct pstip_fragment_shader *) fs;
  640.    /* pass-through */
  641.    pstip->driver_delete_fs_state(pstip->pipe, pstipfs->driver_fs);
  642.  
  643.    if (pstipfs->pstip_fs)
  644.       pstip->driver_delete_fs_state(pstip->pipe, pstipfs->pstip_fs);
  645.  
  646.    FREE((void*)pstipfs->state.tokens);
  647.    FREE(pstipfs);
  648. }
  649.  
  650.  
  651. static void
  652. pstip_bind_sampler_states(struct pipe_context *pipe, unsigned shader,
  653.                           unsigned start, unsigned num, void **sampler)
  654. {
  655.    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
  656.    uint i;
  657.  
  658.    assert(start == 0);
  659.  
  660.    if (shader == PIPE_SHADER_FRAGMENT) {
  661.       /* save current */
  662.       memcpy(pstip->state.samplers, sampler, num * sizeof(void *));
  663.       for (i = num; i < PIPE_MAX_SAMPLERS; i++) {
  664.          pstip->state.samplers[i] = NULL;
  665.       }
  666.       pstip->num_samplers = num;
  667.    }
  668.  
  669.    /* pass-through */
  670.    pstip->driver_bind_sampler_states(pstip->pipe, shader, start, num, sampler);
  671. }
  672.  
  673.  
  674. static void
  675. pstip_set_sampler_views(struct pipe_context *pipe,
  676.                         unsigned shader, unsigned start, unsigned num,
  677.                         struct pipe_sampler_view **views)
  678. {
  679.    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
  680.    uint i;
  681.  
  682.    if (shader == PIPE_SHADER_FRAGMENT) {
  683.       /* save current */
  684.       for (i = 0; i < num; i++) {
  685.          pipe_sampler_view_reference(&pstip->state.sampler_views[start + i],
  686.                                      views[i]);
  687.       }
  688.       pstip->num_sampler_views = num;
  689.    }
  690.  
  691.    /* pass-through */
  692.    pstip->driver_set_sampler_views(pstip->pipe, shader, start, num, views);
  693. }
  694.  
  695.  
  696. static void
  697. pstip_set_polygon_stipple(struct pipe_context *pipe,
  698.                           const struct pipe_poly_stipple *stipple)
  699. {
  700.    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
  701.  
  702.    /* save current */
  703.    pstip->state.stipple = stipple;
  704.  
  705.    /* pass-through */
  706.    pstip->driver_set_polygon_stipple(pstip->pipe, stipple);
  707.  
  708.    pstip_update_texture(pstip);
  709. }
  710.  
  711.  
  712. /**
  713.  * Called by drivers that want to install this polygon stipple stage
  714.  * into the draw module's pipeline.  This will not be used if the
  715.  * hardware has native support for polygon stipple.
  716.  */
  717. boolean
  718. draw_install_pstipple_stage(struct draw_context *draw,
  719.                             struct pipe_context *pipe)
  720. {
  721.    struct pstip_stage *pstip;
  722.  
  723.    pipe->draw = (void *) draw;
  724.  
  725.    /*
  726.     * Create / install pgon stipple drawing / prim stage
  727.     */
  728.    pstip = draw_pstip_stage( draw, pipe );
  729.    if (pstip == NULL)
  730.       goto fail;
  731.  
  732.    draw->pipeline.pstipple = &pstip->stage;
  733.  
  734.    /* save original driver functions */
  735.    pstip->driver_create_fs_state = pipe->create_fs_state;
  736.    pstip->driver_bind_fs_state = pipe->bind_fs_state;
  737.    pstip->driver_delete_fs_state = pipe->delete_fs_state;
  738.  
  739.    pstip->driver_bind_sampler_states = pipe->bind_sampler_states;
  740.    pstip->driver_set_sampler_views = pipe->set_sampler_views;
  741.    pstip->driver_set_polygon_stipple = pipe->set_polygon_stipple;
  742.  
  743.    /* create special texture, sampler state */
  744.    if (!pstip_create_texture(pstip))
  745.       goto fail;
  746.  
  747.    if (!pstip_create_sampler(pstip))
  748.       goto fail;
  749.  
  750.    /* override the driver's functions */
  751.    pipe->create_fs_state = pstip_create_fs_state;
  752.    pipe->bind_fs_state = pstip_bind_fs_state;
  753.    pipe->delete_fs_state = pstip_delete_fs_state;
  754.  
  755.    pipe->bind_sampler_states = pstip_bind_sampler_states;
  756.    pipe->set_sampler_views = pstip_set_sampler_views;
  757.    pipe->set_polygon_stipple = pstip_set_polygon_stipple;
  758.  
  759.    return TRUE;
  760.  
  761.  fail:
  762.    if (pstip)
  763.       pstip->stage.destroy( &pstip->stage );
  764.  
  765.    return FALSE;
  766. }
  767.