Home | History | Annotate | Download | only in nvc0
      1 /*
      2  * Copyright 2010 Christoph Bumiller
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice shall be included in
     12  * all copies or substantial portions of the Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20  * OTHER DEALINGS IN THE SOFTWARE.
     21  */
     22 
     23 #include "pipe/p_defines.h"
     24 #include "util/u_framebuffer.h"
     25 #include "util/u_helpers.h"
     26 #include "util/u_inlines.h"
     27 #include "util/u_transfer.h"
     28 
     29 #include "tgsi/tgsi_parse.h"
     30 
     31 #include "nvc0/nvc0_stateobj.h"
     32 #include "nvc0/nvc0_context.h"
     33 #include "nvc0/nvc0_query_hw.h"
     34 
     35 #include "nvc0/nvc0_3d.xml.h"
     36 
     37 #include "nouveau_gldefs.h"
     38 
     39 static inline uint32_t
     40 nvc0_colormask(unsigned mask)
     41 {
     42     uint32_t ret = 0;
     43 
     44     if (mask & PIPE_MASK_R)
     45         ret |= 0x0001;
     46     if (mask & PIPE_MASK_G)
     47         ret |= 0x0010;
     48     if (mask & PIPE_MASK_B)
     49         ret |= 0x0100;
     50     if (mask & PIPE_MASK_A)
     51         ret |= 0x1000;
     52 
     53     return ret;
     54 }
     55 
     56 #define NVC0_BLEND_FACTOR_CASE(a, b) \
     57    case PIPE_BLENDFACTOR_##a: return NV50_BLEND_FACTOR_##b
     58 
     59 static inline uint32_t
     60 nvc0_blend_fac(unsigned factor)
     61 {
     62    switch (factor) {
     63    NVC0_BLEND_FACTOR_CASE(ONE, ONE);
     64    NVC0_BLEND_FACTOR_CASE(SRC_COLOR, SRC_COLOR);
     65    NVC0_BLEND_FACTOR_CASE(SRC_ALPHA, SRC_ALPHA);
     66    NVC0_BLEND_FACTOR_CASE(DST_ALPHA, DST_ALPHA);
     67    NVC0_BLEND_FACTOR_CASE(DST_COLOR, DST_COLOR);
     68    NVC0_BLEND_FACTOR_CASE(SRC_ALPHA_SATURATE, SRC_ALPHA_SATURATE);
     69    NVC0_BLEND_FACTOR_CASE(CONST_COLOR, CONSTANT_COLOR);
     70    NVC0_BLEND_FACTOR_CASE(CONST_ALPHA, CONSTANT_ALPHA);
     71    NVC0_BLEND_FACTOR_CASE(SRC1_COLOR, SRC1_COLOR);
     72    NVC0_BLEND_FACTOR_CASE(SRC1_ALPHA, SRC1_ALPHA);
     73    NVC0_BLEND_FACTOR_CASE(ZERO, ZERO);
     74    NVC0_BLEND_FACTOR_CASE(INV_SRC_COLOR, ONE_MINUS_SRC_COLOR);
     75    NVC0_BLEND_FACTOR_CASE(INV_SRC_ALPHA, ONE_MINUS_SRC_ALPHA);
     76    NVC0_BLEND_FACTOR_CASE(INV_DST_ALPHA, ONE_MINUS_DST_ALPHA);
     77    NVC0_BLEND_FACTOR_CASE(INV_DST_COLOR, ONE_MINUS_DST_COLOR);
     78    NVC0_BLEND_FACTOR_CASE(INV_CONST_COLOR, ONE_MINUS_CONSTANT_COLOR);
     79    NVC0_BLEND_FACTOR_CASE(INV_CONST_ALPHA, ONE_MINUS_CONSTANT_ALPHA);
     80    NVC0_BLEND_FACTOR_CASE(INV_SRC1_COLOR, ONE_MINUS_SRC1_COLOR);
     81    NVC0_BLEND_FACTOR_CASE(INV_SRC1_ALPHA, ONE_MINUS_SRC1_ALPHA);
     82    default:
     83       return NV50_BLEND_FACTOR_ZERO;
     84    }
     85 }
     86 
     87 static void *
     88 nvc0_blend_state_create(struct pipe_context *pipe,
     89                         const struct pipe_blend_state *cso)
     90 {
     91    struct nvc0_blend_stateobj *so = CALLOC_STRUCT(nvc0_blend_stateobj);
     92    int i;
     93    int r; /* reference */
     94    uint32_t ms;
     95    uint8_t blend_en = 0;
     96    bool indep_masks = false;
     97    bool indep_funcs = false;
     98 
     99    so->pipe = *cso;
    100 
    101    /* check which states actually have differing values */
    102    if (cso->independent_blend_enable) {
    103       for (r = 0; r < 8 && !cso->rt[r].blend_enable; ++r);
    104       blend_en |= 1 << r;
    105       for (i = r + 1; i < 8; ++i) {
    106          if (!cso->rt[i].blend_enable)
    107             continue;
    108          blend_en |= 1 << i;
    109          if (cso->rt[i].rgb_func != cso->rt[r].rgb_func ||
    110              cso->rt[i].rgb_src_factor != cso->rt[r].rgb_src_factor ||
    111              cso->rt[i].rgb_dst_factor != cso->rt[r].rgb_dst_factor ||
    112              cso->rt[i].alpha_func != cso->rt[r].alpha_func ||
    113              cso->rt[i].alpha_src_factor != cso->rt[r].alpha_src_factor ||
    114              cso->rt[i].alpha_dst_factor != cso->rt[r].alpha_dst_factor) {
    115             indep_funcs = true;
    116             break;
    117          }
    118       }
    119       for (; i < 8; ++i)
    120          blend_en |= (cso->rt[i].blend_enable ? 1 : 0) << i;
    121 
    122       for (i = 1; i < 8; ++i) {
    123          if (cso->rt[i].colormask != cso->rt[0].colormask) {
    124             indep_masks = true;
    125             break;
    126          }
    127       }
    128    } else {
    129       r = 0;
    130       if (cso->rt[0].blend_enable)
    131          blend_en = 0xff;
    132    }
    133 
    134    if (cso->logicop_enable) {
    135       SB_BEGIN_3D(so, LOGIC_OP_ENABLE, 2);
    136       SB_DATA    (so, 1);
    137       SB_DATA    (so, nvgl_logicop_func(cso->logicop_func));
    138 
    139       SB_IMMED_3D(so, MACRO_BLEND_ENABLES, 0);
    140    } else {
    141       SB_IMMED_3D(so, LOGIC_OP_ENABLE, 0);
    142 
    143       SB_IMMED_3D(so, BLEND_INDEPENDENT, indep_funcs);
    144       SB_IMMED_3D(so, MACRO_BLEND_ENABLES, blend_en);
    145       if (indep_funcs) {
    146          for (i = 0; i < 8; ++i) {
    147             if (cso->rt[i].blend_enable) {
    148                SB_BEGIN_3D(so, IBLEND_EQUATION_RGB(i), 6);
    149                SB_DATA    (so, nvgl_blend_eqn(cso->rt[i].rgb_func));
    150                SB_DATA    (so, nvc0_blend_fac(cso->rt[i].rgb_src_factor));
    151                SB_DATA    (so, nvc0_blend_fac(cso->rt[i].rgb_dst_factor));
    152                SB_DATA    (so, nvgl_blend_eqn(cso->rt[i].alpha_func));
    153                SB_DATA    (so, nvc0_blend_fac(cso->rt[i].alpha_src_factor));
    154                SB_DATA    (so, nvc0_blend_fac(cso->rt[i].alpha_dst_factor));
    155             }
    156          }
    157       } else
    158       if (blend_en) {
    159          SB_BEGIN_3D(so, BLEND_EQUATION_RGB, 5);
    160          SB_DATA    (so, nvgl_blend_eqn(cso->rt[r].rgb_func));
    161          SB_DATA    (so, nvc0_blend_fac(cso->rt[r].rgb_src_factor));
    162          SB_DATA    (so, nvc0_blend_fac(cso->rt[r].rgb_dst_factor));
    163          SB_DATA    (so, nvgl_blend_eqn(cso->rt[r].alpha_func));
    164          SB_DATA    (so, nvc0_blend_fac(cso->rt[r].alpha_src_factor));
    165          SB_BEGIN_3D(so, BLEND_FUNC_DST_ALPHA, 1);
    166          SB_DATA    (so, nvc0_blend_fac(cso->rt[r].alpha_dst_factor));
    167       }
    168 
    169       SB_IMMED_3D(so, COLOR_MASK_COMMON, !indep_masks);
    170       if (indep_masks) {
    171          SB_BEGIN_3D(so, COLOR_MASK(0), 8);
    172          for (i = 0; i < 8; ++i)
    173             SB_DATA(so, nvc0_colormask(cso->rt[i].colormask));
    174       } else {
    175          SB_BEGIN_3D(so, COLOR_MASK(0), 1);
    176          SB_DATA    (so, nvc0_colormask(cso->rt[0].colormask));
    177       }
    178    }
    179 
    180    ms = 0;
    181    if (cso->alpha_to_coverage)
    182       ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_COVERAGE;
    183    if (cso->alpha_to_one)
    184       ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_ONE;
    185 
    186    SB_BEGIN_3D(so, MULTISAMPLE_CTRL, 1);
    187    SB_DATA    (so, ms);
    188 
    189    assert(so->size <= ARRAY_SIZE(so->state));
    190    return so;
    191 }
    192 
    193 static void
    194 nvc0_blend_state_bind(struct pipe_context *pipe, void *hwcso)
    195 {
    196     struct nvc0_context *nvc0 = nvc0_context(pipe);
    197 
    198     nvc0->blend = hwcso;
    199     nvc0->dirty_3d |= NVC0_NEW_3D_BLEND;
    200 }
    201 
    202 static void
    203 nvc0_blend_state_delete(struct pipe_context *pipe, void *hwcso)
    204 {
    205     FREE(hwcso);
    206 }
    207 
    208 /* NOTE: ignoring line_last_pixel */
    209 static void *
    210 nvc0_rasterizer_state_create(struct pipe_context *pipe,
    211                              const struct pipe_rasterizer_state *cso)
    212 {
    213     struct nvc0_rasterizer_stateobj *so;
    214     uint32_t reg;
    215 
    216     so = CALLOC_STRUCT(nvc0_rasterizer_stateobj);
    217     if (!so)
    218         return NULL;
    219     so->pipe = *cso;
    220 
    221     /* Scissor enables are handled in scissor state, we will not want to
    222      * always emit 16 commands, one for each scissor rectangle, here.
    223      */
    224 
    225     SB_IMMED_3D(so, PROVOKING_VERTEX_LAST, !cso->flatshade_first);
    226     SB_IMMED_3D(so, VERTEX_TWO_SIDE_ENABLE, cso->light_twoside);
    227 
    228     SB_IMMED_3D(so, VERT_COLOR_CLAMP_EN, cso->clamp_vertex_color);
    229     SB_BEGIN_3D(so, FRAG_COLOR_CLAMP_EN, 1);
    230     SB_DATA    (so, cso->clamp_fragment_color ? 0x11111111 : 0x00000000);
    231 
    232     SB_IMMED_3D(so, MULTISAMPLE_ENABLE, cso->multisample);
    233 
    234     SB_IMMED_3D(so, LINE_SMOOTH_ENABLE, cso->line_smooth);
    235     if (cso->line_smooth || cso->multisample)
    236        SB_BEGIN_3D(so, LINE_WIDTH_SMOOTH, 1);
    237     else
    238        SB_BEGIN_3D(so, LINE_WIDTH_ALIASED, 1);
    239     SB_DATA    (so, fui(cso->line_width));
    240 
    241     SB_IMMED_3D(so, LINE_STIPPLE_ENABLE, cso->line_stipple_enable);
    242     if (cso->line_stipple_enable) {
    243         SB_BEGIN_3D(so, LINE_STIPPLE_PATTERN, 1);
    244         SB_DATA    (so, (cso->line_stipple_pattern << 8) |
    245                          cso->line_stipple_factor);
    246 
    247     }
    248 
    249     SB_IMMED_3D(so, VP_POINT_SIZE, cso->point_size_per_vertex);
    250     if (!cso->point_size_per_vertex) {
    251        SB_BEGIN_3D(so, POINT_SIZE, 1);
    252        SB_DATA    (so, fui(cso->point_size));
    253     }
    254 
    255     reg = (cso->sprite_coord_mode == PIPE_SPRITE_COORD_UPPER_LEFT) ?
    256        NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_UPPER_LEFT :
    257        NVC0_3D_POINT_COORD_REPLACE_COORD_ORIGIN_LOWER_LEFT;
    258 
    259     SB_BEGIN_3D(so, POINT_COORD_REPLACE, 1);
    260     SB_DATA    (so, ((cso->sprite_coord_enable & 0xff) << 3) | reg);
    261     SB_IMMED_3D(so, POINT_SPRITE_ENABLE, cso->point_quad_rasterization);
    262     SB_IMMED_3D(so, POINT_SMOOTH_ENABLE, cso->point_smooth);
    263 
    264     SB_BEGIN_3D(so, MACRO_POLYGON_MODE_FRONT, 1);
    265     SB_DATA    (so, nvgl_polygon_mode(cso->fill_front));
    266     SB_BEGIN_3D(so, MACRO_POLYGON_MODE_BACK, 1);
    267     SB_DATA    (so, nvgl_polygon_mode(cso->fill_back));
    268     SB_IMMED_3D(so, POLYGON_SMOOTH_ENABLE, cso->poly_smooth);
    269 
    270     SB_BEGIN_3D(so, CULL_FACE_ENABLE, 3);
    271     SB_DATA    (so, cso->cull_face != PIPE_FACE_NONE);
    272     SB_DATA    (so, cso->front_ccw ? NVC0_3D_FRONT_FACE_CCW :
    273                                      NVC0_3D_FRONT_FACE_CW);
    274     switch (cso->cull_face) {
    275     case PIPE_FACE_FRONT_AND_BACK:
    276        SB_DATA(so, NVC0_3D_CULL_FACE_FRONT_AND_BACK);
    277        break;
    278     case PIPE_FACE_FRONT:
    279        SB_DATA(so, NVC0_3D_CULL_FACE_FRONT);
    280        break;
    281     case PIPE_FACE_BACK:
    282     default:
    283        SB_DATA(so, NVC0_3D_CULL_FACE_BACK);
    284        break;
    285     }
    286 
    287     SB_IMMED_3D(so, POLYGON_STIPPLE_ENABLE, cso->poly_stipple_enable);
    288     SB_BEGIN_3D(so, POLYGON_OFFSET_POINT_ENABLE, 3);
    289     SB_DATA    (so, cso->offset_point);
    290     SB_DATA    (so, cso->offset_line);
    291     SB_DATA    (so, cso->offset_tri);
    292 
    293     if (cso->offset_point || cso->offset_line || cso->offset_tri) {
    294         SB_BEGIN_3D(so, POLYGON_OFFSET_FACTOR, 1);
    295         SB_DATA    (so, fui(cso->offset_scale));
    296         if (!cso->offset_units_unscaled) {
    297            SB_BEGIN_3D(so, POLYGON_OFFSET_UNITS, 1);
    298            SB_DATA    (so, fui(cso->offset_units * 2.0f));
    299         }
    300         SB_BEGIN_3D(so, POLYGON_OFFSET_CLAMP, 1);
    301         SB_DATA    (so, fui(cso->offset_clamp));
    302     }
    303 
    304     if (cso->depth_clip)
    305        reg = NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1;
    306     else
    307        reg =
    308           NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK1_UNK1 |
    309           NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_NEAR |
    310           NVC0_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_FAR |
    311           NVC0_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK2;
    312 
    313     SB_BEGIN_3D(so, VIEW_VOLUME_CLIP_CTRL, 1);
    314     SB_DATA    (so, reg);
    315 
    316     SB_IMMED_3D(so, DEPTH_CLIP_NEGATIVE_Z, cso->clip_halfz);
    317 
    318     SB_IMMED_3D(so, PIXEL_CENTER_INTEGER, !cso->half_pixel_center);
    319 
    320     assert(so->size <= ARRAY_SIZE(so->state));
    321     return (void *)so;
    322 }
    323 
    324 static void
    325 nvc0_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
    326 {
    327    struct nvc0_context *nvc0 = nvc0_context(pipe);
    328 
    329    nvc0->rast = hwcso;
    330    nvc0->dirty_3d |= NVC0_NEW_3D_RASTERIZER;
    331 }
    332 
    333 static void
    334 nvc0_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
    335 {
    336    FREE(hwcso);
    337 }
    338 
    339 static void *
    340 nvc0_zsa_state_create(struct pipe_context *pipe,
    341                       const struct pipe_depth_stencil_alpha_state *cso)
    342 {
    343    struct nvc0_zsa_stateobj *so = CALLOC_STRUCT(nvc0_zsa_stateobj);
    344 
    345    so->pipe = *cso;
    346 
    347    SB_IMMED_3D(so, DEPTH_TEST_ENABLE, cso->depth.enabled);
    348    if (cso->depth.enabled) {
    349       SB_IMMED_3D(so, DEPTH_WRITE_ENABLE, cso->depth.writemask);
    350       SB_BEGIN_3D(so, DEPTH_TEST_FUNC, 1);
    351       SB_DATA    (so, nvgl_comparison_op(cso->depth.func));
    352    }
    353 
    354    SB_IMMED_3D(so, DEPTH_BOUNDS_EN, cso->depth.bounds_test);
    355    if (cso->depth.bounds_test) {
    356       SB_BEGIN_3D(so, DEPTH_BOUNDS(0), 2);
    357       SB_DATA    (so, fui(cso->depth.bounds_min));
    358       SB_DATA    (so, fui(cso->depth.bounds_max));
    359    }
    360 
    361    if (cso->stencil[0].enabled) {
    362       SB_BEGIN_3D(so, STENCIL_ENABLE, 5);
    363       SB_DATA    (so, 1);
    364       SB_DATA    (so, nvgl_stencil_op(cso->stencil[0].fail_op));
    365       SB_DATA    (so, nvgl_stencil_op(cso->stencil[0].zfail_op));
    366       SB_DATA    (so, nvgl_stencil_op(cso->stencil[0].zpass_op));
    367       SB_DATA    (so, nvgl_comparison_op(cso->stencil[0].func));
    368       SB_BEGIN_3D(so, STENCIL_FRONT_FUNC_MASK, 2);
    369       SB_DATA    (so, cso->stencil[0].valuemask);
    370       SB_DATA    (so, cso->stencil[0].writemask);
    371    } else {
    372       SB_IMMED_3D(so, STENCIL_ENABLE, 0);
    373    }
    374 
    375    if (cso->stencil[1].enabled) {
    376       assert(cso->stencil[0].enabled);
    377       SB_BEGIN_3D(so, STENCIL_TWO_SIDE_ENABLE, 5);
    378       SB_DATA    (so, 1);
    379       SB_DATA    (so, nvgl_stencil_op(cso->stencil[1].fail_op));
    380       SB_DATA    (so, nvgl_stencil_op(cso->stencil[1].zfail_op));
    381       SB_DATA    (so, nvgl_stencil_op(cso->stencil[1].zpass_op));
    382       SB_DATA    (so, nvgl_comparison_op(cso->stencil[1].func));
    383       SB_BEGIN_3D(so, STENCIL_BACK_MASK, 2);
    384       SB_DATA    (so, cso->stencil[1].writemask);
    385       SB_DATA    (so, cso->stencil[1].valuemask);
    386    } else
    387    if (cso->stencil[0].enabled) {
    388       SB_IMMED_3D(so, STENCIL_TWO_SIDE_ENABLE, 0);
    389    }
    390 
    391    SB_IMMED_3D(so, ALPHA_TEST_ENABLE, cso->alpha.enabled);
    392    if (cso->alpha.enabled) {
    393       SB_BEGIN_3D(so, ALPHA_TEST_REF, 2);
    394       SB_DATA    (so, fui(cso->alpha.ref_value));
    395       SB_DATA    (so, nvgl_comparison_op(cso->alpha.func));
    396    }
    397 
    398    assert(so->size <= ARRAY_SIZE(so->state));
    399    return (void *)so;
    400 }
    401 
    402 static void
    403 nvc0_zsa_state_bind(struct pipe_context *pipe, void *hwcso)
    404 {
    405    struct nvc0_context *nvc0 = nvc0_context(pipe);
    406 
    407    nvc0->zsa = hwcso;
    408    nvc0->dirty_3d |= NVC0_NEW_3D_ZSA;
    409 }
    410 
    411 static void
    412 nvc0_zsa_state_delete(struct pipe_context *pipe, void *hwcso)
    413 {
    414    FREE(hwcso);
    415 }
    416 
    417 /* ====================== SAMPLERS AND TEXTURES ================================
    418  */
    419 
    420 #define NV50_TSC_WRAP_CASE(n) \
    421     case PIPE_TEX_WRAP_##n: return NV50_TSC_WRAP_##n
    422 
    423 static void
    424 nvc0_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
    425 {
    426    unsigned s, i;
    427 
    428    for (s = 0; s < 6; ++s)
    429       for (i = 0; i < nvc0_context(pipe)->num_samplers[s]; ++i)
    430          if (nvc0_context(pipe)->samplers[s][i] == hwcso)
    431             nvc0_context(pipe)->samplers[s][i] = NULL;
    432 
    433    nvc0_screen_tsc_free(nvc0_context(pipe)->screen, nv50_tsc_entry(hwcso));
    434 
    435    FREE(hwcso);
    436 }
    437 
    438 static inline void
    439 nvc0_stage_sampler_states_bind(struct nvc0_context *nvc0,
    440                                unsigned s,
    441                                unsigned nr, void **hwcso)
    442 {
    443    unsigned i;
    444 
    445    for (i = 0; i < nr; ++i) {
    446       struct nv50_tsc_entry *old = nvc0->samplers[s][i];
    447 
    448       if (hwcso[i] == old)
    449          continue;
    450       nvc0->samplers_dirty[s] |= 1 << i;
    451 
    452       nvc0->samplers[s][i] = nv50_tsc_entry(hwcso[i]);
    453       if (old)
    454          nvc0_screen_tsc_unlock(nvc0->screen, old);
    455    }
    456    for (; i < nvc0->num_samplers[s]; ++i) {
    457       if (nvc0->samplers[s][i]) {
    458          nvc0_screen_tsc_unlock(nvc0->screen, nvc0->samplers[s][i]);
    459          nvc0->samplers[s][i] = NULL;
    460       }
    461    }
    462 
    463    nvc0->num_samplers[s] = nr;
    464 }
    465 
    466 static void
    467 nvc0_bind_sampler_states(struct pipe_context *pipe,
    468                          enum pipe_shader_type shader,
    469                          unsigned start, unsigned nr, void **samplers)
    470 {
    471    const unsigned s = nvc0_shader_stage(shader);
    472 
    473    assert(start == 0);
    474    nvc0_stage_sampler_states_bind(nvc0_context(pipe), s, nr, samplers);
    475 
    476    if (s == 5)
    477       nvc0_context(pipe)->dirty_cp |= NVC0_NEW_CP_SAMPLERS;
    478    else
    479       nvc0_context(pipe)->dirty_3d |= NVC0_NEW_3D_SAMPLERS;
    480 }
    481 
    482 
    483 /* NOTE: only called when not referenced anywhere, won't be bound */
    484 static void
    485 nvc0_sampler_view_destroy(struct pipe_context *pipe,
    486                           struct pipe_sampler_view *view)
    487 {
    488    pipe_resource_reference(&view->texture, NULL);
    489 
    490    nvc0_screen_tic_free(nvc0_context(pipe)->screen, nv50_tic_entry(view));
    491 
    492    FREE(nv50_tic_entry(view));
    493 }
    494 
    495 static inline void
    496 nvc0_stage_set_sampler_views(struct nvc0_context *nvc0, int s,
    497                              unsigned nr,
    498                              struct pipe_sampler_view **views)
    499 {
    500    unsigned i;
    501 
    502    for (i = 0; i < nr; ++i) {
    503       struct nv50_tic_entry *old = nv50_tic_entry(nvc0->textures[s][i]);
    504 
    505       if (views[i] == nvc0->textures[s][i])
    506          continue;
    507       nvc0->textures_dirty[s] |= 1 << i;
    508 
    509       if (views[i] && views[i]->texture) {
    510          struct pipe_resource *res = views[i]->texture;
    511          if (res->target == PIPE_BUFFER &&
    512              (res->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT))
    513             nvc0->textures_coherent[s] |= 1 << i;
    514          else
    515             nvc0->textures_coherent[s] &= ~(1 << i);
    516       } else {
    517          nvc0->textures_coherent[s] &= ~(1 << i);
    518       }
    519 
    520       if (old) {
    521          if (s == 5)
    522             nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_TEX(i));
    523          else
    524             nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TEX(s, i));
    525          nvc0_screen_tic_unlock(nvc0->screen, old);
    526       }
    527 
    528       pipe_sampler_view_reference(&nvc0->textures[s][i], views[i]);
    529    }
    530 
    531    for (i = nr; i < nvc0->num_textures[s]; ++i) {
    532       struct nv50_tic_entry *old = nv50_tic_entry(nvc0->textures[s][i]);
    533       if (old) {
    534          if (s == 5)
    535             nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_TEX(i));
    536          else
    537             nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TEX(s, i));
    538          nvc0_screen_tic_unlock(nvc0->screen, old);
    539          pipe_sampler_view_reference(&nvc0->textures[s][i], NULL);
    540       }
    541    }
    542 
    543    nvc0->num_textures[s] = nr;
    544 }
    545 
    546 static void
    547 nvc0_set_sampler_views(struct pipe_context *pipe, enum pipe_shader_type shader,
    548                        unsigned start, unsigned nr,
    549                        struct pipe_sampler_view **views)
    550 {
    551    const unsigned s = nvc0_shader_stage(shader);
    552 
    553    assert(start == 0);
    554    nvc0_stage_set_sampler_views(nvc0_context(pipe), s, nr, views);
    555 
    556    if (s == 5)
    557       nvc0_context(pipe)->dirty_cp |= NVC0_NEW_CP_TEXTURES;
    558    else
    559       nvc0_context(pipe)->dirty_3d |= NVC0_NEW_3D_TEXTURES;
    560 }
    561 
    562 /* ============================= SHADERS =======================================
    563  */
    564 
    565 static void *
    566 nvc0_sp_state_create(struct pipe_context *pipe,
    567                      const struct pipe_shader_state *cso, unsigned type)
    568 {
    569    struct nvc0_program *prog;
    570 
    571    prog = CALLOC_STRUCT(nvc0_program);
    572    if (!prog)
    573       return NULL;
    574 
    575    prog->type = type;
    576 
    577    if (cso->tokens)
    578       prog->pipe.tokens = tgsi_dup_tokens(cso->tokens);
    579 
    580    if (cso->stream_output.num_outputs)
    581       prog->pipe.stream_output = cso->stream_output;
    582 
    583    prog->translated = nvc0_program_translate(
    584       prog, nvc0_context(pipe)->screen->base.device->chipset,
    585       &nouveau_context(pipe)->debug);
    586 
    587    return (void *)prog;
    588 }
    589 
    590 static void
    591 nvc0_sp_state_delete(struct pipe_context *pipe, void *hwcso)
    592 {
    593    struct nvc0_program *prog = (struct nvc0_program *)hwcso;
    594 
    595    nvc0_program_destroy(nvc0_context(pipe), prog);
    596 
    597    FREE((void *)prog->pipe.tokens);
    598    FREE(prog);
    599 }
    600 
    601 static void *
    602 nvc0_vp_state_create(struct pipe_context *pipe,
    603                      const struct pipe_shader_state *cso)
    604 {
    605    return nvc0_sp_state_create(pipe, cso, PIPE_SHADER_VERTEX);
    606 }
    607 
    608 static void
    609 nvc0_vp_state_bind(struct pipe_context *pipe, void *hwcso)
    610 {
    611     struct nvc0_context *nvc0 = nvc0_context(pipe);
    612 
    613     nvc0->vertprog = hwcso;
    614     nvc0->dirty_3d |= NVC0_NEW_3D_VERTPROG;
    615 }
    616 
    617 static void *
    618 nvc0_fp_state_create(struct pipe_context *pipe,
    619                      const struct pipe_shader_state *cso)
    620 {
    621    return nvc0_sp_state_create(pipe, cso, PIPE_SHADER_FRAGMENT);
    622 }
    623 
    624 static void
    625 nvc0_fp_state_bind(struct pipe_context *pipe, void *hwcso)
    626 {
    627     struct nvc0_context *nvc0 = nvc0_context(pipe);
    628 
    629     nvc0->fragprog = hwcso;
    630     nvc0->dirty_3d |= NVC0_NEW_3D_FRAGPROG;
    631 }
    632 
    633 static void *
    634 nvc0_gp_state_create(struct pipe_context *pipe,
    635                      const struct pipe_shader_state *cso)
    636 {
    637    return nvc0_sp_state_create(pipe, cso, PIPE_SHADER_GEOMETRY);
    638 }
    639 
    640 static void
    641 nvc0_gp_state_bind(struct pipe_context *pipe, void *hwcso)
    642 {
    643     struct nvc0_context *nvc0 = nvc0_context(pipe);
    644 
    645     nvc0->gmtyprog = hwcso;
    646     nvc0->dirty_3d |= NVC0_NEW_3D_GMTYPROG;
    647 }
    648 
    649 static void *
    650 nvc0_tcp_state_create(struct pipe_context *pipe,
    651                      const struct pipe_shader_state *cso)
    652 {
    653    return nvc0_sp_state_create(pipe, cso, PIPE_SHADER_TESS_CTRL);
    654 }
    655 
    656 static void
    657 nvc0_tcp_state_bind(struct pipe_context *pipe, void *hwcso)
    658 {
    659     struct nvc0_context *nvc0 = nvc0_context(pipe);
    660 
    661     nvc0->tctlprog = hwcso;
    662     nvc0->dirty_3d |= NVC0_NEW_3D_TCTLPROG;
    663 }
    664 
    665 static void *
    666 nvc0_tep_state_create(struct pipe_context *pipe,
    667                      const struct pipe_shader_state *cso)
    668 {
    669    return nvc0_sp_state_create(pipe, cso, PIPE_SHADER_TESS_EVAL);
    670 }
    671 
    672 static void
    673 nvc0_tep_state_bind(struct pipe_context *pipe, void *hwcso)
    674 {
    675     struct nvc0_context *nvc0 = nvc0_context(pipe);
    676 
    677     nvc0->tevlprog = hwcso;
    678     nvc0->dirty_3d |= NVC0_NEW_3D_TEVLPROG;
    679 }
    680 
    681 static void *
    682 nvc0_cp_state_create(struct pipe_context *pipe,
    683                      const struct pipe_compute_state *cso)
    684 {
    685    struct nvc0_program *prog;
    686 
    687    prog = CALLOC_STRUCT(nvc0_program);
    688    if (!prog)
    689       return NULL;
    690    prog->type = PIPE_SHADER_COMPUTE;
    691 
    692    prog->cp.smem_size = cso->req_local_mem;
    693    prog->cp.lmem_size = cso->req_private_mem;
    694    prog->parm_size = cso->req_input_mem;
    695 
    696    prog->pipe.tokens = tgsi_dup_tokens((const struct tgsi_token *)cso->prog);
    697 
    698    prog->translated = nvc0_program_translate(
    699       prog, nvc0_context(pipe)->screen->base.device->chipset,
    700       &nouveau_context(pipe)->debug);
    701 
    702    return (void *)prog;
    703 }
    704 
    705 static void
    706 nvc0_cp_state_bind(struct pipe_context *pipe, void *hwcso)
    707 {
    708     struct nvc0_context *nvc0 = nvc0_context(pipe);
    709 
    710     nvc0->compprog = hwcso;
    711     nvc0->dirty_cp |= NVC0_NEW_CP_PROGRAM;
    712 }
    713 
    714 static void
    715 nvc0_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
    716                          const struct pipe_constant_buffer *cb)
    717 {
    718    struct nvc0_context *nvc0 = nvc0_context(pipe);
    719    struct pipe_resource *res = cb ? cb->buffer : NULL;
    720    const unsigned s = nvc0_shader_stage(shader);
    721    const unsigned i = index;
    722 
    723    if (unlikely(shader == PIPE_SHADER_COMPUTE)) {
    724       if (nvc0->constbuf[s][i].user)
    725          nvc0->constbuf[s][i].u.buf = NULL;
    726       else
    727       if (nvc0->constbuf[s][i].u.buf)
    728          nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_CB(i));
    729 
    730       nvc0->dirty_cp |= NVC0_NEW_CP_CONSTBUF;
    731    } else {
    732       if (nvc0->constbuf[s][i].user)
    733          nvc0->constbuf[s][i].u.buf = NULL;
    734       else
    735       if (nvc0->constbuf[s][i].u.buf)
    736          nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_CB(s, i));
    737 
    738       nvc0->dirty_3d |= NVC0_NEW_3D_CONSTBUF;
    739    }
    740    nvc0->constbuf_dirty[s] |= 1 << i;
    741 
    742    if (nvc0->constbuf[s][i].u.buf)
    743       nv04_resource(nvc0->constbuf[s][i].u.buf)->cb_bindings[s] &= ~(1 << i);
    744    pipe_resource_reference(&nvc0->constbuf[s][i].u.buf, res);
    745 
    746    nvc0->constbuf[s][i].user = (cb && cb->user_buffer) ? true : false;
    747    if (nvc0->constbuf[s][i].user) {
    748       nvc0->constbuf[s][i].u.data = cb->user_buffer;
    749       nvc0->constbuf[s][i].size = MIN2(cb->buffer_size, 0x10000);
    750       nvc0->constbuf_valid[s] |= 1 << i;
    751       nvc0->constbuf_coherent[s] &= ~(1 << i);
    752    } else
    753    if (cb) {
    754       nvc0->constbuf[s][i].offset = cb->buffer_offset;
    755       nvc0->constbuf[s][i].size = MIN2(align(cb->buffer_size, 0x100), 0x10000);
    756       nvc0->constbuf_valid[s] |= 1 << i;
    757       if (res && res->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT)
    758          nvc0->constbuf_coherent[s] |= 1 << i;
    759       else
    760          nvc0->constbuf_coherent[s] &= ~(1 << i);
    761    }
    762    else {
    763       nvc0->constbuf_valid[s] &= ~(1 << i);
    764       nvc0->constbuf_coherent[s] &= ~(1 << i);
    765    }
    766 }
    767 
    768 /* =============================================================================
    769  */
    770 
    771 static void
    772 nvc0_set_blend_color(struct pipe_context *pipe,
    773                      const struct pipe_blend_color *bcol)
    774 {
    775     struct nvc0_context *nvc0 = nvc0_context(pipe);
    776 
    777     nvc0->blend_colour = *bcol;
    778     nvc0->dirty_3d |= NVC0_NEW_3D_BLEND_COLOUR;
    779 }
    780 
    781 static void
    782 nvc0_set_stencil_ref(struct pipe_context *pipe,
    783                      const struct pipe_stencil_ref *sr)
    784 {
    785     struct nvc0_context *nvc0 = nvc0_context(pipe);
    786 
    787     nvc0->stencil_ref = *sr;
    788     nvc0->dirty_3d |= NVC0_NEW_3D_STENCIL_REF;
    789 }
    790 
    791 static void
    792 nvc0_set_clip_state(struct pipe_context *pipe,
    793                     const struct pipe_clip_state *clip)
    794 {
    795     struct nvc0_context *nvc0 = nvc0_context(pipe);
    796 
    797     memcpy(nvc0->clip.ucp, clip->ucp, sizeof(clip->ucp));
    798 
    799     nvc0->dirty_3d |= NVC0_NEW_3D_CLIP;
    800 }
    801 
    802 static void
    803 nvc0_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask)
    804 {
    805     struct nvc0_context *nvc0 = nvc0_context(pipe);
    806 
    807     nvc0->sample_mask = sample_mask;
    808     nvc0->dirty_3d |= NVC0_NEW_3D_SAMPLE_MASK;
    809 }
    810 
    811 static void
    812 nvc0_set_min_samples(struct pipe_context *pipe, unsigned min_samples)
    813 {
    814    struct nvc0_context *nvc0 = nvc0_context(pipe);
    815 
    816    if (nvc0->min_samples != min_samples) {
    817       nvc0->min_samples = min_samples;
    818       nvc0->dirty_3d |= NVC0_NEW_3D_MIN_SAMPLES;
    819    }
    820 }
    821 
    822 static void
    823 nvc0_set_framebuffer_state(struct pipe_context *pipe,
    824                            const struct pipe_framebuffer_state *fb)
    825 {
    826     struct nvc0_context *nvc0 = nvc0_context(pipe);
    827 
    828     nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_FB);
    829 
    830     util_copy_framebuffer_state(&nvc0->framebuffer, fb);
    831 
    832     nvc0->dirty_3d |= NVC0_NEW_3D_FRAMEBUFFER;
    833 }
    834 
    835 static void
    836 nvc0_set_polygon_stipple(struct pipe_context *pipe,
    837                          const struct pipe_poly_stipple *stipple)
    838 {
    839     struct nvc0_context *nvc0 = nvc0_context(pipe);
    840 
    841     nvc0->stipple = *stipple;
    842     nvc0->dirty_3d |= NVC0_NEW_3D_STIPPLE;
    843 }
    844 
    845 static void
    846 nvc0_set_scissor_states(struct pipe_context *pipe,
    847                         unsigned start_slot,
    848                         unsigned num_scissors,
    849                         const struct pipe_scissor_state *scissor)
    850 {
    851    struct nvc0_context *nvc0 = nvc0_context(pipe);
    852    int i;
    853 
    854    assert(start_slot + num_scissors <= NVC0_MAX_VIEWPORTS);
    855    for (i = 0; i < num_scissors; i++) {
    856       if (!memcmp(&nvc0->scissors[start_slot + i], &scissor[i], sizeof(*scissor)))
    857          continue;
    858       nvc0->scissors[start_slot + i] = scissor[i];
    859       nvc0->scissors_dirty |= 1 << (start_slot + i);
    860       nvc0->dirty_3d |= NVC0_NEW_3D_SCISSOR;
    861    }
    862 }
    863 
    864 static void
    865 nvc0_set_viewport_states(struct pipe_context *pipe,
    866                          unsigned start_slot,
    867                          unsigned num_viewports,
    868                          const struct pipe_viewport_state *vpt)
    869 {
    870    struct nvc0_context *nvc0 = nvc0_context(pipe);
    871    int i;
    872 
    873    assert(start_slot + num_viewports <= NVC0_MAX_VIEWPORTS);
    874    for (i = 0; i < num_viewports; i++) {
    875       if (!memcmp(&nvc0->viewports[start_slot + i], &vpt[i], sizeof(*vpt)))
    876          continue;
    877       nvc0->viewports[start_slot + i] = vpt[i];
    878       nvc0->viewports_dirty |= 1 << (start_slot + i);
    879       nvc0->dirty_3d |= NVC0_NEW_3D_VIEWPORT;
    880    }
    881 
    882 }
    883 
    884 static void
    885 nvc0_set_window_rectangles(struct pipe_context *pipe,
    886                            boolean include,
    887                            unsigned num_rectangles,
    888                            const struct pipe_scissor_state *rectangles)
    889 {
    890    struct nvc0_context *nvc0 = nvc0_context(pipe);
    891 
    892    nvc0->window_rect.inclusive = include;
    893    nvc0->window_rect.rects = MIN2(num_rectangles, NVC0_MAX_WINDOW_RECTANGLES);
    894    memcpy(nvc0->window_rect.rect, rectangles,
    895           sizeof(struct pipe_scissor_state) * nvc0->window_rect.rects);
    896 
    897    nvc0->dirty_3d |= NVC0_NEW_3D_WINDOW_RECTS;
    898 }
    899 
    900 static void
    901 nvc0_set_tess_state(struct pipe_context *pipe,
    902                     const float default_tess_outer[4],
    903                     const float default_tess_inner[2])
    904 {
    905    struct nvc0_context *nvc0 = nvc0_context(pipe);
    906 
    907    memcpy(nvc0->default_tess_outer, default_tess_outer, 4 * sizeof(float));
    908    memcpy(nvc0->default_tess_inner, default_tess_inner, 2 * sizeof(float));
    909    nvc0->dirty_3d |= NVC0_NEW_3D_TESSFACTOR;
    910 }
    911 
    912 static void
    913 nvc0_set_vertex_buffers(struct pipe_context *pipe,
    914                         unsigned start_slot, unsigned count,
    915                         const struct pipe_vertex_buffer *vb)
    916 {
    917     struct nvc0_context *nvc0 = nvc0_context(pipe);
    918     unsigned i;
    919 
    920     nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_VTX);
    921     nvc0->dirty_3d |= NVC0_NEW_3D_ARRAYS;
    922 
    923     util_set_vertex_buffers_count(nvc0->vtxbuf, &nvc0->num_vtxbufs, vb,
    924                                   start_slot, count);
    925 
    926     if (!vb) {
    927        nvc0->vbo_user &= ~(((1ull << count) - 1) << start_slot);
    928        nvc0->constant_vbos &= ~(((1ull << count) - 1) << start_slot);
    929        nvc0->vtxbufs_coherent &= ~(((1ull << count) - 1) << start_slot);
    930        return;
    931     }
    932 
    933     for (i = 0; i < count; ++i) {
    934        unsigned dst_index = start_slot + i;
    935 
    936        if (vb[i].user_buffer) {
    937           nvc0->vbo_user |= 1 << dst_index;
    938           if (!vb[i].stride && nvc0->screen->eng3d->oclass < GM107_3D_CLASS)
    939              nvc0->constant_vbos |= 1 << dst_index;
    940           else
    941              nvc0->constant_vbos &= ~(1 << dst_index);
    942           nvc0->vtxbufs_coherent &= ~(1 << dst_index);
    943        } else {
    944           nvc0->vbo_user &= ~(1 << dst_index);
    945           nvc0->constant_vbos &= ~(1 << dst_index);
    946 
    947           if (vb[i].buffer &&
    948               vb[i].buffer->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT)
    949              nvc0->vtxbufs_coherent |= (1 << dst_index);
    950           else
    951              nvc0->vtxbufs_coherent &= ~(1 << dst_index);
    952        }
    953     }
    954 }
    955 
    956 static void
    957 nvc0_set_index_buffer(struct pipe_context *pipe,
    958                       const struct pipe_index_buffer *ib)
    959 {
    960     struct nvc0_context *nvc0 = nvc0_context(pipe);
    961 
    962     if (nvc0->idxbuf.buffer)
    963        nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_IDX);
    964 
    965     if (ib) {
    966        pipe_resource_reference(&nvc0->idxbuf.buffer, ib->buffer);
    967        nvc0->idxbuf.index_size = ib->index_size;
    968        if (ib->buffer) {
    969           nvc0->idxbuf.offset = ib->offset;
    970           nvc0->dirty_3d |= NVC0_NEW_3D_IDXBUF;
    971        } else {
    972           nvc0->idxbuf.user_buffer = ib->user_buffer;
    973           nvc0->dirty_3d &= ~NVC0_NEW_3D_IDXBUF;
    974        }
    975     } else {
    976        nvc0->dirty_3d &= ~NVC0_NEW_3D_IDXBUF;
    977        pipe_resource_reference(&nvc0->idxbuf.buffer, NULL);
    978     }
    979 }
    980 
    981 static void
    982 nvc0_vertex_state_bind(struct pipe_context *pipe, void *hwcso)
    983 {
    984     struct nvc0_context *nvc0 = nvc0_context(pipe);
    985 
    986     nvc0->vertex = hwcso;
    987     nvc0->dirty_3d |= NVC0_NEW_3D_VERTEX;
    988 }
    989 
    990 static struct pipe_stream_output_target *
    991 nvc0_so_target_create(struct pipe_context *pipe,
    992                       struct pipe_resource *res,
    993                       unsigned offset, unsigned size)
    994 {
    995    struct nv04_resource *buf = (struct nv04_resource *)res;
    996    struct nvc0_so_target *targ = MALLOC_STRUCT(nvc0_so_target);
    997    if (!targ)
    998       return NULL;
    999 
   1000    targ->pq = pipe->create_query(pipe, NVC0_HW_QUERY_TFB_BUFFER_OFFSET, 0);
   1001    if (!targ->pq) {
   1002       FREE(targ);
   1003       return NULL;
   1004    }
   1005    targ->clean = true;
   1006 
   1007    targ->pipe.buffer_size = size;
   1008    targ->pipe.buffer_offset = offset;
   1009    targ->pipe.context = pipe;
   1010    targ->pipe.buffer = NULL;
   1011    pipe_resource_reference(&targ->pipe.buffer, res);
   1012    pipe_reference_init(&targ->pipe.reference, 1);
   1013 
   1014    assert(buf->base.target == PIPE_BUFFER);
   1015    util_range_add(&buf->valid_buffer_range, offset, offset + size);
   1016 
   1017    return &targ->pipe;
   1018 }
   1019 
   1020 static void
   1021 nvc0_so_target_save_offset(struct pipe_context *pipe,
   1022                            struct pipe_stream_output_target *ptarg,
   1023                            unsigned index, bool *serialize)
   1024 {
   1025    struct nvc0_so_target *targ = nvc0_so_target(ptarg);
   1026 
   1027    if (*serialize) {
   1028       *serialize = false;
   1029       PUSH_SPACE(nvc0_context(pipe)->base.pushbuf, 1);
   1030       IMMED_NVC0(nvc0_context(pipe)->base.pushbuf, NVC0_3D(SERIALIZE), 0);
   1031 
   1032       NOUVEAU_DRV_STAT(nouveau_screen(pipe->screen), gpu_serialize_count, 1);
   1033    }
   1034 
   1035    nvc0_query(targ->pq)->index = index;
   1036    pipe->end_query(pipe, targ->pq);
   1037 }
   1038 
   1039 static void
   1040 nvc0_so_target_destroy(struct pipe_context *pipe,
   1041                        struct pipe_stream_output_target *ptarg)
   1042 {
   1043    struct nvc0_so_target *targ = nvc0_so_target(ptarg);
   1044    pipe->destroy_query(pipe, targ->pq);
   1045    pipe_resource_reference(&targ->pipe.buffer, NULL);
   1046    FREE(targ);
   1047 }
   1048 
   1049 static void
   1050 nvc0_set_transform_feedback_targets(struct pipe_context *pipe,
   1051                                     unsigned num_targets,
   1052                                     struct pipe_stream_output_target **targets,
   1053                                     const unsigned *offsets)
   1054 {
   1055    struct nvc0_context *nvc0 = nvc0_context(pipe);
   1056    unsigned i;
   1057    bool serialize = true;
   1058 
   1059    assert(num_targets <= 4);
   1060 
   1061    for (i = 0; i < num_targets; ++i) {
   1062       const bool changed = nvc0->tfbbuf[i] != targets[i];
   1063       const bool append = (offsets[i] == ((unsigned)-1));
   1064       if (!changed && append)
   1065          continue;
   1066       nvc0->tfbbuf_dirty |= 1 << i;
   1067 
   1068       if (nvc0->tfbbuf[i] && changed)
   1069          nvc0_so_target_save_offset(pipe, nvc0->tfbbuf[i], i, &serialize);
   1070 
   1071       if (targets[i] && !append)
   1072          nvc0_so_target(targets[i])->clean = true;
   1073 
   1074       pipe_so_target_reference(&nvc0->tfbbuf[i], targets[i]);
   1075    }
   1076    for (; i < nvc0->num_tfbbufs; ++i) {
   1077       if (nvc0->tfbbuf[i]) {
   1078          nvc0->tfbbuf_dirty |= 1 << i;
   1079          nvc0_so_target_save_offset(pipe, nvc0->tfbbuf[i], i, &serialize);
   1080          pipe_so_target_reference(&nvc0->tfbbuf[i], NULL);
   1081       }
   1082    }
   1083    nvc0->num_tfbbufs = num_targets;
   1084 
   1085    if (nvc0->tfbbuf_dirty) {
   1086       nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_TFB);
   1087       nvc0->dirty_3d |= NVC0_NEW_3D_TFB_TARGETS;
   1088    }
   1089 }
   1090 
   1091 static void
   1092 nvc0_bind_surfaces_range(struct nvc0_context *nvc0, const unsigned t,
   1093                          unsigned start, unsigned nr,
   1094                          struct pipe_surface **psurfaces)
   1095 {
   1096    const unsigned end = start + nr;
   1097    const unsigned mask = ((1 << nr) - 1) << start;
   1098    unsigned i;
   1099 
   1100    if (psurfaces) {
   1101       for (i = start; i < end; ++i) {
   1102          const unsigned p = i - start;
   1103          if (psurfaces[p])
   1104             nvc0->surfaces_valid[t] |= (1 << i);
   1105          else
   1106             nvc0->surfaces_valid[t] &= ~(1 << i);
   1107          pipe_surface_reference(&nvc0->surfaces[t][i], psurfaces[p]);
   1108       }
   1109    } else {
   1110       for (i = start; i < end; ++i)
   1111          pipe_surface_reference(&nvc0->surfaces[t][i], NULL);
   1112       nvc0->surfaces_valid[t] &= ~mask;
   1113    }
   1114    nvc0->surfaces_dirty[t] |= mask;
   1115 
   1116    if (t == 0)
   1117       nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_SUF);
   1118    else
   1119       nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_SUF);
   1120 }
   1121 
   1122 static void
   1123 nvc0_set_compute_resources(struct pipe_context *pipe,
   1124                            unsigned start, unsigned nr,
   1125                            struct pipe_surface **resources)
   1126 {
   1127    nvc0_bind_surfaces_range(nvc0_context(pipe), 1, start, nr, resources);
   1128 
   1129    nvc0_context(pipe)->dirty_cp |= NVC0_NEW_CP_SURFACES;
   1130 }
   1131 
   1132 static bool
   1133 nvc0_bind_images_range(struct nvc0_context *nvc0, const unsigned s,
   1134                        unsigned start, unsigned nr,
   1135                        const struct pipe_image_view *pimages)
   1136 {
   1137    const unsigned end = start + nr;
   1138    unsigned mask = 0;
   1139    unsigned i;
   1140 
   1141    assert(s < 6);
   1142 
   1143    if (pimages) {
   1144       for (i = start; i < end; ++i) {
   1145          struct pipe_image_view *img = &nvc0->images[s][i];
   1146          const unsigned p = i - start;
   1147 
   1148          if (img->resource == pimages[p].resource &&
   1149              img->format == pimages[p].format &&
   1150              img->access == pimages[p].access) {
   1151             if (img->resource == NULL)
   1152                continue;
   1153             if (img->resource->target == PIPE_BUFFER &&
   1154                 img->u.buf.offset == pimages[p].u.buf.offset &&
   1155                 img->u.buf.size == pimages[p].u.buf.size)
   1156                continue;
   1157             if (img->resource->target != PIPE_BUFFER &&
   1158                 img->u.tex.first_layer == pimages[p].u.tex.first_layer &&
   1159                 img->u.tex.last_layer == pimages[p].u.tex.last_layer &&
   1160                 img->u.tex.level == pimages[p].u.tex.level)
   1161                continue;
   1162          }
   1163 
   1164          mask |= (1 << i);
   1165          if (pimages[p].resource)
   1166             nvc0->images_valid[s] |= (1 << i);
   1167          else
   1168             nvc0->images_valid[s] &= ~(1 << i);
   1169 
   1170          img->format = pimages[p].format;
   1171          img->access = pimages[p].access;
   1172          if (pimages[p].resource && pimages[p].resource->target == PIPE_BUFFER)
   1173             img->u.buf = pimages[p].u.buf;
   1174          else
   1175             img->u.tex = pimages[p].u.tex;
   1176 
   1177          pipe_resource_reference(
   1178                &img->resource, pimages[p].resource);
   1179 
   1180          if (nvc0->screen->base.class_3d >= GM107_3D_CLASS) {
   1181             if (nvc0->images_tic[s][i]) {
   1182                struct nv50_tic_entry *old =
   1183                   nv50_tic_entry(nvc0->images_tic[s][i]);
   1184                nvc0_screen_tic_unlock(nvc0->screen, old);
   1185                pipe_sampler_view_reference(&nvc0->images_tic[s][i], NULL);
   1186             }
   1187 
   1188             nvc0->images_tic[s][i] =
   1189                gm107_create_texture_view_from_image(&nvc0->base.pipe,
   1190                                                     &pimages[p]);
   1191          }
   1192       }
   1193       if (!mask)
   1194          return false;
   1195    } else {
   1196       mask = ((1 << nr) - 1) << start;
   1197       if (!(nvc0->images_valid[s] & mask))
   1198          return false;
   1199       for (i = start; i < end; ++i) {
   1200          pipe_resource_reference(&nvc0->images[s][i].resource, NULL);
   1201          if (nvc0->screen->base.class_3d >= GM107_3D_CLASS) {
   1202             struct nv50_tic_entry *old = nv50_tic_entry(nvc0->images_tic[s][i]);
   1203             if (old) {
   1204                nvc0_screen_tic_unlock(nvc0->screen, old);
   1205                pipe_sampler_view_reference(&nvc0->images_tic[s][i], NULL);
   1206             }
   1207          }
   1208       }
   1209       nvc0->images_valid[s] &= ~mask;
   1210    }
   1211    nvc0->images_dirty[s] |= mask;
   1212 
   1213    if (s == 5)
   1214       nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_SUF);
   1215    else
   1216       nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_SUF);
   1217 
   1218    return true;
   1219 }
   1220 
   1221 static void
   1222 nvc0_set_shader_images(struct pipe_context *pipe,
   1223                        enum pipe_shader_type shader,
   1224                        unsigned start, unsigned nr,
   1225                        const struct pipe_image_view *images)
   1226 {
   1227    const unsigned s = nvc0_shader_stage(shader);
   1228    if (!nvc0_bind_images_range(nvc0_context(pipe), s, start, nr, images))
   1229       return;
   1230 
   1231    if (s == 5)
   1232       nvc0_context(pipe)->dirty_cp |= NVC0_NEW_CP_SURFACES;
   1233    else
   1234       nvc0_context(pipe)->dirty_3d |= NVC0_NEW_3D_SURFACES;
   1235 }
   1236 
   1237 static bool
   1238 nvc0_bind_buffers_range(struct nvc0_context *nvc0, const unsigned t,
   1239                         unsigned start, unsigned nr,
   1240                         const struct pipe_shader_buffer *pbuffers)
   1241 {
   1242    const unsigned end = start + nr;
   1243    unsigned mask = 0;
   1244    unsigned i;
   1245 
   1246    assert(t < 6);
   1247 
   1248    if (pbuffers) {
   1249       for (i = start; i < end; ++i) {
   1250          struct pipe_shader_buffer *buf = &nvc0->buffers[t][i];
   1251          const unsigned p = i - start;
   1252          if (buf->buffer == pbuffers[p].buffer &&
   1253              buf->buffer_offset == pbuffers[p].buffer_offset &&
   1254              buf->buffer_size == pbuffers[p].buffer_size)
   1255             continue;
   1256 
   1257          mask |= (1 << i);
   1258          if (pbuffers[p].buffer)
   1259             nvc0->buffers_valid[t] |= (1 << i);
   1260          else
   1261             nvc0->buffers_valid[t] &= ~(1 << i);
   1262          buf->buffer_offset = pbuffers[p].buffer_offset;
   1263          buf->buffer_size = pbuffers[p].buffer_size;
   1264          pipe_resource_reference(&buf->buffer, pbuffers[p].buffer);
   1265       }
   1266       if (!mask)
   1267          return false;
   1268    } else {
   1269       mask = ((1 << nr) - 1) << start;
   1270       if (!(nvc0->buffers_valid[t] & mask))
   1271          return false;
   1272       for (i = start; i < end; ++i)
   1273          pipe_resource_reference(&nvc0->buffers[t][i].buffer, NULL);
   1274       nvc0->buffers_valid[t] &= ~mask;
   1275    }
   1276    nvc0->buffers_dirty[t] |= mask;
   1277 
   1278    if (t == 5)
   1279       nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_BUF);
   1280    else
   1281       nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_BUF);
   1282 
   1283    return true;
   1284 }
   1285 
   1286 static void
   1287 nvc0_set_shader_buffers(struct pipe_context *pipe,
   1288                         enum pipe_shader_type shader,
   1289                         unsigned start, unsigned nr,
   1290                         const struct pipe_shader_buffer *buffers)
   1291 {
   1292    const unsigned s = nvc0_shader_stage(shader);
   1293    if (!nvc0_bind_buffers_range(nvc0_context(pipe), s, start, nr, buffers))
   1294       return;
   1295 
   1296    if (s == 5)
   1297       nvc0_context(pipe)->dirty_cp |= NVC0_NEW_CP_BUFFERS;
   1298    else
   1299       nvc0_context(pipe)->dirty_3d |= NVC0_NEW_3D_BUFFERS;
   1300 }
   1301 
   1302 static inline void
   1303 nvc0_set_global_handle(uint32_t *phandle, struct pipe_resource *res)
   1304 {
   1305    struct nv04_resource *buf = nv04_resource(res);
   1306    if (buf) {
   1307       uint64_t limit = (buf->address + buf->base.width0) - 1;
   1308       if (limit < (1ULL << 32)) {
   1309          *phandle = (uint32_t)buf->address;
   1310       } else {
   1311          NOUVEAU_ERR("Cannot map into TGSI_RESOURCE_GLOBAL: "
   1312                      "resource not contained within 32-bit address space !\n");
   1313          *phandle = 0;
   1314       }
   1315    } else {
   1316       *phandle = 0;
   1317    }
   1318 }
   1319 
   1320 static void
   1321 nvc0_set_global_bindings(struct pipe_context *pipe,
   1322                          unsigned start, unsigned nr,
   1323                          struct pipe_resource **resources,
   1324                          uint32_t **handles)
   1325 {
   1326    struct nvc0_context *nvc0 = nvc0_context(pipe);
   1327    struct pipe_resource **ptr;
   1328    unsigned i;
   1329    const unsigned end = start + nr;
   1330 
   1331    if (nvc0->global_residents.size <= (end * sizeof(struct pipe_resource *))) {
   1332       const unsigned old_size = nvc0->global_residents.size;
   1333       const unsigned req_size = end * sizeof(struct pipe_resource *);
   1334       util_dynarray_resize(&nvc0->global_residents, req_size);
   1335       memset((uint8_t *)nvc0->global_residents.data + old_size, 0,
   1336              req_size - old_size);
   1337    }
   1338 
   1339    if (resources) {
   1340       ptr = util_dynarray_element(
   1341          &nvc0->global_residents, struct pipe_resource *, start);
   1342       for (i = 0; i < nr; ++i) {
   1343          pipe_resource_reference(&ptr[i], resources[i]);
   1344          nvc0_set_global_handle(handles[i], resources[i]);
   1345       }
   1346    } else {
   1347       ptr = util_dynarray_element(
   1348          &nvc0->global_residents, struct pipe_resource *, start);
   1349       for (i = 0; i < nr; ++i)
   1350          pipe_resource_reference(&ptr[i], NULL);
   1351    }
   1352 
   1353    nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_GLOBAL);
   1354 
   1355    nvc0->dirty_cp |= NVC0_NEW_CP_GLOBALS;
   1356 }
   1357 
   1358 void
   1359 nvc0_init_state_functions(struct nvc0_context *nvc0)
   1360 {
   1361    struct pipe_context *pipe = &nvc0->base.pipe;
   1362 
   1363    pipe->create_blend_state = nvc0_blend_state_create;
   1364    pipe->bind_blend_state = nvc0_blend_state_bind;
   1365    pipe->delete_blend_state = nvc0_blend_state_delete;
   1366 
   1367    pipe->create_rasterizer_state = nvc0_rasterizer_state_create;
   1368    pipe->bind_rasterizer_state = nvc0_rasterizer_state_bind;
   1369    pipe->delete_rasterizer_state = nvc0_rasterizer_state_delete;
   1370 
   1371    pipe->create_depth_stencil_alpha_state = nvc0_zsa_state_create;
   1372    pipe->bind_depth_stencil_alpha_state = nvc0_zsa_state_bind;
   1373    pipe->delete_depth_stencil_alpha_state = nvc0_zsa_state_delete;
   1374 
   1375    pipe->create_sampler_state = nv50_sampler_state_create;
   1376    pipe->delete_sampler_state = nvc0_sampler_state_delete;
   1377    pipe->bind_sampler_states = nvc0_bind_sampler_states;
   1378 
   1379    pipe->create_sampler_view = nvc0_create_sampler_view;
   1380    pipe->sampler_view_destroy = nvc0_sampler_view_destroy;
   1381    pipe->set_sampler_views = nvc0_set_sampler_views;
   1382 
   1383    pipe->create_vs_state = nvc0_vp_state_create;
   1384    pipe->create_fs_state = nvc0_fp_state_create;
   1385    pipe->create_gs_state = nvc0_gp_state_create;
   1386    pipe->create_tcs_state = nvc0_tcp_state_create;
   1387    pipe->create_tes_state = nvc0_tep_state_create;
   1388    pipe->bind_vs_state = nvc0_vp_state_bind;
   1389    pipe->bind_fs_state = nvc0_fp_state_bind;
   1390    pipe->bind_gs_state = nvc0_gp_state_bind;
   1391    pipe->bind_tcs_state = nvc0_tcp_state_bind;
   1392    pipe->bind_tes_state = nvc0_tep_state_bind;
   1393    pipe->delete_vs_state = nvc0_sp_state_delete;
   1394    pipe->delete_fs_state = nvc0_sp_state_delete;
   1395    pipe->delete_gs_state = nvc0_sp_state_delete;
   1396    pipe->delete_tcs_state = nvc0_sp_state_delete;
   1397    pipe->delete_tes_state = nvc0_sp_state_delete;
   1398 
   1399    pipe->create_compute_state = nvc0_cp_state_create;
   1400    pipe->bind_compute_state = nvc0_cp_state_bind;
   1401    pipe->delete_compute_state = nvc0_sp_state_delete;
   1402 
   1403    pipe->set_blend_color = nvc0_set_blend_color;
   1404    pipe->set_stencil_ref = nvc0_set_stencil_ref;
   1405    pipe->set_clip_state = nvc0_set_clip_state;
   1406    pipe->set_sample_mask = nvc0_set_sample_mask;
   1407    pipe->set_min_samples = nvc0_set_min_samples;
   1408    pipe->set_constant_buffer = nvc0_set_constant_buffer;
   1409    pipe->set_framebuffer_state = nvc0_set_framebuffer_state;
   1410    pipe->set_polygon_stipple = nvc0_set_polygon_stipple;
   1411    pipe->set_scissor_states = nvc0_set_scissor_states;
   1412    pipe->set_viewport_states = nvc0_set_viewport_states;
   1413    pipe->set_window_rectangles = nvc0_set_window_rectangles;
   1414    pipe->set_tess_state = nvc0_set_tess_state;
   1415 
   1416    pipe->create_vertex_elements_state = nvc0_vertex_state_create;
   1417    pipe->delete_vertex_elements_state = nvc0_vertex_state_delete;
   1418    pipe->bind_vertex_elements_state = nvc0_vertex_state_bind;
   1419 
   1420    pipe->set_vertex_buffers = nvc0_set_vertex_buffers;
   1421    pipe->set_index_buffer = nvc0_set_index_buffer;
   1422 
   1423    pipe->create_stream_output_target = nvc0_so_target_create;
   1424    pipe->stream_output_target_destroy = nvc0_so_target_destroy;
   1425    pipe->set_stream_output_targets = nvc0_set_transform_feedback_targets;
   1426 
   1427    pipe->set_global_binding = nvc0_set_global_bindings;
   1428    pipe->set_compute_resources = nvc0_set_compute_resources;
   1429    pipe->set_shader_images = nvc0_set_shader_images;
   1430    pipe->set_shader_buffers = nvc0_set_shader_buffers;
   1431 
   1432    nvc0->sample_mask = ~0;
   1433    nvc0->min_samples = 1;
   1434    nvc0->default_tess_outer[0] =
   1435    nvc0->default_tess_outer[1] =
   1436    nvc0->default_tess_outer[2] =
   1437    nvc0->default_tess_outer[3] = 1.0;
   1438    nvc0->default_tess_inner[0] =
   1439    nvc0->default_tess_inner[1] = 1.0;
   1440 }
   1441