Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1.  
  2. #include "nv50_context.h"
  3. #include "os/os_time.h"
  4.  
  5. static void
  6. nv50_validate_fb(struct nv50_context *nv50)
  7. {
  8.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  9.    struct pipe_framebuffer_state *fb = &nv50->framebuffer;
  10.    unsigned i;
  11.    unsigned ms_mode = NV50_3D_MULTISAMPLE_MODE_MS1;
  12.    uint32_t array_size = 0xffff, array_mode = 0;
  13.  
  14.    nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_FB);
  15.  
  16.    BEGIN_NV04(push, NV50_3D(RT_CONTROL), 1);
  17.    PUSH_DATA (push, (076543210 << 4) | fb->nr_cbufs);
  18.    BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2);
  19.    PUSH_DATA (push, fb->width << 16);
  20.    PUSH_DATA (push, fb->height << 16);
  21.  
  22.    for (i = 0; i < fb->nr_cbufs; ++i) {
  23.       struct nv50_miptree *mt = nv50_miptree(fb->cbufs[i]->texture);
  24.       struct nv50_surface *sf = nv50_surface(fb->cbufs[i]);
  25.       struct nouveau_bo *bo = mt->base.bo;
  26.  
  27.       array_size = MIN2(array_size, sf->depth);
  28.       if (mt->layout_3d)
  29.          array_mode = NV50_3D_RT_ARRAY_MODE_MODE_3D; /* 1 << 16 */
  30.  
  31.       /* can't mix 3D with ARRAY or have RTs of different depth/array_size */
  32.       assert(mt->layout_3d || !array_mode || array_size == 1);
  33.  
  34.       BEGIN_NV04(push, NV50_3D(RT_ADDRESS_HIGH(i)), 5);
  35.       PUSH_DATAh(push, bo->offset + sf->offset);
  36.       PUSH_DATA (push, bo->offset + sf->offset);
  37.       PUSH_DATA (push, nv50_format_table[sf->base.format].rt);
  38.       if (likely(nouveau_bo_memtype(bo))) {
  39.          PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode);
  40.          PUSH_DATA (push, mt->layer_stride >> 2);
  41.          BEGIN_NV04(push, NV50_3D(RT_HORIZ(i)), 2);
  42.          PUSH_DATA (push, sf->width);
  43.          PUSH_DATA (push, sf->height);
  44.          BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1);
  45.          PUSH_DATA (push, array_mode | array_size);
  46.       } else {
  47.          PUSH_DATA (push, 0);
  48.          PUSH_DATA (push, 0);
  49.          BEGIN_NV04(push, NV50_3D(RT_HORIZ(i)), 2);
  50.          PUSH_DATA (push, NV50_3D_RT_HORIZ_LINEAR | mt->level[0].pitch);
  51.          PUSH_DATA (push, sf->height);
  52.          BEGIN_NV04(push, NV50_3D(RT_ARRAY_MODE), 1);
  53.          PUSH_DATA (push, 0);
  54.  
  55.          assert(!fb->zsbuf);
  56.          assert(!mt->ms_mode);
  57.       }
  58.  
  59.       ms_mode = mt->ms_mode;
  60.  
  61.       if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
  62.          nv50->state.rt_serialize = TRUE;
  63.       mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
  64.       mt->base.status &= NOUVEAU_BUFFER_STATUS_GPU_READING;
  65.  
  66.       /* only register for writing, otherwise we'd always serialize here */
  67.       BCTX_REFN(nv50->bufctx_3d, FB, &mt->base, WR);
  68.    }
  69.  
  70.    if (fb->zsbuf) {
  71.       struct nv50_miptree *mt = nv50_miptree(fb->zsbuf->texture);
  72.       struct nv50_surface *sf = nv50_surface(fb->zsbuf);
  73.       struct nouveau_bo *bo = mt->base.bo;
  74.       int unk = mt->base.base.target == PIPE_TEXTURE_3D || sf->depth == 1;
  75.  
  76.       BEGIN_NV04(push, NV50_3D(ZETA_ADDRESS_HIGH), 5);
  77.       PUSH_DATAh(push, bo->offset + sf->offset);
  78.       PUSH_DATA (push, bo->offset + sf->offset);
  79.       PUSH_DATA (push, nv50_format_table[fb->zsbuf->format].rt);
  80.       PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode);
  81.       PUSH_DATA (push, mt->layer_stride >> 2);
  82.       BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);
  83.       PUSH_DATA (push, 1);
  84.       BEGIN_NV04(push, NV50_3D(ZETA_HORIZ), 3);
  85.       PUSH_DATA (push, sf->width);
  86.       PUSH_DATA (push, sf->height);
  87.       PUSH_DATA (push, (unk << 16) | sf->depth);
  88.  
  89.       ms_mode = mt->ms_mode;
  90.  
  91.       if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING)
  92.          nv50->state.rt_serialize = TRUE;
  93.       mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
  94.       mt->base.status &= NOUVEAU_BUFFER_STATUS_GPU_READING;
  95.  
  96.       BCTX_REFN(nv50->bufctx_3d, FB, &mt->base, WR);
  97.    } else {
  98.       BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);
  99.       PUSH_DATA (push, 0);
  100.    }
  101.  
  102.    BEGIN_NV04(push, NV50_3D(MULTISAMPLE_MODE), 1);
  103.    PUSH_DATA (push, ms_mode);
  104.  
  105.    BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2);
  106.    PUSH_DATA (push, fb->width << 16);
  107.    PUSH_DATA (push, fb->height << 16);
  108. }
  109.  
  110. static void
  111. nv50_validate_blend_colour(struct nv50_context *nv50)
  112. {
  113.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  114.  
  115.    BEGIN_NV04(push, NV50_3D(BLEND_COLOR(0)), 4);
  116.    PUSH_DATAf(push, nv50->blend_colour.color[0]);
  117.    PUSH_DATAf(push, nv50->blend_colour.color[1]);
  118.    PUSH_DATAf(push, nv50->blend_colour.color[2]);
  119.    PUSH_DATAf(push, nv50->blend_colour.color[3]);
  120. }
  121.  
  122. static void
  123. nv50_validate_stencil_ref(struct nv50_context *nv50)
  124. {
  125.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  126.  
  127.    BEGIN_NV04(push, NV50_3D(STENCIL_FRONT_FUNC_REF), 1);
  128.    PUSH_DATA (push, nv50->stencil_ref.ref_value[0]);
  129.    BEGIN_NV04(push, NV50_3D(STENCIL_BACK_FUNC_REF), 1);
  130.    PUSH_DATA (push, nv50->stencil_ref.ref_value[1]);
  131. }
  132.  
  133. static void
  134. nv50_validate_stipple(struct nv50_context *nv50)
  135. {
  136.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  137.    unsigned i;
  138.  
  139.    BEGIN_NV04(push, NV50_3D(POLYGON_STIPPLE_PATTERN(0)), 32);
  140.    for (i = 0; i < 32; ++i)
  141.       PUSH_DATA(push, util_bswap32(nv50->stipple.stipple[i]));
  142. }
  143.  
  144. static void
  145. nv50_validate_scissor(struct nv50_context *nv50)
  146. {
  147.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  148.    struct pipe_scissor_state *s = &nv50->scissor;
  149. #ifdef NV50_SCISSORS_CLIPPING
  150.    struct pipe_viewport_state *vp = &nv50->viewport;
  151.    int minx, maxx, miny, maxy;
  152.  
  153.    if (!(nv50->dirty &
  154.          (NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT | NV50_NEW_FRAMEBUFFER)) &&
  155.        nv50->state.scissor == nv50->rast->pipe.scissor)
  156.       return;
  157.    nv50->state.scissor = nv50->rast->pipe.scissor;
  158.  
  159.    if (nv50->state.scissor) {
  160.       minx = s->minx;
  161.       maxx = s->maxx;
  162.       miny = s->miny;
  163.       maxy = s->maxy;
  164.    } else {
  165.       minx = 0;
  166.       maxx = nv50->framebuffer.width;
  167.       miny = 0;
  168.       maxy = nv50->framebuffer.height;
  169.    }
  170.  
  171.    minx = MAX2(minx, (int)(vp->translate[0] - fabsf(vp->scale[0])));
  172.    maxx = MIN2(maxx, (int)(vp->translate[0] + fabsf(vp->scale[0])));
  173.    miny = MAX2(miny, (int)(vp->translate[1] - fabsf(vp->scale[1])));
  174.    maxy = MIN2(maxy, (int)(vp->translate[1] + fabsf(vp->scale[1])));
  175.  
  176.    BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2);
  177.    PUSH_DATA (push, (maxx << 16) | minx);
  178.    PUSH_DATA (push, (maxy << 16) | miny);
  179. #else
  180.    BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2);
  181.    PUSH_DATA (push, (s->maxx << 16) | s->minx);
  182.    PUSH_DATA (push, (s->maxy << 16) | s->miny);
  183. #endif
  184. }
  185.  
  186. static void
  187. nv50_validate_viewport(struct nv50_context *nv50)
  188. {
  189.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  190.    float zmin, zmax;
  191.  
  192.    BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSLATE_X(0)), 3);
  193.    PUSH_DATAf(push, nv50->viewport.translate[0]);
  194.    PUSH_DATAf(push, nv50->viewport.translate[1]);
  195.    PUSH_DATAf(push, nv50->viewport.translate[2]);
  196.    BEGIN_NV04(push, NV50_3D(VIEWPORT_SCALE_X(0)), 3);
  197.    PUSH_DATAf(push, nv50->viewport.scale[0]);
  198.    PUSH_DATAf(push, nv50->viewport.scale[1]);
  199.    PUSH_DATAf(push, nv50->viewport.scale[2]);
  200.  
  201.    zmin = nv50->viewport.translate[2] - fabsf(nv50->viewport.scale[2]);
  202.    zmax = nv50->viewport.translate[2] + fabsf(nv50->viewport.scale[2]);
  203.  
  204. #ifdef NV50_SCISSORS_CLIPPING
  205.    BEGIN_NV04(push, NV50_3D(DEPTH_RANGE_NEAR(0)), 2);
  206.    PUSH_DATAf(push, zmin);
  207.    PUSH_DATAf(push, zmax);
  208. #endif
  209. }
  210.  
  211. static INLINE void
  212. nv50_check_program_ucps(struct nv50_context *nv50,
  213.                         struct nv50_program *vp, uint8_t mask)
  214. {
  215.    const unsigned n = util_logbase2(mask) + 1;
  216.  
  217.    if (vp->vp.clpd_nr >= n)
  218.       return;
  219.    nv50_program_destroy(nv50, vp);
  220.  
  221.    vp->vp.clpd_nr = n;
  222.    if (likely(vp == nv50->vertprog)) {
  223.       nv50->dirty |= NV50_NEW_VERTPROG;
  224.       nv50_vertprog_validate(nv50);
  225.    } else {
  226.       nv50->dirty |= NV50_NEW_GMTYPROG;
  227.       nv50_gmtyprog_validate(nv50);
  228.    }
  229.    nv50_fp_linkage_validate(nv50);
  230. }
  231.  
  232. static void
  233. nv50_validate_clip(struct nv50_context *nv50)
  234. {
  235.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  236.    struct nv50_program *vp;
  237.    uint8_t clip_enable;
  238.  
  239.    if (nv50->dirty & NV50_NEW_CLIP) {
  240.       BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);
  241.       PUSH_DATA (push, (0 << 8) | NV50_CB_AUX);
  242.       BEGIN_NI04(push, NV50_3D(CB_DATA(0)), PIPE_MAX_CLIP_PLANES * 4);
  243.       PUSH_DATAp(push, &nv50->clip.ucp[0][0], PIPE_MAX_CLIP_PLANES * 4);
  244.    }
  245.  
  246.    vp = nv50->gmtyprog;
  247.    if (likely(!vp))
  248.       vp = nv50->vertprog;
  249.  
  250.    clip_enable = nv50->rast->pipe.clip_plane_enable;
  251.  
  252.    BEGIN_NV04(push, NV50_3D(CLIP_DISTANCE_ENABLE), 1);
  253.    PUSH_DATA (push, clip_enable);
  254.  
  255.    if (clip_enable)
  256.       nv50_check_program_ucps(nv50, vp, clip_enable);
  257. }
  258.  
  259. static void
  260. nv50_validate_blend(struct nv50_context *nv50)
  261. {
  262.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  263.  
  264.    PUSH_SPACE(push, nv50->blend->size);
  265.    PUSH_DATAp(push, nv50->blend->state, nv50->blend->size);
  266. }
  267.  
  268. static void
  269. nv50_validate_zsa(struct nv50_context *nv50)
  270. {
  271.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  272.  
  273.    PUSH_SPACE(push, nv50->zsa->size);
  274.    PUSH_DATAp(push, nv50->zsa->state, nv50->zsa->size);
  275. }
  276.  
  277. static void
  278. nv50_validate_rasterizer(struct nv50_context *nv50)
  279. {
  280.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  281.  
  282.    PUSH_SPACE(push, nv50->rast->size);
  283.    PUSH_DATAp(push, nv50->rast->state, nv50->rast->size);
  284. }
  285.  
  286. static void
  287. nv50_validate_sample_mask(struct nv50_context *nv50)
  288. {
  289.    struct nouveau_pushbuf *push = nv50->base.pushbuf;
  290.  
  291.    unsigned mask[4] =
  292.    {
  293.       nv50->sample_mask & 0xffff,
  294.       nv50->sample_mask & 0xffff,
  295.       nv50->sample_mask & 0xffff,
  296.       nv50->sample_mask & 0xffff
  297.    };
  298.  
  299.    BEGIN_NV04(push, NV50_3D(MSAA_MASK(0)), 4);
  300.    PUSH_DATA (push, mask[0]);
  301.    PUSH_DATA (push, mask[1]);
  302.    PUSH_DATA (push, mask[2]);
  303.    PUSH_DATA (push, mask[3]);
  304. }
  305.  
  306. static void
  307. nv50_switch_pipe_context(struct nv50_context *ctx_to)
  308. {
  309.    struct nv50_context *ctx_from = ctx_to->screen->cur_ctx;
  310.  
  311.    if (ctx_from)
  312.       ctx_to->state = ctx_from->state;
  313.  
  314.    ctx_to->dirty = ~0;
  315.  
  316.    if (!ctx_to->vertex)
  317.       ctx_to->dirty &= ~(NV50_NEW_VERTEX | NV50_NEW_ARRAYS);
  318.  
  319.    if (!ctx_to->vertprog)
  320.       ctx_to->dirty &= ~NV50_NEW_VERTPROG;
  321.    if (!ctx_to->fragprog)
  322.       ctx_to->dirty &= ~NV50_NEW_FRAGPROG;
  323.  
  324.    if (!ctx_to->blend)
  325.       ctx_to->dirty &= ~NV50_NEW_BLEND;
  326.    if (!ctx_to->rast)
  327. #ifdef NV50_SCISSORS_CLIPPING
  328.       ctx_to->dirty &= ~(NV50_NEW_RASTERIZER | NV50_NEW_SCISSOR);
  329. #else
  330.       ctx_to->dirty &= ~NV50_NEW_RASTERIZER;
  331. #endif
  332.    if (!ctx_to->zsa)
  333.       ctx_to->dirty &= ~NV50_NEW_ZSA;
  334.  
  335.    ctx_to->screen->cur_ctx = ctx_to;
  336. }
  337.  
  338. static struct state_validate {
  339.     void (*func)(struct nv50_context *);
  340.     uint32_t states;
  341. } validate_list[] = {
  342.     { nv50_validate_fb,            NV50_NEW_FRAMEBUFFER },
  343.     { nv50_validate_blend,         NV50_NEW_BLEND },
  344.     { nv50_validate_zsa,           NV50_NEW_ZSA },
  345.     { nv50_validate_sample_mask,   NV50_NEW_SAMPLE_MASK },
  346.     { nv50_validate_rasterizer,    NV50_NEW_RASTERIZER },
  347.     { nv50_validate_blend_colour,  NV50_NEW_BLEND_COLOUR },
  348.     { nv50_validate_stencil_ref,   NV50_NEW_STENCIL_REF },
  349.     { nv50_validate_stipple,       NV50_NEW_STIPPLE },
  350. #ifdef NV50_SCISSORS_CLIPPING
  351.     { nv50_validate_scissor,       NV50_NEW_SCISSOR | NV50_NEW_VIEWPORT |
  352.                                    NV50_NEW_RASTERIZER |
  353.                                    NV50_NEW_FRAMEBUFFER },
  354. #else
  355.     { nv50_validate_scissor,       NV50_NEW_SCISSOR },
  356. #endif
  357.     { nv50_validate_viewport,      NV50_NEW_VIEWPORT },
  358.     { nv50_vertprog_validate,      NV50_NEW_VERTPROG },
  359.     { nv50_gmtyprog_validate,      NV50_NEW_GMTYPROG },
  360.     { nv50_fragprog_validate,      NV50_NEW_FRAGPROG },
  361.     { nv50_fp_linkage_validate,    NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG |
  362.                                    NV50_NEW_GMTYPROG | NV50_NEW_RASTERIZER },
  363.     { nv50_gp_linkage_validate,    NV50_NEW_GMTYPROG | NV50_NEW_VERTPROG },
  364.     { nv50_validate_derived_rs,    NV50_NEW_FRAGPROG | NV50_NEW_RASTERIZER |
  365.                                    NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG },
  366.     { nv50_validate_clip,          NV50_NEW_CLIP | NV50_NEW_RASTERIZER |
  367.                                    NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG },
  368.     { nv50_constbufs_validate,     NV50_NEW_CONSTBUF },
  369.     { nv50_validate_textures,      NV50_NEW_TEXTURES },
  370.     { nv50_validate_samplers,      NV50_NEW_SAMPLERS },
  371.     { nv50_stream_output_validate, NV50_NEW_STRMOUT |
  372.                                    NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG },
  373.     { nv50_vertex_arrays_validate, NV50_NEW_VERTEX | NV50_NEW_ARRAYS }
  374. };
  375. #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
  376.  
  377. boolean
  378. nv50_state_validate(struct nv50_context *nv50, uint32_t mask, unsigned words)
  379. {
  380.    uint32_t state_mask;
  381.    int ret;
  382.    unsigned i;
  383.  
  384.    if (nv50->screen->cur_ctx != nv50)
  385.       nv50_switch_pipe_context(nv50);
  386.  
  387.    state_mask = nv50->dirty & mask;
  388.  
  389.    if (state_mask) {
  390.       for (i = 0; i < validate_list_len; ++i) {
  391.          struct state_validate *validate = &validate_list[i];
  392.  
  393.          if (state_mask & validate->states)
  394.             validate->func(nv50);
  395.       }
  396.       nv50->dirty &= ~state_mask;
  397.  
  398.       if (nv50->state.rt_serialize) {
  399.          nv50->state.rt_serialize = FALSE;
  400.          BEGIN_NV04(nv50->base.pushbuf, SUBC_3D(NV50_GRAPH_SERIALIZE), 1);
  401.          PUSH_DATA (nv50->base.pushbuf, 0);
  402.       }
  403.  
  404.       nv50_bufctx_fence(nv50->bufctx_3d, FALSE);
  405.    }
  406.    nouveau_pushbuf_bufctx(nv50->base.pushbuf, nv50->bufctx_3d);
  407.    ret = nouveau_pushbuf_validate(nv50->base.pushbuf);
  408.  
  409.    if (unlikely(nv50->state.flushed)) {
  410.       nv50->state.flushed = FALSE;
  411.       nv50_bufctx_fence(nv50->bufctx_3d, TRUE);
  412.    }
  413.    return !ret;
  414. }
  415.