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.  * AA point stage:  AA points are converted to quads and rendered with a
  30.  * special fragment shader.  Another approach would be to use a texture
  31.  * map image of a point, but experiments indicate the quality isn't nearly
  32.  * as good as this approach.
  33.  *
  34.  * Note: this looks a lot like draw_aaline.c but there's actually little
  35.  * if any code that can be shared.
  36.  *
  37.  * Authors:  Brian Paul
  38.  */
  39.  
  40.  
  41. #include "pipe/p_context.h"
  42. #include "pipe/p_defines.h"
  43. #include "pipe/p_shader_tokens.h"
  44.  
  45. #include "tgsi/tgsi_transform.h"
  46. #include "tgsi/tgsi_dump.h"
  47.  
  48. #include "util/u_math.h"
  49. #include "util/u_memory.h"
  50.  
  51. #include "draw_context.h"
  52. #include "draw_vs.h"
  53. #include "draw_pipe.h"
  54.  
  55.  
  56. /** Approx number of new tokens for instructions in aa_transform_inst() */
  57. #define NUM_NEW_TOKENS 200
  58.  
  59.  
  60. /*
  61.  * Enabling NORMALIZE might give _slightly_ better results.
  62.  * Basically, it controls whether we compute distance as d=sqrt(x*x+y*y) or
  63.  * d=x*x+y*y.  Since we're working with a unit circle, the later seems
  64.  * close enough and saves some costly instructions.
  65.  */
  66. #define NORMALIZE 0
  67.  
  68.  
  69. /**
  70.  * Subclass of pipe_shader_state to carry extra fragment shader info.
  71.  */
  72. struct aapoint_fragment_shader
  73. {
  74.    struct pipe_shader_state state;
  75.    void *driver_fs;   /**< the regular shader */
  76.    void *aapoint_fs;  /**< the aa point-augmented shader */
  77.    int generic_attrib; /**< The generic input attrib/texcoord we'll use */
  78. };
  79.  
  80.  
  81. /**
  82.  * Subclass of draw_stage
  83.  */
  84. struct aapoint_stage
  85. {
  86.    struct draw_stage stage;
  87.  
  88.    /** half of pipe_rasterizer_state::point_size */
  89.    float radius;
  90.  
  91.    /** vertex attrib slot containing point size */
  92.    int psize_slot;
  93.  
  94.    /** this is the vertex attrib slot for the new texcoords */
  95.    uint tex_slot;
  96.  
  97.    /** vertex attrib slot containing position */
  98.    uint pos_slot;
  99.  
  100.    /** Currently bound fragment shader */
  101.    struct aapoint_fragment_shader *fs;
  102.  
  103.    /*
  104.     * Driver interface/override functions
  105.     */
  106.    void * (*driver_create_fs_state)(struct pipe_context *,
  107.                                     const struct pipe_shader_state *);
  108.    void (*driver_bind_fs_state)(struct pipe_context *, void *);
  109.    void (*driver_delete_fs_state)(struct pipe_context *, void *);
  110. };
  111.  
  112.  
  113.  
  114. /**
  115.  * Subclass of tgsi_transform_context, used for transforming the
  116.  * user's fragment shader to add the special AA instructions.
  117.  */
  118. struct aa_transform_context {
  119.    struct tgsi_transform_context base;
  120.    uint tempsUsed;  /**< bitmask */
  121.    int colorOutput; /**< which output is the primary color */
  122.    int maxInput, maxGeneric;  /**< max input index found */
  123.    int tmp0, colorTemp;  /**< temp registers */
  124. };
  125.  
  126.  
  127. /**
  128.  * TGSI declaration transform callback.
  129.  * Look for two free temp regs and available input reg for new texcoords.
  130.  */
  131. static void
  132. aa_transform_decl(struct tgsi_transform_context *ctx,
  133.                   struct tgsi_full_declaration *decl)
  134. {
  135.    struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
  136.  
  137.    if (decl->Declaration.File == TGSI_FILE_OUTPUT &&
  138.        decl->Semantic.Name == TGSI_SEMANTIC_COLOR &&
  139.        decl->Semantic.Index == 0) {
  140.       aactx->colorOutput = decl->Range.First;
  141.    }
  142.    else if (decl->Declaration.File == TGSI_FILE_INPUT) {
  143.       if ((int) decl->Range.Last > aactx->maxInput)
  144.          aactx->maxInput = decl->Range.Last;
  145.       if (decl->Semantic.Name == TGSI_SEMANTIC_GENERIC &&
  146.            (int) decl->Semantic.Index > aactx->maxGeneric) {
  147.          aactx->maxGeneric = decl->Semantic.Index;
  148.       }
  149.    }
  150.    else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
  151.       uint i;
  152.       for (i = decl->Range.First;
  153.            i <= decl->Range.Last; i++) {
  154.          aactx->tempsUsed |= (1 << i);
  155.       }
  156.    }
  157.  
  158.    ctx->emit_declaration(ctx, decl);
  159. }
  160.  
  161.  
  162. /**
  163.  * TGSI transform callback.
  164.  * Insert new declarations and instructions before first instruction.
  165.  */
  166. static void
  167. aa_transform_prolog(struct tgsi_transform_context *ctx)
  168. {
  169.    /* emit our new declarations before the first instruction */
  170.    struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
  171.    struct tgsi_full_instruction newInst;
  172.    const int texInput = aactx->maxInput + 1;
  173.    int tmp0;
  174.    uint i;
  175.  
  176.    /* find two free temp regs */
  177.    for (i = 0; i < 32; i++) {
  178.       if ((aactx->tempsUsed & (1 << i)) == 0) {
  179.          /* found a free temp */
  180.          if (aactx->tmp0 < 0)
  181.             aactx->tmp0 = i;
  182.          else if (aactx->colorTemp < 0)
  183.             aactx->colorTemp = i;
  184.          else
  185.             break;
  186.       }
  187.    }
  188.  
  189.    assert(aactx->colorTemp != aactx->tmp0);
  190.  
  191.    tmp0 = aactx->tmp0;
  192.  
  193.    /* declare new generic input/texcoord */
  194.    tgsi_transform_input_decl(ctx, texInput,
  195.                              TGSI_SEMANTIC_GENERIC, aactx->maxGeneric + 1,
  196.                              TGSI_INTERPOLATE_LINEAR);
  197.  
  198.    /* declare new temp regs */
  199.    tgsi_transform_temp_decl(ctx, tmp0);
  200.    tgsi_transform_temp_decl(ctx, aactx->colorTemp);
  201.  
  202.    /*
  203.     * Emit code to compute fragment coverage, kill if outside point radius
  204.     *
  205.     * Temp reg0 usage:
  206.     *  t0.x = distance of fragment from center point
  207.     *  t0.y = boolean, is t0.x > 1.0, also misc temp usage
  208.     *  t0.z = temporary for computing 1/(1-k) value
  209.     *  t0.w = final coverage value
  210.     */
  211.  
  212.    /* MUL t0.xy, tex, tex;  # compute x^2, y^2 */
  213.    tgsi_transform_op2_inst(ctx, TGSI_OPCODE_MUL,
  214.                            TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_XY,
  215.                            TGSI_FILE_INPUT, texInput,
  216.                            TGSI_FILE_INPUT, texInput);
  217.  
  218.    /* ADD t0.x, t0.x, t0.y;  # x^2 + y^2 */
  219.    tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_ADD,
  220.                                TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_X,
  221.                                TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_X,
  222.                                TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_Y);
  223.  
  224. #if NORMALIZE  /* OPTIONAL normalization of length */
  225.    /* RSQ t0.x, t0.x; */
  226.    tgsi_transform_op1_inst(ctx, TGSI_OPCODE_RSQ,
  227.                            TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_X,
  228.                            TGSI_FILE_TEMPORARY, tmp0);
  229.  
  230.    /* RCP t0.x, t0.x; */
  231.    tgsi_transform_op1_inst(ctx, TGSI_OPCODE_RCP,
  232.                            TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_X,
  233.                            TGSI_FILE_TEMPORARY, tmp0);
  234. #endif
  235.  
  236.    /* SGT t0.y, t0.xxxx, tex.wwww;  # bool b = d > 1 (NOTE tex.w == 1) */
  237.    tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_SGT,
  238.                                TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_Y,
  239.                                TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_X,
  240.                                TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_W);
  241.  
  242.    /* KILL_IF -tmp0.yyyy;   # if -tmp0.y < 0, KILL */
  243.    tgsi_transform_kill_inst(ctx, TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_Y);
  244.  
  245.    /* compute coverage factor = (1-d)/(1-k) */
  246.  
  247.    /* SUB t0.z, tex.w, tex.z;  # m = 1 - k */
  248.    tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_SUB,
  249.                                TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_Z,
  250.                                TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_W,
  251.                                TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_Z);
  252.  
  253.    /* RCP t0.z, t0.z;  # t0.z = 1 / m */
  254.    newInst = tgsi_default_full_instruction();
  255.    newInst.Instruction.Opcode = TGSI_OPCODE_RCP;
  256.    newInst.Instruction.NumDstRegs = 1;
  257.    newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
  258.    newInst.Dst[0].Register.Index = tmp0;
  259.    newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_Z;
  260.    newInst.Instruction.NumSrcRegs = 1;
  261.    newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
  262.    newInst.Src[0].Register.Index = tmp0;
  263.    newInst.Src[0].Register.SwizzleX = TGSI_SWIZZLE_Z;
  264.    ctx->emit_instruction(ctx, &newInst);
  265.  
  266.    /* SUB t0.y, 1, t0.x;  # d = 1 - d */
  267.    tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_SUB,
  268.                                TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_Y,
  269.                                TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_W,
  270.                                TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_X);
  271.  
  272.    /* MUL t0.w, t0.y, t0.z;   # coverage = d * m */
  273.    tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_MUL,
  274.                                TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_W,
  275.                                TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_Y,
  276.                                TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_Z);
  277.  
  278.    /* SLE t0.y, t0.x, tex.z;  # bool b = distance <= k */
  279.    tgsi_transform_op2_swz_inst(ctx, TGSI_OPCODE_SLE,
  280.                                TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_Y,
  281.                                TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_X,
  282.                                TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_Z);
  283.  
  284.    /* CMP t0.w, -t0.y, tex.w, t0.w;
  285.     *  # if -t0.y < 0 then
  286.     *       t0.w = 1
  287.     *    else
  288.     *       t0.w = t0.w
  289.     */
  290.    tgsi_transform_op3_swz_inst(ctx, TGSI_OPCODE_CMP,
  291.                                TGSI_FILE_TEMPORARY, tmp0, TGSI_WRITEMASK_W,
  292.                                TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_Y, 1,
  293.                                TGSI_FILE_INPUT, texInput, TGSI_SWIZZLE_W,
  294.                                TGSI_FILE_TEMPORARY, tmp0, TGSI_SWIZZLE_W);
  295. }
  296.  
  297.  
  298. /**
  299.  * TGSI transform callback.
  300.  * Insert new instructions before the END instruction.
  301.  */
  302. static void
  303. aa_transform_epilog(struct tgsi_transform_context *ctx)
  304. {
  305.    struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
  306.  
  307.    /* add alpha modulation code at tail of program */
  308.  
  309.    /* MOV result.color.xyz, colorTemp; */
  310.    tgsi_transform_op1_inst(ctx, TGSI_OPCODE_MOV,
  311.                            TGSI_FILE_OUTPUT, aactx->colorOutput,
  312.                            TGSI_WRITEMASK_XYZ,
  313.                            TGSI_FILE_TEMPORARY, aactx->colorTemp);
  314.  
  315.    /* MUL result.color.w, colorTemp, tmp0.w; */
  316.    tgsi_transform_op2_inst(ctx, TGSI_OPCODE_MUL,
  317.                            TGSI_FILE_OUTPUT, aactx->colorOutput,
  318.                            TGSI_WRITEMASK_W,
  319.                            TGSI_FILE_TEMPORARY, aactx->colorTemp,
  320.                            TGSI_FILE_TEMPORARY, aactx->tmp0);
  321. }
  322.  
  323.  
  324. /**
  325.  * TGSI transform callback.
  326.  * Called per instruction.
  327.  * Replace writes to result.color w/ a temp reg.
  328.  */
  329. static void
  330. aa_transform_inst(struct tgsi_transform_context *ctx,
  331.                   struct tgsi_full_instruction *inst)
  332. {
  333.    struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
  334.    unsigned i;
  335.  
  336.    /* Not an END instruction.
  337.     * Look for writes to result.color and replace with colorTemp reg.
  338.     */
  339.    for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
  340.       struct tgsi_full_dst_register *dst = &inst->Dst[i];
  341.       if (dst->Register.File == TGSI_FILE_OUTPUT &&
  342.           dst->Register.Index == aactx->colorOutput) {
  343.          dst->Register.File = TGSI_FILE_TEMPORARY;
  344.          dst->Register.Index = aactx->colorTemp;
  345.       }
  346.    }
  347.  
  348.    ctx->emit_instruction(ctx, inst);
  349. }
  350.  
  351.  
  352. /**
  353.  * Generate the frag shader we'll use for drawing AA points.
  354.  * This will be the user's shader plus some texture/modulate instructions.
  355.  */
  356. static boolean
  357. generate_aapoint_fs(struct aapoint_stage *aapoint)
  358. {
  359.    const struct pipe_shader_state *orig_fs = &aapoint->fs->state;
  360.    struct pipe_shader_state aapoint_fs;
  361.    struct aa_transform_context transform;
  362.    const uint newLen = tgsi_num_tokens(orig_fs->tokens) + NUM_NEW_TOKENS;
  363.    struct pipe_context *pipe = aapoint->stage.draw->pipe;
  364.  
  365.    aapoint_fs = *orig_fs; /* copy to init */
  366.    aapoint_fs.tokens = tgsi_alloc_tokens(newLen);
  367.    if (aapoint_fs.tokens == NULL)
  368.       return FALSE;
  369.  
  370.    memset(&transform, 0, sizeof(transform));
  371.    transform.colorOutput = -1;
  372.    transform.maxInput = -1;
  373.    transform.maxGeneric = -1;
  374.    transform.colorTemp = -1;
  375.    transform.tmp0 = -1;
  376.    transform.base.prolog = aa_transform_prolog;
  377.    transform.base.epilog = aa_transform_epilog;
  378.    transform.base.transform_instruction = aa_transform_inst;
  379.    transform.base.transform_declaration = aa_transform_decl;
  380.  
  381.    tgsi_transform_shader(orig_fs->tokens,
  382.                          (struct tgsi_token *) aapoint_fs.tokens,
  383.                          newLen, &transform.base);
  384.  
  385. #if 0 /* DEBUG */
  386.    debug_printf("draw_aapoint, orig shader:\n");
  387.    tgsi_dump(orig_fs->tokens, 0);
  388.    debug_printf("draw_aapoint, new shader:\n");
  389.    tgsi_dump(aapoint_fs.tokens, 0);
  390. #endif
  391.  
  392.    aapoint->fs->aapoint_fs
  393.       = aapoint->driver_create_fs_state(pipe, &aapoint_fs);
  394.    if (aapoint->fs->aapoint_fs == NULL)
  395.       goto fail;
  396.  
  397.    aapoint->fs->generic_attrib = transform.maxGeneric + 1;
  398.    FREE((void *)aapoint_fs.tokens);
  399.    return TRUE;
  400.  
  401. fail:
  402.    FREE((void *)aapoint_fs.tokens);
  403.    return FALSE;
  404. }
  405.  
  406.  
  407. /**
  408.  * When we're about to draw our first AA point in a batch, this function is
  409.  * called to tell the driver to bind our modified fragment shader.
  410.  */
  411. static boolean
  412. bind_aapoint_fragment_shader(struct aapoint_stage *aapoint)
  413. {
  414.    struct draw_context *draw = aapoint->stage.draw;
  415.    struct pipe_context *pipe = draw->pipe;
  416.  
  417.    if (!aapoint->fs->aapoint_fs &&
  418.        !generate_aapoint_fs(aapoint))
  419.       return FALSE;
  420.  
  421.    draw->suspend_flushing = TRUE;
  422.    aapoint->driver_bind_fs_state(pipe, aapoint->fs->aapoint_fs);
  423.    draw->suspend_flushing = FALSE;
  424.  
  425.    return TRUE;
  426. }
  427.  
  428.  
  429.  
  430. static INLINE struct aapoint_stage *
  431. aapoint_stage( struct draw_stage *stage )
  432. {
  433.    return (struct aapoint_stage *) stage;
  434. }
  435.  
  436.  
  437.  
  438.  
  439. /**
  440.  * Draw an AA point by drawing a quad.
  441.  */
  442. static void
  443. aapoint_point(struct draw_stage *stage, struct prim_header *header)
  444. {
  445.    const struct aapoint_stage *aapoint = aapoint_stage(stage);
  446.    struct prim_header tri;
  447.    struct vertex_header *v[4];
  448.    const uint tex_slot = aapoint->tex_slot;
  449.    const uint pos_slot = aapoint->pos_slot;
  450.    float radius, *pos, *tex;
  451.    uint i;
  452.    float k;
  453.  
  454.    if (aapoint->psize_slot >= 0) {
  455.       radius = 0.5f * header->v[0]->data[aapoint->psize_slot][0];
  456.    }
  457.    else {
  458.       radius = aapoint->radius;
  459.    }
  460.  
  461.    /*
  462.     * Note: the texcoords (generic attrib, really) we use are special:
  463.     * The S and T components simply vary from -1 to +1.
  464.     * The R component is k, below.
  465.     * The Q component is 1.0 and will used as a handy constant in the
  466.     * fragment shader.
  467.     */
  468.  
  469.    /*
  470.     * k is the threshold distance from the point's center at which
  471.     * we begin alpha attenuation (the coverage value).
  472.     * Operating within a unit circle, we'll compute the fragment's
  473.     * distance 'd' from the center point using the texcoords.
  474.     * IF d > 1.0 THEN
  475.     *    KILL fragment
  476.     * ELSE IF d > k THEN
  477.     *    compute coverage in [0,1] proportional to d in [k, 1].
  478.     * ELSE
  479.     *    coverage = 1.0;  // full coverage
  480.     * ENDIF
  481.     *
  482.     * Note: the ELSEIF and ELSE clauses are actually implemented with CMP to
  483.     * avoid using IF/ELSE/ENDIF TGSI opcodes.
  484.     */
  485.  
  486. #if !NORMALIZE
  487.    k = 1.0f / radius;
  488.    k = 1.0f - 2.0f * k + k * k;
  489. #else
  490.    k = 1.0f - 1.0f / radius;
  491. #endif
  492.  
  493.    /* allocate/dup new verts */
  494.    for (i = 0; i < 4; i++) {
  495.       v[i] = dup_vert(stage, header->v[0], i);
  496.    }
  497.  
  498.    /* new verts */
  499.    pos = v[0]->data[pos_slot];
  500.    pos[0] -= radius;
  501.    pos[1] -= radius;
  502.  
  503.    pos = v[1]->data[pos_slot];
  504.    pos[0] += radius;
  505.    pos[1] -= radius;
  506.  
  507.    pos = v[2]->data[pos_slot];
  508.    pos[0] += radius;
  509.    pos[1] += radius;
  510.  
  511.    pos = v[3]->data[pos_slot];
  512.    pos[0] -= radius;
  513.    pos[1] += radius;
  514.  
  515.    /* new texcoords */
  516.    tex = v[0]->data[tex_slot];
  517.    ASSIGN_4V(tex, -1, -1, k, 1);
  518.  
  519.    tex = v[1]->data[tex_slot];
  520.    ASSIGN_4V(tex,  1, -1, k, 1);
  521.  
  522.    tex = v[2]->data[tex_slot];
  523.    ASSIGN_4V(tex,  1,  1, k, 1);
  524.  
  525.    tex = v[3]->data[tex_slot];
  526.    ASSIGN_4V(tex, -1,  1, k, 1);
  527.  
  528.    /* emit 2 tris for the quad strip */
  529.    tri.v[0] = v[0];
  530.    tri.v[1] = v[1];
  531.    tri.v[2] = v[2];
  532.    stage->next->tri( stage->next, &tri );
  533.  
  534.    tri.v[0] = v[0];
  535.    tri.v[1] = v[2];
  536.    tri.v[2] = v[3];
  537.    stage->next->tri( stage->next, &tri );
  538. }
  539.  
  540.  
  541. static void
  542. aapoint_first_point(struct draw_stage *stage, struct prim_header *header)
  543. {
  544.    auto struct aapoint_stage *aapoint = aapoint_stage(stage);
  545.    struct draw_context *draw = stage->draw;
  546.    struct pipe_context *pipe = draw->pipe;
  547.    const struct pipe_rasterizer_state *rast = draw->rasterizer;
  548.    void *r;
  549.  
  550.    assert(draw->rasterizer->point_smooth);
  551.  
  552.    if (draw->rasterizer->point_size <= 2.0)
  553.       aapoint->radius = 1.0;
  554.    else
  555.       aapoint->radius = 0.5f * draw->rasterizer->point_size;
  556.  
  557.    /*
  558.     * Bind (generate) our fragprog.
  559.     */
  560.    bind_aapoint_fragment_shader(aapoint);
  561.  
  562.    draw_aapoint_prepare_outputs(draw, draw->pipeline.aapoint);
  563.  
  564.    draw->suspend_flushing = TRUE;
  565.  
  566.    /* Disable triangle culling, stippling, unfilled mode etc. */
  567.    r = draw_get_rasterizer_no_cull(draw, rast->scissor, rast->flatshade);
  568.    pipe->bind_rasterizer_state(pipe, r);
  569.  
  570.    draw->suspend_flushing = FALSE;
  571.  
  572.    /* now really draw first point */
  573.    stage->point = aapoint_point;
  574.    stage->point(stage, header);
  575. }
  576.  
  577.  
  578. static void
  579. aapoint_flush(struct draw_stage *stage, unsigned flags)
  580. {
  581.    struct draw_context *draw = stage->draw;
  582.    struct aapoint_stage *aapoint = aapoint_stage(stage);
  583.    struct pipe_context *pipe = draw->pipe;
  584.  
  585.    stage->point = aapoint_first_point;
  586.    stage->next->flush( stage->next, flags );
  587.  
  588.    /* restore original frag shader */
  589.    draw->suspend_flushing = TRUE;
  590.    aapoint->driver_bind_fs_state(pipe, aapoint->fs ? aapoint->fs->driver_fs : NULL);
  591.  
  592.    /* restore original rasterizer state */
  593.    if (draw->rast_handle) {
  594.       pipe->bind_rasterizer_state(pipe, draw->rast_handle);
  595.    }
  596.  
  597.    draw->suspend_flushing = FALSE;
  598.  
  599.    draw_remove_extra_vertex_attribs(draw);
  600. }
  601.  
  602.  
  603. static void
  604. aapoint_reset_stipple_counter(struct draw_stage *stage)
  605. {
  606.    stage->next->reset_stipple_counter( stage->next );
  607. }
  608.  
  609.  
  610. static void
  611. aapoint_destroy(struct draw_stage *stage)
  612. {
  613.    struct aapoint_stage* aapoint = aapoint_stage(stage);
  614.    struct pipe_context *pipe = stage->draw->pipe;
  615.  
  616.    draw_free_temp_verts( stage );
  617.  
  618.    /* restore the old entry points */
  619.    pipe->create_fs_state = aapoint->driver_create_fs_state;
  620.    pipe->bind_fs_state = aapoint->driver_bind_fs_state;
  621.    pipe->delete_fs_state = aapoint->driver_delete_fs_state;
  622.  
  623.    FREE( stage );
  624. }
  625.  
  626. void
  627. draw_aapoint_prepare_outputs(struct draw_context *draw,
  628.                              struct draw_stage *stage)
  629. {
  630.    struct aapoint_stage *aapoint = aapoint_stage(stage);
  631.    const struct pipe_rasterizer_state *rast = draw->rasterizer;
  632.  
  633.    /* update vertex attrib info */
  634.    aapoint->pos_slot = draw_current_shader_position_output(draw);
  635.  
  636.    if (!rast->point_smooth)
  637.       return;
  638.  
  639.    /* allocate the extra post-transformed vertex attribute */
  640.    aapoint->tex_slot = draw_alloc_extra_vertex_attrib(draw,
  641.                                                       TGSI_SEMANTIC_GENERIC,
  642.                                                       aapoint->fs->generic_attrib);
  643.    assert(aapoint->tex_slot > 0); /* output[0] is vertex pos */
  644.  
  645.    /* find psize slot in post-transform vertex */
  646.    aapoint->psize_slot = -1;
  647.    if (draw->rasterizer->point_size_per_vertex) {
  648.       const struct tgsi_shader_info *info = draw_get_shader_info(draw);
  649.       uint i;
  650.       /* find PSIZ vertex output */
  651.       for (i = 0; i < info->num_outputs; i++) {
  652.          if (info->output_semantic_name[i] == TGSI_SEMANTIC_PSIZE) {
  653.             aapoint->psize_slot = i;
  654.             break;
  655.          }
  656.       }
  657.    }
  658. }
  659.  
  660. static struct aapoint_stage *
  661. draw_aapoint_stage(struct draw_context *draw)
  662. {
  663.    struct aapoint_stage *aapoint = CALLOC_STRUCT(aapoint_stage);
  664.    if (aapoint == NULL)
  665.       goto fail;
  666.  
  667.    aapoint->stage.draw = draw;
  668.    aapoint->stage.name = "aapoint";
  669.    aapoint->stage.next = NULL;
  670.    aapoint->stage.point = aapoint_first_point;
  671.    aapoint->stage.line = draw_pipe_passthrough_line;
  672.    aapoint->stage.tri = draw_pipe_passthrough_tri;
  673.    aapoint->stage.flush = aapoint_flush;
  674.    aapoint->stage.reset_stipple_counter = aapoint_reset_stipple_counter;
  675.    aapoint->stage.destroy = aapoint_destroy;
  676.  
  677.    if (!draw_alloc_temp_verts( &aapoint->stage, 4 ))
  678.       goto fail;
  679.  
  680.    return aapoint;
  681.  
  682.  fail:
  683.    if (aapoint)
  684.       aapoint->stage.destroy(&aapoint->stage);
  685.  
  686.    return NULL;
  687.  
  688. }
  689.  
  690.  
  691. static struct aapoint_stage *
  692. aapoint_stage_from_pipe(struct pipe_context *pipe)
  693. {
  694.    struct draw_context *draw = (struct draw_context *) pipe->draw;
  695.    return aapoint_stage(draw->pipeline.aapoint);
  696. }
  697.  
  698.  
  699. /**
  700.  * This function overrides the driver's create_fs_state() function and
  701.  * will typically be called by the state tracker.
  702.  */
  703. static void *
  704. aapoint_create_fs_state(struct pipe_context *pipe,
  705.                        const struct pipe_shader_state *fs)
  706. {
  707.    struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe);
  708.    struct aapoint_fragment_shader *aafs = CALLOC_STRUCT(aapoint_fragment_shader);
  709.    if (aafs == NULL)
  710.       return NULL;
  711.  
  712.    aafs->state.tokens = tgsi_dup_tokens(fs->tokens);
  713.  
  714.    /* pass-through */
  715.    aafs->driver_fs = aapoint->driver_create_fs_state(pipe, fs);
  716.  
  717.    return aafs;
  718. }
  719.  
  720.  
  721. static void
  722. aapoint_bind_fs_state(struct pipe_context *pipe, void *fs)
  723. {
  724.    struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe);
  725.    struct aapoint_fragment_shader *aafs = (struct aapoint_fragment_shader *) fs;
  726.    /* save current */
  727.    aapoint->fs = aafs;
  728.    /* pass-through */
  729.    aapoint->driver_bind_fs_state(pipe,
  730.                                  (aafs ? aafs->driver_fs : NULL));
  731. }
  732.  
  733.  
  734. static void
  735. aapoint_delete_fs_state(struct pipe_context *pipe, void *fs)
  736. {
  737.    struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe);
  738.    struct aapoint_fragment_shader *aafs = (struct aapoint_fragment_shader *) fs;
  739.  
  740.    /* pass-through */
  741.    aapoint->driver_delete_fs_state(pipe, aafs->driver_fs);
  742.  
  743.    if (aafs->aapoint_fs)
  744.       aapoint->driver_delete_fs_state(pipe, aafs->aapoint_fs);
  745.  
  746.    FREE((void*)aafs->state.tokens);
  747.  
  748.    FREE(aafs);
  749. }
  750.  
  751.  
  752. /**
  753.  * Called by drivers that want to install this AA point prim stage
  754.  * into the draw module's pipeline.  This will not be used if the
  755.  * hardware has native support for AA points.
  756.  */
  757. boolean
  758. draw_install_aapoint_stage(struct draw_context *draw,
  759.                            struct pipe_context *pipe)
  760. {
  761.    struct aapoint_stage *aapoint;
  762.  
  763.    pipe->draw = (void *) draw;
  764.  
  765.    /*
  766.     * Create / install AA point drawing / prim stage
  767.     */
  768.    aapoint = draw_aapoint_stage( draw );
  769.    if (aapoint == NULL)
  770.       return FALSE;
  771.  
  772.    /* save original driver functions */
  773.    aapoint->driver_create_fs_state = pipe->create_fs_state;
  774.    aapoint->driver_bind_fs_state = pipe->bind_fs_state;
  775.    aapoint->driver_delete_fs_state = pipe->delete_fs_state;
  776.  
  777.    /* override the driver's functions */
  778.    pipe->create_fs_state = aapoint_create_fs_state;
  779.    pipe->bind_fs_state = aapoint_bind_fs_state;
  780.    pipe->delete_fs_state = aapoint_delete_fs_state;
  781.  
  782.    draw->pipeline.aapoint = &aapoint->stage;
  783.  
  784.    return TRUE;
  785. }
  786.