nv50/ir/opt: improve post-multiply and check target for support
[mesa.git] / src / gallium / drivers / nv50 / nv50_state.c
index 799f49619d27b3f50bb338c89d4ee70594c80822..bf554427ca0d59a1a2f6cfa7e5622785b0bf06e5 100644 (file)
 
 #include "nouveau/nouveau_gldefs.h"
 
+/* Caveats:
+ *  ! pipe_sampler_state.normalized_coords is ignored - rectangle textures will
+ *     use non-normalized coordinates, everything else won't
+ *    (The relevant bit is in the TIC entry and not the TSC entry.)
+ *
+ *  ! pipe_sampler_state.seamless_cube_map is ignored - seamless filtering is
+ *     always activated on NVA0 +
+ *    (Give me the global bit, otherwise it's not worth the CPU work.)
+ *
+ *  ! pipe_sampler_state.border_color is not swizzled according to the texture
+ *     swizzle in pipe_sampler_view
+ *    (This will be ugly with indirect independent texture/sampler access,
+ *     we'd have to emulate the logic in the shader. GL doesn't have that,
+ *     D3D doesn't have swizzle, if we knew what we were implementing we'd be
+ *     good.)
+ *
+ *  ! pipe_rasterizer_state.line_last_pixel is ignored - it is never drawn
+ *
+ *  ! pipe_rasterizer_state.flatshade_first also applies to QUADS
+ *    (There's a GL query for that, forcing an exception is just ridiculous.)
+ *
+ *  ! pipe_rasterizer_state.gl_rasterization_rules is ignored - pixel centers
+ *     are always at half integer coordinates and the top-left rule applies
+ *    (There does not seem to be a hardware switch for this.)
+ *
+ *  ! pipe_rasterizer_state.sprite_coord_enable is masked with 0xff on NVC0
+ *    (The hardware only has 8 slots meant for TexCoord and we have to assign
+ *     in advance to maintain elegant separate shader objects.)
+ */
+
 static INLINE uint32_t
 nv50_colormask(unsigned mask)
 {
@@ -89,8 +119,9 @@ nv50_blend_state_create(struct pipe_context *pipe,
    struct nv50_blend_stateobj *so = CALLOC_STRUCT(nv50_blend_stateobj);
    int i;
    boolean emit_common_func = cso->rt[0].blend_enable;
+   uint32_t ms;
 
-   if (nv50_context(pipe)->screen->tesla->grclass >= NVA3_3D) {
+   if (nv50_context(pipe)->screen->tesla->oclass >= NVA3_3D_CLASS) {
       SB_BEGIN_3D(so, BLEND_INDEPENDENT, 1);
       SB_DATA    (so, cso->independent_blend_enable);
    }
@@ -111,7 +142,7 @@ nv50_blend_state_create(struct pipe_context *pipe,
             emit_common_func = TRUE;
       }
 
-      if (nv50_context(pipe)->screen->tesla->grclass >= NVA3_3D) {
+      if (nv50_context(pipe)->screen->tesla->oclass >= NVA3_3D_CLASS) {
          emit_common_func = FALSE;
 
          for (i = 0; i < 8; ++i) {
@@ -160,6 +191,15 @@ nv50_blend_state_create(struct pipe_context *pipe,
       SB_DATA    (so, nv50_colormask(cso->rt[0].colormask));
    }
 
+   ms = 0;
+   if (cso->alpha_to_coverage)
+      ms |= NV50_3D_MULTISAMPLE_CTRL_ALPHA_TO_COVERAGE;
+   if (cso->alpha_to_one)
+      ms |= NV50_3D_MULTISAMPLE_CTRL_ALPHA_TO_ONE;
+
+   SB_BEGIN_3D(so, MULTISAMPLE_CTRL, 1);
+   SB_DATA    (so, ms);
+
    assert(so->size <= (sizeof(so->state) / sizeof(so->state[0])));
    return so;
 }
@@ -185,6 +225,7 @@ nv50_rasterizer_state_create(struct pipe_context *pipe,
                              const struct pipe_rasterizer_state *cso)
 {
    struct nv50_rasterizer_stateobj *so;
+   uint32_t reg;
 
    so = CALLOC_STRUCT(nv50_rasterizer_stateobj);
    if (!so)
@@ -207,6 +248,9 @@ nv50_rasterizer_state_create(struct pipe_context *pipe,
    SB_BEGIN_3D(so, FRAG_COLOR_CLAMP_EN, 1);
    SB_DATA    (so, cso->clamp_fragment_color ? 0x11111111 : 0x00000000);
 
+   SB_BEGIN_3D(so, MULTISAMPLE_ENABLE, 1);
+   SB_DATA    (so, cso->multisample);
+
    SB_BEGIN_3D(so, LINE_WIDTH, 1);
    SB_DATA    (so, fui(cso->line_width));
    SB_BEGIN_3D(so, LINE_SMOOTH_ENABLE, 1);
@@ -265,7 +309,25 @@ nv50_rasterizer_state_create(struct pipe_context *pipe,
       SB_DATA    (so, fui(cso->offset_scale));
       SB_BEGIN_3D(so, POLYGON_OFFSET_UNITS, 1);
       SB_DATA    (so, fui(cso->offset_units * 2.0f));
+      SB_BEGIN_3D(so, POLYGON_OFFSET_CLAMP, 1);
+      SB_DATA    (so, fui(cso->offset_clamp));
+   }
+
+   if (cso->depth_clip) {
+      reg = 0;
+   } else {
+      reg =
+         NV50_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_NEAR |
+         NV50_3D_VIEW_VOLUME_CLIP_CTRL_DEPTH_CLAMP_FAR |
+         NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK1;
    }
+#ifndef NV50_SCISSORS_CLIPPING
+   reg |=
+      NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK7 |
+      NV50_3D_VIEW_VOLUME_CLIP_CTRL_UNK12_UNK1;
+#endif
+   SB_BEGIN_3D(so, VIEW_VOLUME_CLIP_CTRL, 1);
+   SB_DATA    (so, reg);
 
    assert(so->size <= (sizeof(so->state) / sizeof(so->state[0])));
    return (void *)so;
@@ -465,10 +527,10 @@ nv50_sampler_state_create(struct pipe_context *pipe,
    so->tsc[2] |=
       (((int)(f[1] * 256.0f) & 0xfff) << 12) | ((int)(f[0] * 256.0f) & 0xfff);
 
-   so->tsc[4] = fui(cso->border_color[0]);
-   so->tsc[5] = fui(cso->border_color[1]);
-   so->tsc[6] = fui(cso->border_color[2]);
-   so->tsc[7] = fui(cso->border_color[3]);
+   so->tsc[4] = fui(cso->border_color.f[0]);
+   so->tsc[5] = fui(cso->border_color.f[1]);
+   so->tsc[6] = fui(cso->border_color.f[2]);
+   so->tsc[7] = fui(cso->border_color.f[3]);
 
    return (void *)so;
 }
@@ -478,7 +540,7 @@ nv50_sampler_state_delete(struct pipe_context *pipe, void *hwcso)
 {
    unsigned s, i;
 
-   for (s = 0; s < 5; ++s)
+   for (s = 0; s < 3; ++s)
       for (i = 0; i < nv50_context(pipe)->num_samplers[s]; ++i)
          if (nv50_context(pipe)->samplers[s][i] == hwcso)
             nv50_context(pipe)->samplers[s][i] = NULL;
@@ -566,7 +628,7 @@ nv50_stage_set_sampler_views(struct nv50_context *nv50, int s,
 
    nv50->num_textures[s] = nr;
 
-   nv50_bufctx_reset(nv50, NV50_BUFCTX_TEXTURES);
+   nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_TEXTURES);
 
    nv50->dirty |= NV50_NEW_TEXTURES;
 }
@@ -679,13 +741,15 @@ nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
 {
    struct nv50_context *nv50 = nv50_context(pipe);
 
-   if (nv50->constbuf[shader][index])
-      nv50_bufctx_del_resident(nv50, NV50_BUFCTX_CONSTANT,
-                              nv04_resource(nv50->constbuf[shader][index]));
-
    pipe_resource_reference(&nv50->constbuf[shader][index], res);
 
    nv50->constbuf_dirty[shader] |= 1 << index;
+   if (res)
+      nv50->constbuf_valid[shader] |= 1 << index;
+   else
+      nv50->constbuf_valid[shader] &= ~(1 << index);
+
+   nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_CB(shader, index));
 
    nv50->dirty |= NV50_NEW_CONSTBUF;
 }
@@ -718,12 +782,8 @@ nv50_set_clip_state(struct pipe_context *pipe,
                     const struct pipe_clip_state *clip)
 {
    struct nv50_context *nv50 = nv50_context(pipe);
-   const unsigned size = clip->nr * sizeof(clip->ucp[0]);
-
-   memcpy(&nv50->clip.ucp[0][0], &clip->ucp[0][0], size);
-   nv50->clip.nr = clip->nr;
 
-   nv50->clip.depth_clamp = clip->depth_clamp;
+   memcpy(nv50->clip.ucp, clip->ucp, sizeof(clip->ucp));
 
    nv50->dirty |= NV50_NEW_CLIP;
 }
@@ -743,8 +803,22 @@ nv50_set_framebuffer_state(struct pipe_context *pipe,
                            const struct pipe_framebuffer_state *fb)
 {
    struct nv50_context *nv50 = nv50_context(pipe);
+   unsigned i;
+
+   nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_FB);
+
+   for (i = 0; i < fb->nr_cbufs; ++i)
+      pipe_surface_reference(&nv50->framebuffer.cbufs[i], fb->cbufs[i]);
+   for (; i < nv50->framebuffer.nr_cbufs; ++i)
+      pipe_surface_reference(&nv50->framebuffer.cbufs[i], NULL);
+
+   nv50->framebuffer.nr_cbufs = fb->nr_cbufs;
+
+   nv50->framebuffer.width = fb->width;
+   nv50->framebuffer.height = fb->height;
+
+   pipe_surface_reference(&nv50->framebuffer.zsbuf, fb->zsbuf);
 
-   nv50->framebuffer = *fb;
    nv50->dirty |= NV50_NEW_FRAMEBUFFER;
 }
 
@@ -794,7 +868,7 @@ nv50_set_vertex_buffers(struct pipe_context *pipe,
    memcpy(nv50->vtxbuf, vb, sizeof(*vb) * count);
    nv50->num_vtxbufs = count;
 
-   nv50_bufctx_reset(nv50, NV50_BUFCTX_VERTEX);
+   nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_VERTEX);
 
    nv50->dirty |= NV50_NEW_ARRAYS;
 }
@@ -805,10 +879,15 @@ nv50_set_index_buffer(struct pipe_context *pipe,
 {
    struct nv50_context *nv50 = nv50_context(pipe);
 
-   if (ib) {
-      pipe_resource_reference(&nv50->idxbuf.buffer, ib->buffer);
+   if (nv50->idxbuf.buffer)
+      nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_INDEX);
 
-      memcpy(&nv50->idxbuf, ib, sizeof(nv50->idxbuf));
+   if (ib && ib->buffer) {
+      pipe_resource_reference(&nv50->idxbuf.buffer, ib->buffer);
+      nv50->idxbuf.offset = ib->offset;
+      nv50->idxbuf.index_size = ib->index_size;
+      if (nouveau_resource_mapped_by_gpu(ib->buffer))
+         BCTX_REFN(nv50->bufctx_3d, INDEX, nv04_resource(ib->buffer), RD);
    } else {
       pipe_resource_reference(&nv50->idxbuf.buffer, NULL);
    }