Home | History | Annotate | Download | only in draw
      1 /**************************************************************************
      2  *
      3  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
      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 TUNGSTEN GRAPHICS 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_SAMPLERS];
     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, void **);
    103 
    104    void (*driver_set_sampler_views)(struct pipe_context *,
    105                                     unsigned,
    106                                     struct pipe_sampler_view **);
    107 
    108    void (*driver_set_polygon_stipple)(struct pipe_context *,
    109                                       const struct pipe_poly_stipple *);
    110 
    111    struct pipe_context *pipe;
    112 };
    113 
    114 
    115 
    116 /**
    117  * Subclass of tgsi_transform_context, used for transforming the
    118  * user's fragment shader to add the extra texture sample and fragment kill
    119  * instructions.
    120  */
    121 struct pstip_transform_context {
    122    struct tgsi_transform_context base;
    123    uint tempsUsed;  /**< bitmask */
    124    int wincoordInput;
    125    int maxInput;
    126    uint samplersUsed;  /**< bitfield of samplers used */
    127    int freeSampler;  /** an available sampler for the pstipple */
    128    int texTemp;  /**< temp registers */
    129    int numImmed;
    130    boolean firstInstruction;
    131 };
    132 
    133 
    134 /**
    135  * TGSI declaration transform callback.
    136  * Look for a free sampler, a free input attrib, and two free temp regs.
    137  */
    138 static void
    139 pstip_transform_decl(struct tgsi_transform_context *ctx,
    140                      struct tgsi_full_declaration *decl)
    141 {
    142    struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
    143 
    144    if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
    145       uint i;
    146       for (i = decl->Range.First;
    147            i <= decl->Range.Last; i++) {
    148          pctx->samplersUsed |= 1 << i;
    149       }
    150    }
    151    else if (decl->Declaration.File == TGSI_FILE_INPUT) {
    152       pctx->maxInput = MAX2(pctx->maxInput, (int) decl->Range.Last);
    153       if (decl->Semantic.Name == TGSI_SEMANTIC_POSITION)
    154          pctx->wincoordInput = (int) decl->Range.First;
    155    }
    156    else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
    157       uint i;
    158       for (i = decl->Range.First;
    159            i <= decl->Range.Last; i++) {
    160          pctx->tempsUsed |= (1 << i);
    161       }
    162    }
    163 
    164    ctx->emit_declaration(ctx, decl);
    165 }
    166 
    167 
    168 /**
    169  * TGSI immediate declaration transform callback.
    170  * We're just counting the number of immediates here.
    171  */
    172 static void
    173 pstip_transform_immed(struct tgsi_transform_context *ctx,
    174                       struct tgsi_full_immediate *immed)
    175 {
    176    struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
    177    ctx->emit_immediate(ctx, immed); /* emit to output shader */
    178    pctx->numImmed++;
    179 }
    180 
    181 
    182 /**
    183  * Find the lowest zero bit in the given word, or -1 if bitfield is all ones.
    184  */
    185 static int
    186 free_bit(uint bitfield)
    187 {
    188    return ffs(~bitfield) - 1;
    189 }
    190 
    191 
    192 /**
    193  * TGSI instruction transform callback.
    194  * Replace writes to result.color w/ a temp reg.
    195  * Upon END instruction, insert texture sampling code for antialiasing.
    196  */
    197 static void
    198 pstip_transform_inst(struct tgsi_transform_context *ctx,
    199                      struct tgsi_full_instruction *inst)
    200 {
    201    struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
    202 
    203    if (pctx->firstInstruction) {
    204       /* emit our new declarations before the first instruction */
    205 
    206       struct tgsi_full_declaration decl;
    207       struct tgsi_full_instruction newInst;
    208       uint i;
    209       int wincoordInput;
    210 
    211       /* find free sampler */
    212       pctx->freeSampler = free_bit(pctx->samplersUsed);
    213       if (pctx->freeSampler >= PIPE_MAX_SAMPLERS)
    214          pctx->freeSampler = PIPE_MAX_SAMPLERS - 1;
    215 
    216       if (pctx->wincoordInput < 0)
    217          wincoordInput = pctx->maxInput + 1;
    218       else
    219          wincoordInput = pctx->wincoordInput;
    220 
    221       /* find one free temp reg */
    222       for (i = 0; i < 32; i++) {
    223          if ((pctx->tempsUsed & (1 << i)) == 0) {
    224             /* found a free temp */
    225             if (pctx->texTemp < 0)
    226                pctx->texTemp  = i;
    227             else
    228                break;
    229          }
    230       }
    231       assert(pctx->texTemp >= 0);
    232 
    233       if (pctx->wincoordInput < 0) {
    234          /* declare new position input reg */
    235          decl = tgsi_default_full_declaration();
    236          decl.Declaration.File = TGSI_FILE_INPUT;
    237          decl.Declaration.Interpolate = 1;
    238          decl.Declaration.Semantic = 1;
    239          decl.Semantic.Name = TGSI_SEMANTIC_POSITION;
    240          decl.Semantic.Index = 0;
    241          decl.Range.First =
    242             decl.Range.Last = wincoordInput;
    243          decl.Interp.Interpolate = TGSI_INTERPOLATE_LINEAR; /* XXX? */
    244          ctx->emit_declaration(ctx, &decl);
    245       }
    246 
    247       /* declare new sampler */
    248       decl = tgsi_default_full_declaration();
    249       decl.Declaration.File = TGSI_FILE_SAMPLER;
    250       decl.Range.First =
    251       decl.Range.Last = pctx->freeSampler;
    252       ctx->emit_declaration(ctx, &decl);
    253 
    254       /* declare new temp regs */
    255       decl = tgsi_default_full_declaration();
    256       decl.Declaration.File = TGSI_FILE_TEMPORARY;
    257       decl.Range.First =
    258       decl.Range.Last = pctx->texTemp;
    259       ctx->emit_declaration(ctx, &decl);
    260 
    261       /* emit immediate = {1/32, 1/32, 1, 1}
    262        * The index/position of this immediate will be pctx->numImmed
    263        */
    264       {
    265          static const float value[4] = { 1.0/32, 1.0/32, 1.0, 1.0 };
    266          struct tgsi_full_immediate immed;
    267          uint size = 4;
    268          immed = tgsi_default_full_immediate();
    269          immed.Immediate.NrTokens = 1 + size; /* one for the token itself */
    270          immed.u[0].Float = value[0];
    271          immed.u[1].Float = value[1];
    272          immed.u[2].Float = value[2];
    273          immed.u[3].Float = value[3];
    274          ctx->emit_immediate(ctx, &immed);
    275       }
    276 
    277       pctx->firstInstruction = FALSE;
    278 
    279 
    280       /*
    281        * Insert new MUL/TEX/KILP instructions at start of program
    282        * Take gl_FragCoord, divide by 32 (stipple size), sample the
    283        * texture and kill fragment if needed.
    284        *
    285        * We'd like to use non-normalized texcoords to index into a RECT
    286        * texture, but we can only use GL_REPEAT wrap mode with normalized
    287        * texcoords.  Darn.
    288        */
    289 
    290       /* MUL texTemp, INPUT[wincoord], 1/32; */
    291       newInst = tgsi_default_full_instruction();
    292       newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
    293       newInst.Instruction.NumDstRegs = 1;
    294       newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
    295       newInst.Dst[0].Register.Index = pctx->texTemp;
    296       newInst.Instruction.NumSrcRegs = 2;
    297       newInst.Src[0].Register.File = TGSI_FILE_INPUT;
    298       newInst.Src[0].Register.Index = wincoordInput;
    299       newInst.Src[1].Register.File = TGSI_FILE_IMMEDIATE;
    300       newInst.Src[1].Register.Index = pctx->numImmed;
    301       ctx->emit_instruction(ctx, &newInst);
    302 
    303       /* TEX texTemp, texTemp, sampler; */
    304       newInst = tgsi_default_full_instruction();
    305       newInst.Instruction.Opcode = TGSI_OPCODE_TEX;
    306       newInst.Instruction.NumDstRegs = 1;
    307       newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
    308       newInst.Dst[0].Register.Index = pctx->texTemp;
    309       newInst.Instruction.NumSrcRegs = 2;
    310       newInst.Instruction.Texture = TRUE;
    311       newInst.Texture.Texture = TGSI_TEXTURE_2D;
    312       newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
    313       newInst.Src[0].Register.Index = pctx->texTemp;
    314       newInst.Src[1].Register.File = TGSI_FILE_SAMPLER;
    315       newInst.Src[1].Register.Index = pctx->freeSampler;
    316       ctx->emit_instruction(ctx, &newInst);
    317 
    318       /* KIL -texTemp;   # if -texTemp < 0, KILL fragment */
    319       newInst = tgsi_default_full_instruction();
    320       newInst.Instruction.Opcode = TGSI_OPCODE_KIL;
    321       newInst.Instruction.NumDstRegs = 0;
    322       newInst.Instruction.NumSrcRegs = 1;
    323       newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
    324       newInst.Src[0].Register.Index = pctx->texTemp;
    325       newInst.Src[0].Register.Negate = 1;
    326       ctx->emit_instruction(ctx, &newInst);
    327    }
    328 
    329    /* emit this instruction */
    330    ctx->emit_instruction(ctx, inst);
    331 }
    332 
    333 
    334 /**
    335  * Generate the frag shader we'll use for doing polygon stipple.
    336  * This will be the user's shader prefixed with a TEX and KIL instruction.
    337  */
    338 static boolean
    339 generate_pstip_fs(struct pstip_stage *pstip)
    340 {
    341    const struct pipe_shader_state *orig_fs = &pstip->fs->state;
    342    /*struct draw_context *draw = pstip->stage.draw;*/
    343    struct pipe_shader_state pstip_fs;
    344    struct pstip_transform_context transform;
    345    const uint newLen = tgsi_num_tokens(orig_fs->tokens) + NUM_NEW_TOKENS;
    346 
    347    pstip_fs = *orig_fs; /* copy to init */
    348    pstip_fs.tokens = tgsi_alloc_tokens(newLen);
    349    if (pstip_fs.tokens == NULL)
    350       return FALSE;
    351 
    352    memset(&transform, 0, sizeof(transform));
    353    transform.wincoordInput = -1;
    354    transform.maxInput = -1;
    355    transform.texTemp = -1;
    356    transform.firstInstruction = TRUE;
    357    transform.base.transform_instruction = pstip_transform_inst;
    358    transform.base.transform_declaration = pstip_transform_decl;
    359    transform.base.transform_immediate = pstip_transform_immed;
    360 
    361    tgsi_transform_shader(orig_fs->tokens,
    362                          (struct tgsi_token *) pstip_fs.tokens,
    363                          newLen, &transform.base);
    364 
    365 #if 0 /* DEBUG */
    366    tgsi_dump(orig_fs->tokens, 0);
    367    tgsi_dump(pstip_fs.tokens, 0);
    368 #endif
    369 
    370    assert(pstip->fs);
    371 
    372    pstip->fs->sampler_unit = transform.freeSampler;
    373    assert(pstip->fs->sampler_unit < PIPE_MAX_SAMPLERS);
    374 
    375    pstip->fs->pstip_fs = pstip->driver_create_fs_state(pstip->pipe, &pstip_fs);
    376 
    377    FREE((void *)pstip_fs.tokens);
    378 
    379    if (!pstip->fs->pstip_fs)
    380       return FALSE;
    381 
    382    return TRUE;
    383 }
    384 
    385 
    386 /**
    387  * Load texture image with current stipple pattern.
    388  */
    389 static void
    390 pstip_update_texture(struct pstip_stage *pstip)
    391 {
    392    static const uint bit31 = 1 << 31;
    393    struct pipe_context *pipe = pstip->pipe;
    394    struct pipe_transfer *transfer;
    395    const uint *stipple = pstip->state.stipple->stipple;
    396    uint i, j;
    397    ubyte *data;
    398 
    399    transfer = pipe_get_transfer(pipe, pstip->texture, 0, 0,
    400                                 PIPE_TRANSFER_WRITE, 0, 0, 32, 32);
    401    data = pipe->transfer_map(pipe, transfer);
    402 
    403    /*
    404     * Load alpha texture.
    405     * Note: 0 means keep the fragment, 255 means kill it.
    406     * We'll negate the texel value and use KILP which kills if value
    407     * is negative.
    408     */
    409    for (i = 0; i < 32; i++) {
    410       for (j = 0; j < 32; j++) {
    411          if (stipple[i] & (bit31 >> j)) {
    412             /* fragment "on" */
    413             data[i * transfer->stride + j] = 0;
    414          }
    415          else {
    416             /* fragment "off" */
    417             data[i * transfer->stride + j] = 255;
    418          }
    419       }
    420    }
    421 
    422    /* unmap */
    423    pipe->transfer_unmap(pipe, transfer);
    424    pipe->transfer_destroy(pipe, transfer);
    425 }
    426 
    427 
    428 /**
    429  * Create the texture map we'll use for stippling.
    430  */
    431 static boolean
    432 pstip_create_texture(struct pstip_stage *pstip)
    433 {
    434    struct pipe_context *pipe = pstip->pipe;
    435    struct pipe_screen *screen = pipe->screen;
    436    struct pipe_resource texTemp;
    437    struct pipe_sampler_view viewTempl;
    438 
    439    memset(&texTemp, 0, sizeof(texTemp));
    440    texTemp.target = PIPE_TEXTURE_2D;
    441    texTemp.format = PIPE_FORMAT_A8_UNORM; /* XXX verify supported by driver! */
    442    texTemp.last_level = 0;
    443    texTemp.width0 = 32;
    444    texTemp.height0 = 32;
    445    texTemp.depth0 = 1;
    446    texTemp.array_size = 1;
    447    texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
    448 
    449    pstip->texture = screen->resource_create(screen, &texTemp);
    450    if (pstip->texture == NULL)
    451       return FALSE;
    452 
    453    u_sampler_view_default_template(&viewTempl,
    454                                    pstip->texture,
    455                                    pstip->texture->format);
    456    pstip->sampler_view = pipe->create_sampler_view(pipe,
    457                                                    pstip->texture,
    458                                                    &viewTempl);
    459    if (!pstip->sampler_view) {
    460       return FALSE;
    461    }
    462 
    463    return TRUE;
    464 }
    465 
    466 
    467 /**
    468  * Create the sampler CSO that'll be used for stippling.
    469  */
    470 static boolean
    471 pstip_create_sampler(struct pstip_stage *pstip)
    472 {
    473    struct pipe_sampler_state sampler;
    474    struct pipe_context *pipe = pstip->pipe;
    475 
    476    memset(&sampler, 0, sizeof(sampler));
    477    sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
    478    sampler.wrap_t = PIPE_TEX_WRAP_REPEAT;
    479    sampler.wrap_r = PIPE_TEX_WRAP_REPEAT;
    480    sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
    481    sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
    482    sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
    483    sampler.normalized_coords = 1;
    484    sampler.min_lod = 0.0f;
    485    sampler.max_lod = 0.0f;
    486 
    487    pstip->sampler_cso = pipe->create_sampler_state(pipe, &sampler);
    488    if (pstip->sampler_cso == NULL)
    489       return FALSE;
    490 
    491    return TRUE;
    492 }
    493 
    494 
    495 /**
    496  * When we're about to draw our first stipple polygon in a batch, this function
    497  * is called to tell the driver to bind our modified fragment shader.
    498  */
    499 static boolean
    500 bind_pstip_fragment_shader(struct pstip_stage *pstip)
    501 {
    502    struct draw_context *draw = pstip->stage.draw;
    503    if (!pstip->fs->pstip_fs &&
    504        !generate_pstip_fs(pstip))
    505       return FALSE;
    506 
    507    draw->suspend_flushing = TRUE;
    508    pstip->driver_bind_fs_state(pstip->pipe, pstip->fs->pstip_fs);
    509    draw->suspend_flushing = FALSE;
    510    return TRUE;
    511 }
    512 
    513 
    514 static INLINE struct pstip_stage *
    515 pstip_stage( struct draw_stage *stage )
    516 {
    517    return (struct pstip_stage *) stage;
    518 }
    519 
    520 
    521 static void
    522 pstip_first_tri(struct draw_stage *stage, struct prim_header *header)
    523 {
    524    struct pstip_stage *pstip = pstip_stage(stage);
    525    struct pipe_context *pipe = pstip->pipe;
    526    struct draw_context *draw = stage->draw;
    527    uint num_samplers;
    528 
    529    assert(stage->draw->rasterizer->poly_stipple_enable);
    530 
    531    /* bind our fragprog */
    532    if (!bind_pstip_fragment_shader(pstip)) {
    533       stage->tri = draw_pipe_passthrough_tri;
    534       stage->tri(stage, header);
    535       return;
    536    }
    537 
    538 
    539    /* how many samplers? */
    540    /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */
    541    num_samplers = MAX2(pstip->num_sampler_views, pstip->num_samplers);
    542    num_samplers = MAX2(num_samplers, pstip->fs->sampler_unit + 1);
    543 
    544    /* plug in our sampler, texture */
    545    pstip->state.samplers[pstip->fs->sampler_unit] = pstip->sampler_cso;
    546    pipe_sampler_view_reference(&pstip->state.sampler_views[pstip->fs->sampler_unit],
    547                                pstip->sampler_view);
    548 
    549    assert(num_samplers <= PIPE_MAX_SAMPLERS);
    550 
    551    draw->suspend_flushing = TRUE;
    552    pstip->driver_bind_sampler_states(pipe, num_samplers, pstip->state.samplers);
    553    pstip->driver_set_sampler_views(pipe, num_samplers, pstip->state.sampler_views);
    554    draw->suspend_flushing = FALSE;
    555 
    556    /* now really draw first triangle */
    557    stage->tri = draw_pipe_passthrough_tri;
    558    stage->tri(stage, header);
    559 }
    560 
    561 
    562 static void
    563 pstip_flush(struct draw_stage *stage, unsigned flags)
    564 {
    565    struct draw_context *draw = stage->draw;
    566    struct pstip_stage *pstip = pstip_stage(stage);
    567    struct pipe_context *pipe = pstip->pipe;
    568 
    569    stage->tri = pstip_first_tri;
    570    stage->next->flush( stage->next, flags );
    571 
    572    /* restore original frag shader, texture, sampler state */
    573    draw->suspend_flushing = TRUE;
    574    pstip->driver_bind_fs_state(pipe, pstip->fs ? pstip->fs->driver_fs : NULL);
    575    pstip->driver_bind_sampler_states(pipe, pstip->num_samplers,
    576                                      pstip->state.samplers);
    577    pstip->driver_set_sampler_views(pipe,
    578                                    pstip->num_sampler_views,
    579                                    pstip->state.sampler_views);
    580    draw->suspend_flushing = FALSE;
    581 }
    582 
    583 
    584 static void
    585 pstip_reset_stipple_counter(struct draw_stage *stage)
    586 {
    587    stage->next->reset_stipple_counter( stage->next );
    588 }
    589 
    590 
    591 static void
    592 pstip_destroy(struct draw_stage *stage)
    593 {
    594    struct pstip_stage *pstip = pstip_stage(stage);
    595    uint i;
    596 
    597    for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
    598       pipe_sampler_view_reference(&pstip->state.sampler_views[i], NULL);
    599    }
    600 
    601    pstip->pipe->delete_sampler_state(pstip->pipe, pstip->sampler_cso);
    602 
    603    pipe_resource_reference(&pstip->texture, NULL);
    604 
    605    if (pstip->sampler_view) {
    606       pipe_sampler_view_reference(&pstip->sampler_view, NULL);
    607    }
    608 
    609    draw_free_temp_verts( stage );
    610    FREE( stage );
    611 }
    612 
    613 
    614 /** Create a new polygon stipple drawing stage object */
    615 static struct pstip_stage *
    616 draw_pstip_stage(struct draw_context *draw, struct pipe_context *pipe)
    617 {
    618    struct pstip_stage *pstip = CALLOC_STRUCT(pstip_stage);
    619    if (pstip == NULL)
    620       goto fail;
    621 
    622    pstip->pipe = pipe;
    623 
    624    pstip->stage.draw = draw;
    625    pstip->stage.name = "pstip";
    626    pstip->stage.next = NULL;
    627    pstip->stage.point = draw_pipe_passthrough_point;
    628    pstip->stage.line = draw_pipe_passthrough_line;
    629    pstip->stage.tri = pstip_first_tri;
    630    pstip->stage.flush = pstip_flush;
    631    pstip->stage.reset_stipple_counter = pstip_reset_stipple_counter;
    632    pstip->stage.destroy = pstip_destroy;
    633 
    634    if (!draw_alloc_temp_verts( &pstip->stage, 8 ))
    635       goto fail;
    636 
    637    return pstip;
    638 
    639 fail:
    640    if (pstip)
    641       pstip->stage.destroy( &pstip->stage );
    642 
    643    return NULL;
    644 }
    645 
    646 
    647 static struct pstip_stage *
    648 pstip_stage_from_pipe(struct pipe_context *pipe)
    649 {
    650    struct draw_context *draw = (struct draw_context *) pipe->draw;
    651    return pstip_stage(draw->pipeline.pstipple);
    652 }
    653 
    654 
    655 /**
    656  * This function overrides the driver's create_fs_state() function and
    657  * will typically be called by the state tracker.
    658  */
    659 static void *
    660 pstip_create_fs_state(struct pipe_context *pipe,
    661                        const struct pipe_shader_state *fs)
    662 {
    663    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
    664    struct pstip_fragment_shader *pstipfs = CALLOC_STRUCT(pstip_fragment_shader);
    665 
    666    if (pstipfs) {
    667       pstipfs->state = *fs;
    668 
    669       /* pass-through */
    670       pstipfs->driver_fs = pstip->driver_create_fs_state(pstip->pipe, fs);
    671    }
    672 
    673    return pstipfs;
    674 }
    675 
    676 
    677 static void
    678 pstip_bind_fs_state(struct pipe_context *pipe, void *fs)
    679 {
    680    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
    681    struct pstip_fragment_shader *pstipfs = (struct pstip_fragment_shader *) fs;
    682    /* save current */
    683    pstip->fs = pstipfs;
    684    /* pass-through */
    685    pstip->driver_bind_fs_state(pstip->pipe,
    686                                (pstipfs ? pstipfs->driver_fs : NULL));
    687 }
    688 
    689 
    690 static void
    691 pstip_delete_fs_state(struct pipe_context *pipe, void *fs)
    692 {
    693    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
    694    struct pstip_fragment_shader *pstipfs = (struct pstip_fragment_shader *) fs;
    695    /* pass-through */
    696    pstip->driver_delete_fs_state(pstip->pipe, pstipfs->driver_fs);
    697 
    698    if (pstipfs->pstip_fs)
    699       pstip->driver_delete_fs_state(pstip->pipe, pstipfs->pstip_fs);
    700 
    701    FREE(pstipfs);
    702 }
    703 
    704 
    705 static void
    706 pstip_bind_sampler_states(struct pipe_context *pipe,
    707                           unsigned num, void **sampler)
    708 {
    709    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
    710    uint i;
    711 
    712    /* save current */
    713    memcpy(pstip->state.samplers, sampler, num * sizeof(void *));
    714    for (i = num; i < PIPE_MAX_SAMPLERS; i++) {
    715       pstip->state.samplers[i] = NULL;
    716    }
    717 
    718    pstip->num_samplers = num;
    719    /* pass-through */
    720    pstip->driver_bind_sampler_states(pstip->pipe, num, sampler);
    721 }
    722 
    723 
    724 static void
    725 pstip_set_sampler_views(struct pipe_context *pipe,
    726                         unsigned num,
    727                         struct pipe_sampler_view **views)
    728 {
    729    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
    730    uint i;
    731 
    732    /* save current */
    733    for (i = 0; i < num; i++) {
    734       pipe_sampler_view_reference(&pstip->state.sampler_views[i], views[i]);
    735    }
    736    for (; i < PIPE_MAX_SAMPLERS; i++) {
    737       pipe_sampler_view_reference(&pstip->state.sampler_views[i], NULL);
    738    }
    739 
    740    pstip->num_sampler_views = num;
    741 
    742    /* pass-through */
    743    pstip->driver_set_sampler_views(pstip->pipe, num, views);
    744 }
    745 
    746 
    747 static void
    748 pstip_set_polygon_stipple(struct pipe_context *pipe,
    749                           const struct pipe_poly_stipple *stipple)
    750 {
    751    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
    752 
    753    /* save current */
    754    pstip->state.stipple = stipple;
    755 
    756    /* pass-through */
    757    pstip->driver_set_polygon_stipple(pstip->pipe, stipple);
    758 
    759    pstip_update_texture(pstip);
    760 }
    761 
    762 
    763 /**
    764  * Called by drivers that want to install this polygon stipple stage
    765  * into the draw module's pipeline.  This will not be used if the
    766  * hardware has native support for polygon stipple.
    767  */
    768 boolean
    769 draw_install_pstipple_stage(struct draw_context *draw,
    770                             struct pipe_context *pipe)
    771 {
    772    struct pstip_stage *pstip;
    773 
    774    pipe->draw = (void *) draw;
    775 
    776    /*
    777     * Create / install pgon stipple drawing / prim stage
    778     */
    779    pstip = draw_pstip_stage( draw, pipe );
    780    if (pstip == NULL)
    781       goto fail;
    782 
    783    draw->pipeline.pstipple = &pstip->stage;
    784 
    785    /* create special texture, sampler state */
    786    if (!pstip_create_texture(pstip))
    787       goto fail;
    788 
    789    if (!pstip_create_sampler(pstip))
    790       goto fail;
    791 
    792    /* save original driver functions */
    793    pstip->driver_create_fs_state = pipe->create_fs_state;
    794    pstip->driver_bind_fs_state = pipe->bind_fs_state;
    795    pstip->driver_delete_fs_state = pipe->delete_fs_state;
    796 
    797    pstip->driver_bind_sampler_states = pipe->bind_fragment_sampler_states;
    798    pstip->driver_set_sampler_views = pipe->set_fragment_sampler_views;
    799    pstip->driver_set_polygon_stipple = pipe->set_polygon_stipple;
    800 
    801    /* override the driver's functions */
    802    pipe->create_fs_state = pstip_create_fs_state;
    803    pipe->bind_fs_state = pstip_bind_fs_state;
    804    pipe->delete_fs_state = pstip_delete_fs_state;
    805 
    806    pipe->bind_fragment_sampler_states = pstip_bind_sampler_states;
    807    pipe->set_fragment_sampler_views = pstip_set_sampler_views;
    808    pipe->set_polygon_stipple = pstip_set_polygon_stipple;
    809 
    810    return TRUE;
    811 
    812  fail:
    813    if (pstip)
    814       pstip->stage.destroy( &pstip->stage );
    815 
    816    return FALSE;
    817 }
    818