Home | History | Annotate | Download | only in draw
      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_pstipple.h"
     47 #include "util/u_sampler.h"
     48 
     49 #include "tgsi/tgsi_transform.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 53
     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 *,
    103                                       enum pipe_shader_type,
    104                                       unsigned, unsigned, void **);
    105 
    106    void (*driver_set_sampler_views)(struct pipe_context *,
    107                                     enum pipe_shader_type shader,
    108                                     unsigned start, unsigned count,
    109                                     struct pipe_sampler_view **);
    110 
    111    void (*driver_set_polygon_stipple)(struct pipe_context *,
    112                                       const struct pipe_poly_stipple *);
    113 
    114    struct pipe_context *pipe;
    115 };
    116 
    117 
    118 /**
    119  * Generate the frag shader we'll use for doing polygon stipple.
    120  * This will be the user's shader prefixed with a TEX and KIL instruction.
    121  */
    122 static boolean
    123 generate_pstip_fs(struct pstip_stage *pstip)
    124 {
    125    struct pipe_context *pipe = pstip->pipe;
    126    struct pipe_screen *screen = pipe->screen;
    127    const struct pipe_shader_state *orig_fs = &pstip->fs->state;
    128    /*struct draw_context *draw = pstip->stage.draw;*/
    129    struct pipe_shader_state pstip_fs;
    130    enum tgsi_file_type wincoord_file;
    131 
    132    wincoord_file = screen->get_param(screen, PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL) ?
    133                    TGSI_FILE_SYSTEM_VALUE : TGSI_FILE_INPUT;
    134 
    135    pstip_fs = *orig_fs; /* copy to init */
    136    pstip_fs.tokens = util_pstipple_create_fragment_shader(orig_fs->tokens,
    137                                                           &pstip->fs->sampler_unit,
    138                                                           0,
    139                                                           wincoord_file);
    140    if (pstip_fs.tokens == NULL)
    141       return FALSE;
    142 
    143    assert(pstip->fs->sampler_unit < PIPE_MAX_SAMPLERS);
    144 
    145    pstip->fs->pstip_fs = pstip->driver_create_fs_state(pipe, &pstip_fs);
    146 
    147    FREE((void *)pstip_fs.tokens);
    148 
    149    if (!pstip->fs->pstip_fs)
    150       return FALSE;
    151 
    152    return TRUE;
    153 }
    154 
    155 
    156 /**
    157  * When we're about to draw our first stipple polygon in a batch, this function
    158  * is called to tell the driver to bind our modified fragment shader.
    159  */
    160 static boolean
    161 bind_pstip_fragment_shader(struct pstip_stage *pstip)
    162 {
    163    struct draw_context *draw = pstip->stage.draw;
    164    if (!pstip->fs->pstip_fs &&
    165        !generate_pstip_fs(pstip))
    166       return FALSE;
    167 
    168    draw->suspend_flushing = TRUE;
    169    pstip->driver_bind_fs_state(pstip->pipe, pstip->fs->pstip_fs);
    170    draw->suspend_flushing = FALSE;
    171    return TRUE;
    172 }
    173 
    174 
    175 static inline struct pstip_stage *
    176 pstip_stage( struct draw_stage *stage )
    177 {
    178    return (struct pstip_stage *) stage;
    179 }
    180 
    181 
    182 static void
    183 pstip_first_tri(struct draw_stage *stage, struct prim_header *header)
    184 {
    185    struct pstip_stage *pstip = pstip_stage(stage);
    186    struct pipe_context *pipe = pstip->pipe;
    187    struct draw_context *draw = stage->draw;
    188    uint num_samplers;
    189    uint num_sampler_views;
    190 
    191    assert(stage->draw->rasterizer->poly_stipple_enable);
    192 
    193    /* bind our fragprog */
    194    if (!bind_pstip_fragment_shader(pstip)) {
    195       stage->tri = draw_pipe_passthrough_tri;
    196       stage->tri(stage, header);
    197       return;
    198    }
    199 
    200    /* how many samplers? */
    201    /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */
    202    num_samplers = MAX2(pstip->num_samplers, pstip->fs->sampler_unit + 1);
    203    num_sampler_views = MAX2(pstip->num_sampler_views, num_samplers);
    204 
    205    /* plug in our sampler, texture */
    206    pstip->state.samplers[pstip->fs->sampler_unit] = pstip->sampler_cso;
    207    pipe_sampler_view_reference(&pstip->state.sampler_views[pstip->fs->sampler_unit],
    208                                pstip->sampler_view);
    209 
    210    assert(num_samplers <= PIPE_MAX_SAMPLERS);
    211 
    212    draw->suspend_flushing = TRUE;
    213 
    214    pstip->driver_bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0,
    215                                      num_samplers, pstip->state.samplers);
    216 
    217    pstip->driver_set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0,
    218                                    num_sampler_views, pstip->state.sampler_views);
    219 
    220    draw->suspend_flushing = FALSE;
    221 
    222    /* now really draw first triangle */
    223    stage->tri = draw_pipe_passthrough_tri;
    224    stage->tri(stage, header);
    225 }
    226 
    227 
    228 static void
    229 pstip_flush(struct draw_stage *stage, unsigned flags)
    230 {
    231    struct draw_context *draw = stage->draw;
    232    struct pstip_stage *pstip = pstip_stage(stage);
    233    struct pipe_context *pipe = pstip->pipe;
    234 
    235    stage->tri = pstip_first_tri;
    236    stage->next->flush( stage->next, flags );
    237 
    238    /* restore original frag shader, texture, sampler state */
    239    draw->suspend_flushing = TRUE;
    240    pstip->driver_bind_fs_state(pipe, pstip->fs ? pstip->fs->driver_fs : NULL);
    241 
    242    pstip->driver_bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0,
    243                                      pstip->num_samplers,
    244                                      pstip->state.samplers);
    245 
    246    pstip->driver_set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0,
    247                                    pstip->num_sampler_views,
    248                                    pstip->state.sampler_views);
    249 
    250    draw->suspend_flushing = FALSE;
    251 }
    252 
    253 
    254 static void
    255 pstip_reset_stipple_counter(struct draw_stage *stage)
    256 {
    257    stage->next->reset_stipple_counter( stage->next );
    258 }
    259 
    260 
    261 static void
    262 pstip_destroy(struct draw_stage *stage)
    263 {
    264    struct pstip_stage *pstip = pstip_stage(stage);
    265    uint i;
    266 
    267    for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) {
    268       pipe_sampler_view_reference(&pstip->state.sampler_views[i], NULL);
    269    }
    270 
    271    pstip->pipe->delete_sampler_state(pstip->pipe, pstip->sampler_cso);
    272 
    273    pipe_resource_reference(&pstip->texture, NULL);
    274 
    275    if (pstip->sampler_view) {
    276       pipe_sampler_view_reference(&pstip->sampler_view, NULL);
    277    }
    278 
    279    draw_free_temp_verts( stage );
    280    FREE( stage );
    281 }
    282 
    283 
    284 /** Create a new polygon stipple drawing stage object */
    285 static struct pstip_stage *
    286 draw_pstip_stage(struct draw_context *draw, struct pipe_context *pipe)
    287 {
    288    struct pstip_stage *pstip = CALLOC_STRUCT(pstip_stage);
    289    if (!pstip)
    290       goto fail;
    291 
    292    pstip->pipe = pipe;
    293 
    294    pstip->stage.draw = draw;
    295    pstip->stage.name = "pstip";
    296    pstip->stage.next = NULL;
    297    pstip->stage.point = draw_pipe_passthrough_point;
    298    pstip->stage.line = draw_pipe_passthrough_line;
    299    pstip->stage.tri = pstip_first_tri;
    300    pstip->stage.flush = pstip_flush;
    301    pstip->stage.reset_stipple_counter = pstip_reset_stipple_counter;
    302    pstip->stage.destroy = pstip_destroy;
    303 
    304    if (!draw_alloc_temp_verts( &pstip->stage, 8 ))
    305       goto fail;
    306 
    307    return pstip;
    308 
    309 fail:
    310    if (pstip)
    311       pstip->stage.destroy( &pstip->stage );
    312 
    313    return NULL;
    314 }
    315 
    316 
    317 static struct pstip_stage *
    318 pstip_stage_from_pipe(struct pipe_context *pipe)
    319 {
    320    struct draw_context *draw = (struct draw_context *) pipe->draw;
    321    return pstip_stage(draw->pipeline.pstipple);
    322 }
    323 
    324 
    325 /**
    326  * This function overrides the driver's create_fs_state() function and
    327  * will typically be called by the state tracker.
    328  */
    329 static void *
    330 pstip_create_fs_state(struct pipe_context *pipe,
    331                        const struct pipe_shader_state *fs)
    332 {
    333    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
    334    struct pstip_fragment_shader *pstipfs = CALLOC_STRUCT(pstip_fragment_shader);
    335 
    336    if (pstipfs) {
    337       pstipfs->state.tokens = tgsi_dup_tokens(fs->tokens);
    338 
    339       /* pass-through */
    340       pstipfs->driver_fs = pstip->driver_create_fs_state(pstip->pipe, fs);
    341    }
    342 
    343    return pstipfs;
    344 }
    345 
    346 
    347 static void
    348 pstip_bind_fs_state(struct pipe_context *pipe, void *fs)
    349 {
    350    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
    351    struct pstip_fragment_shader *pstipfs = (struct pstip_fragment_shader *) fs;
    352    /* save current */
    353    pstip->fs = pstipfs;
    354    /* pass-through */
    355    pstip->driver_bind_fs_state(pstip->pipe,
    356                                (pstipfs ? pstipfs->driver_fs : NULL));
    357 }
    358 
    359 
    360 static void
    361 pstip_delete_fs_state(struct pipe_context *pipe, void *fs)
    362 {
    363    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
    364    struct pstip_fragment_shader *pstipfs = (struct pstip_fragment_shader *) fs;
    365    /* pass-through */
    366    pstip->driver_delete_fs_state(pstip->pipe, pstipfs->driver_fs);
    367 
    368    if (pstipfs->pstip_fs)
    369       pstip->driver_delete_fs_state(pstip->pipe, pstipfs->pstip_fs);
    370 
    371    FREE((void*)pstipfs->state.tokens);
    372    FREE(pstipfs);
    373 }
    374 
    375 
    376 static void
    377 pstip_bind_sampler_states(struct pipe_context *pipe,
    378                           enum pipe_shader_type shader,
    379                           unsigned start, unsigned num, void **sampler)
    380 {
    381    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
    382    uint i;
    383 
    384    assert(start == 0);
    385 
    386    if (shader == PIPE_SHADER_FRAGMENT) {
    387       /* save current */
    388       memcpy(pstip->state.samplers, sampler, num * sizeof(void *));
    389       for (i = num; i < PIPE_MAX_SAMPLERS; i++) {
    390          pstip->state.samplers[i] = NULL;
    391       }
    392       pstip->num_samplers = num;
    393    }
    394 
    395    /* pass-through */
    396    pstip->driver_bind_sampler_states(pstip->pipe, shader, start, num, sampler);
    397 }
    398 
    399 
    400 static void
    401 pstip_set_sampler_views(struct pipe_context *pipe,
    402                         enum pipe_shader_type shader,
    403                         unsigned start, unsigned num,
    404                         struct pipe_sampler_view **views)
    405 {
    406    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
    407    uint i;
    408 
    409    if (shader == PIPE_SHADER_FRAGMENT) {
    410       /* save current */
    411       for (i = 0; i < num; i++) {
    412          pipe_sampler_view_reference(&pstip->state.sampler_views[start + i],
    413                                      views[i]);
    414       }
    415       pstip->num_sampler_views = num;
    416    }
    417 
    418    /* pass-through */
    419    pstip->driver_set_sampler_views(pstip->pipe, shader, start, num, views);
    420 }
    421 
    422 
    423 static void
    424 pstip_set_polygon_stipple(struct pipe_context *pipe,
    425                           const struct pipe_poly_stipple *stipple)
    426 {
    427    struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
    428 
    429    /* save current */
    430    pstip->state.stipple = stipple;
    431 
    432    /* pass-through */
    433    pstip->driver_set_polygon_stipple(pstip->pipe, stipple);
    434 
    435    util_pstipple_update_stipple_texture(pstip->pipe, pstip->texture,
    436                                         pstip->state.stipple->stipple);
    437 }
    438 
    439 
    440 /**
    441  * Called by drivers that want to install this polygon stipple stage
    442  * into the draw module's pipeline.  This will not be used if the
    443  * hardware has native support for polygon stipple.
    444  */
    445 boolean
    446 draw_install_pstipple_stage(struct draw_context *draw,
    447                             struct pipe_context *pipe)
    448 {
    449    struct pstip_stage *pstip;
    450 
    451    pipe->draw = (void *) draw;
    452 
    453    /*
    454     * Create / install pgon stipple drawing / prim stage
    455     */
    456    pstip = draw_pstip_stage( draw, pipe );
    457    if (!pstip)
    458       goto fail;
    459 
    460    draw->pipeline.pstipple = &pstip->stage;
    461 
    462    /* save original driver functions */
    463    pstip->driver_create_fs_state = pipe->create_fs_state;
    464    pstip->driver_bind_fs_state = pipe->bind_fs_state;
    465    pstip->driver_delete_fs_state = pipe->delete_fs_state;
    466 
    467    pstip->driver_bind_sampler_states = pipe->bind_sampler_states;
    468    pstip->driver_set_sampler_views = pipe->set_sampler_views;
    469    pstip->driver_set_polygon_stipple = pipe->set_polygon_stipple;
    470 
    471    /* create special texture, sampler state */
    472    pstip->texture = util_pstipple_create_stipple_texture(pipe, NULL);
    473    if (!pstip->texture)
    474       goto fail;
    475 
    476    pstip->sampler_view = util_pstipple_create_sampler_view(pipe,
    477                                                            pstip->texture);
    478    if (!pstip->sampler_view)
    479       goto fail;
    480 
    481    pstip->sampler_cso = util_pstipple_create_sampler(pipe);
    482    if (!pstip->sampler_cso)
    483       goto fail;
    484 
    485    /* override the driver's functions */
    486    pipe->create_fs_state = pstip_create_fs_state;
    487    pipe->bind_fs_state = pstip_bind_fs_state;
    488    pipe->delete_fs_state = pstip_delete_fs_state;
    489 
    490    pipe->bind_sampler_states = pstip_bind_sampler_states;
    491    pipe->set_sampler_views = pstip_set_sampler_views;
    492    pipe->set_polygon_stipple = pstip_set_polygon_stipple;
    493 
    494    return TRUE;
    495 
    496  fail:
    497    if (pstip)
    498       pstip->stage.destroy( &pstip->stage );
    499 
    500    return FALSE;
    501 }
    502