示例#1
0
static void
nv30_set_framebuffer_state(struct pipe_context *pipe,
                           const struct pipe_framebuffer_state *fb)
{
    struct nv30_context *nv30 = nv30_context(pipe);

    nouveau_bufctx_reset(nv30->bufctx, BUFCTX_FB);

    nv30->framebuffer = *fb;
    nv30->dirty |= NV30_NEW_FRAMEBUFFER;

   /* Hardware can't handle different swizzled-ness or different blocksizes
    * for zs and cbufs. If both are supplied and something doesn't match,
    * blank out the zs for now so that at least *some* rendering can occur.
    */
    if (fb->nr_cbufs > 0 && fb->zsbuf) {
       struct nv30_miptree *color_mt = nv30_miptree(fb->cbufs[0]->texture);
       struct nv30_miptree *zeta_mt = nv30_miptree(fb->zsbuf->texture);

       if (color_mt->swizzled != zeta_mt->swizzled ||
           (util_format_get_blocksize(fb->zsbuf->format) > 2) !=
           (util_format_get_blocksize(fb->cbufs[0]->format) > 2)) {
          nv30->framebuffer.zsbuf = NULL;
          debug_printf("Mismatched color and zeta formats, ignoring zeta.\n");
       }
    }
}
示例#2
0
static void
nv30_clear_render_target(struct pipe_context *pipe, struct pipe_surface *ps,
                         const union pipe_color_union *color,
                         unsigned x, unsigned y, unsigned w, unsigned h)
{
   struct nv30_context *nv30 = nv30_context(pipe);
   struct nv30_surface *sf = nv30_surface(ps);
   struct nv30_miptree *mt = nv30_miptree(ps->texture);
   struct nouveau_pushbuf *push = nv30->base.pushbuf;
   struct nouveau_object *eng3d = nv30->screen->eng3d;
   struct nouveau_pushbuf_refn refn;
   uint32_t rt_format;

   rt_format = nv30_format(pipe->screen, ps->format)->hw;
   if (util_format_get_blocksize(ps->format) == 4)
      rt_format |= NV30_3D_RT_FORMAT_ZETA_Z24S8;
   else
      rt_format |= NV30_3D_RT_FORMAT_ZETA_Z16;

   if (nv30_miptree(ps->texture)->swizzled) {
      rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
      rt_format |= util_logbase2(sf->width) << 16;
      rt_format |= util_logbase2(sf->height) << 24;
   } else {
      rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
   }

   refn.bo = mt->base.bo;
   refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR;
   if (nouveau_pushbuf_space(push, 16, 1, 0) ||
       nouveau_pushbuf_refn (push, &refn, 1))
      return;

   BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
   PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0);
   BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3);
   PUSH_DATA (push, sf->width << 16);
   PUSH_DATA (push, sf->height << 16);
   PUSH_DATA (push, rt_format);
   BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 2);
   if (eng3d->oclass < NV40_3D_CLASS)
      PUSH_DATA (push, (sf->pitch << 16) | sf->pitch);
   else
      PUSH_DATA (push, sf->pitch);
   PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0);
   BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
   PUSH_DATA (push, (w << 16) | x);
   PUSH_DATA (push, (h << 16) | y);

   BEGIN_NV04(push, NV30_3D(CLEAR_COLOR_VALUE), 2);
   PUSH_DATA (push, pack_rgba(ps->format, color->f));
   PUSH_DATA (push, NV30_3D_CLEAR_BUFFERS_COLOR_R |
                    NV30_3D_CLEAR_BUFFERS_COLOR_G |
                    NV30_3D_CLEAR_BUFFERS_COLOR_B |
                    NV30_3D_CLEAR_BUFFERS_COLOR_A);

   nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR;
}
示例#3
0
static INLINE void
define_rect(struct pipe_resource *pt, unsigned level, unsigned z,
            unsigned x, unsigned y, unsigned w, unsigned h,
            struct nv30_rect *rect)
{
   struct nv30_miptree *mt = nv30_miptree(pt);
   struct nv30_miptree_level *lvl = &mt->level[level];

   rect->w = u_minify(pt->width0, level) << mt->ms_x;
   rect->w = util_format_get_nblocksx(pt->format, rect->w);
   rect->h = u_minify(pt->height0, level) << mt->ms_y;
   rect->h = util_format_get_nblocksy(pt->format, rect->h);
   rect->d = 1;
   rect->z = 0;
   if (mt->swizzled) {
      if (pt->target == PIPE_TEXTURE_3D) {
         rect->d = u_minify(pt->depth0, level);
         rect->z = z; z = 0;
      }
      rect->pitch = 0;
   } else {
      rect->pitch = lvl->pitch;
   }

   rect->bo     = mt->base.bo;
   rect->domain = NOUVEAU_BO_VRAM;
   rect->offset = layer_offset(pt, level, z);
   rect->cpp    = util_format_get_blocksize(pt->format);

   rect->x0     = util_format_get_nblocksx(pt->format, x) << mt->ms_x;
   rect->y0     = util_format_get_nblocksy(pt->format, y) << mt->ms_y;
   rect->x1     = rect->x0 + (w << mt->ms_x);
   rect->y1     = rect->y0 + (h << mt->ms_y);
}
示例#4
0
static void
nv30_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt)
{
   struct nv30_miptree *mt = nv30_miptree(pt);

   nouveau_bo_ref(NULL, &mt->base.bo);
   FREE(mt);
}
示例#5
0
static INLINE unsigned
layer_offset(struct pipe_resource *pt, unsigned level, unsigned layer)
{
   struct nv30_miptree *mt = nv30_miptree(pt);
   struct nv30_miptree_level *lvl = &mt->level[level];

   if (pt->target == PIPE_TEXTURE_CUBE)
      return (layer * mt->layer_size) + lvl->offset;

   return lvl->offset + (layer * lvl->zslice_size);
}
示例#6
0
static boolean
nv30_miptree_get_handle(struct pipe_screen *pscreen,
                        struct pipe_resource *pt,
                        struct winsys_handle *handle)
{
   struct nv30_miptree *mt = nv30_miptree(pt);
   unsigned stride;

   if (!mt || !mt->base.bo)
      return FALSE;

   stride = mt->level[0].pitch;

   return nouveau_screen_bo_get_handle(pscreen, mt->base.bo, stride, handle);
}
示例#7
0
struct pipe_surface *
nv30_miptree_surface_new(struct pipe_context *pipe,
                         struct pipe_resource *pt,
                         const struct pipe_surface *tmpl)
{
   struct nv30_miptree *mt = nv30_miptree(pt); /* guaranteed */
   struct nv30_surface *ns;
   struct pipe_surface *ps;
   struct nv30_miptree_level *lvl = &mt->level[tmpl->u.tex.level];

   ns = CALLOC_STRUCT(nv30_surface);
   if (!ns)
      return NULL;
   ps = &ns->base;

   pipe_reference_init(&ps->reference, 1);
   pipe_resource_reference(&ps->texture, pt);
   ps->context = pipe;
   ps->format = tmpl->format;
   ps->usage = tmpl->usage;
   ps->u.tex.level = tmpl->u.tex.level;
   ps->u.tex.first_layer = tmpl->u.tex.first_layer;
   ps->u.tex.last_layer = tmpl->u.tex.last_layer;

   ns->width = u_minify(pt->width0, ps->u.tex.level);
   ns->height = u_minify(pt->height0, ps->u.tex.level);
   ns->depth = ps->u.tex.last_layer - ps->u.tex.first_layer + 1;
   ns->offset = layer_offset(pt, ps->u.tex.level, ps->u.tex.first_layer);
   if (mt->swizzled)
      ns->pitch = 4096; /* random, just something the hw won't reject.. */
   else
      ns->pitch = lvl->pitch;

   /* comment says there are going to be removed, but they're used by the st */
   ps->width = ns->width;
   ps->height = ns->height;
   return ps;
}
示例#8
0
static void
nv30_clear_depth_stencil(struct pipe_context *pipe, struct pipe_surface *ps,
                         unsigned buffers, double depth, unsigned stencil,
                         unsigned x, unsigned y, unsigned w, unsigned h)
{
   struct nv30_context *nv30 = nv30_context(pipe);
   struct nv30_surface *sf = nv30_surface(ps);
   struct nv30_miptree *mt = nv30_miptree(ps->texture);
   struct nouveau_pushbuf *push = nv30->base.pushbuf;
   struct nouveau_object *eng3d = nv30->screen->eng3d;
   struct nouveau_pushbuf_refn refn;
   uint32_t rt_format, mode = 0;

   rt_format = nv30_format(pipe->screen, ps->format)->hw;
   if (util_format_get_blocksize(ps->format) == 4)
      rt_format |= NV30_3D_RT_FORMAT_COLOR_A8R8G8B8;
   else
      rt_format |= NV30_3D_RT_FORMAT_COLOR_R5G6B5;

   if (nv30_miptree(ps->texture)->swizzled) {
      rt_format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
      rt_format |= util_logbase2(sf->width) << 16;
      rt_format |= util_logbase2(sf->height) << 24;
   } else {
      rt_format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
   }

   if (buffers & PIPE_CLEAR_DEPTH)
      mode |= NV30_3D_CLEAR_BUFFERS_DEPTH;
   if (buffers & PIPE_CLEAR_STENCIL)
      mode |= NV30_3D_CLEAR_BUFFERS_STENCIL;

   refn.bo = mt->base.bo;
   refn.flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_WR;
   if (nouveau_pushbuf_space(push, 32, 1, 0) ||
       nouveau_pushbuf_refn (push, &refn, 1))
      return;

   BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
   PUSH_DATA (push, 0);
   BEGIN_NV04(push, NV30_3D(RT_HORIZ), 3);
   PUSH_DATA (push, sf->width << 16);
   PUSH_DATA (push, sf->height << 16);
   PUSH_DATA (push, rt_format);
   if (eng3d->oclass < NV40_3D_CLASS) {
      BEGIN_NV04(push, NV30_3D(COLOR0_PITCH), 1);
      PUSH_DATA (push, (sf->pitch << 16) | sf->pitch);
   } else {
      BEGIN_NV04(push, NV40_3D(ZETA_PITCH), 1);
      PUSH_DATA (push, sf->pitch);
   }
   BEGIN_NV04(push, NV30_3D(ZETA_OFFSET), 1);
   PUSH_RELOC(push, mt->base.bo, sf->offset, NOUVEAU_BO_LOW, 0, 0);
   BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
   PUSH_DATA (push, (w << 16) | x);
   PUSH_DATA (push, (h << 16) | y);

   BEGIN_NV04(push, NV30_3D(CLEAR_DEPTH_VALUE), 1);
   PUSH_DATA (push, pack_zeta(ps->format, depth, stencil));
   BEGIN_NV04(push, NV30_3D(CLEAR_BUFFERS), 1);
   PUSH_DATA (push, mode);

   nv30->dirty |= NV30_NEW_FRAMEBUFFER | NV30_NEW_SCISSOR;
}
示例#9
0
static struct pipe_sampler_view *
nv30_sampler_view_create(struct pipe_context *pipe, struct pipe_resource *pt,
                         const struct pipe_sampler_view *tmpl)
{
   const struct nv30_texfmt *fmt = nv30_texfmt(pipe->screen, tmpl->format);
   struct nouveau_object *eng3d = nv30_context(pipe)->screen->eng3d;
   struct nv30_miptree *mt = nv30_miptree(pt);
   struct nv30_sampler_view *so;

   so = MALLOC_STRUCT(nv30_sampler_view);
   if (!so)
      return NULL;
   so->pipe = *tmpl;
   so->pipe.reference.count = 1;
   so->pipe.texture = NULL;
   so->pipe.context = pipe;
   pipe_resource_reference(&so->pipe.texture, pt);

   so->fmt = NV30_3D_TEX_FORMAT_NO_BORDER;
   switch (pt->target) {
   case PIPE_TEXTURE_1D:
      so->fmt |= NV30_3D_TEX_FORMAT_DIMS_1D;
      break;
   case PIPE_TEXTURE_CUBE:
      so->fmt |= NV30_3D_TEX_FORMAT_CUBIC;
   case PIPE_TEXTURE_2D:
   case PIPE_TEXTURE_RECT:
      so->fmt |= NV30_3D_TEX_FORMAT_DIMS_2D;
      break;
   case PIPE_TEXTURE_3D:
      so->fmt |= NV30_3D_TEX_FORMAT_DIMS_3D;
      break;
   default:
      assert(0);
      so->fmt |= NV30_3D_TEX_FORMAT_DIMS_1D;
      break;
   }

   so->filt = fmt->filter;
   so->wrap = fmt->wrap;
   so->swz  = fmt->swizzle;
   so->swz |= swizzle(fmt, 3, tmpl->swizzle_a);
   so->swz |= swizzle(fmt, 0, tmpl->swizzle_r) << 2;
   so->swz |= swizzle(fmt, 1, tmpl->swizzle_g) << 4;
   so->swz |= swizzle(fmt, 2, tmpl->swizzle_b) << 6;

   /* apparently, we need to ignore the t coordinate for 1D textures to
    * fix piglit tex1d-2dborder
    */
   so->wrap_mask = ~0;
   if (pt->target == PIPE_TEXTURE_1D) {
      so->wrap_mask &= ~NV30_3D_TEX_WRAP_T__MASK;
      so->wrap      |=  NV30_3D_TEX_WRAP_T_REPEAT;
   }

   /* yet more hardware suckage, can't filter 32-bit float formats */
   switch (tmpl->format) {
   case PIPE_FORMAT_R32_FLOAT:
   case PIPE_FORMAT_R32G32B32A32_FLOAT:
      so->filt_mask = ~(NV30_3D_TEX_FILTER_MIN__MASK |
                        NV30_3D_TEX_FILTER_MAG__MASK);
      so->filt     |= NV30_3D_TEX_FILTER_MIN_NEAREST |
                      NV30_3D_TEX_FILTER_MAG_NEAREST;
      break;
   default:
      so->filt_mask = ~0;
      break;
   }

   so->npot_size0 = (pt->width0 << 16) | pt->height0;
   if (eng3d->oclass >= NV40_3D_CLASS) {
      so->npot_size1 = (pt->depth0 << 20) | mt->uniform_pitch;
      if (!mt->swizzled)
         so->fmt |= NV40_3D_TEX_FORMAT_LINEAR;
      so->fmt |= 0x00008000;
      so->fmt |= (pt->last_level + 1) << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT;
   } else {
      so->swz |= mt->uniform_pitch << NV30_3D_TEX_SWIZZLE_RECT_PITCH__SHIFT;
      if (pt->last_level)
         so->fmt |= NV30_3D_TEX_FORMAT_MIPMAP;
      so->fmt |= util_logbase2(pt->width0)  << 20;
      so->fmt |= util_logbase2(pt->height0) << 24;
      so->fmt |= util_logbase2(pt->depth0)  << 28;
      so->fmt |= 0x00010000;
   }

   so->base_lod = so->pipe.u.tex.first_level << 8;
   so->high_lod = MIN2(pt->last_level, so->pipe.u.tex.last_level) << 8;
   return &so->pipe;
}
void
nv30_fragtex_validate(struct nv30_context *nv30)
{
   struct pipe_screen *pscreen = &nv30->screen->base.base;
   struct nouveau_object *eng3d = nv30->screen->eng3d;
   struct nouveau_pushbuf *push = nv30->base.pushbuf;
   unsigned dirty = nv30->fragprog.dirty_samplers;

   while (dirty) {
      unsigned unit = ffs(dirty) - 1;
      struct nv30_sampler_view *sv = (void *)nv30->fragprog.textures[unit];
      struct nv30_sampler_state *ss = nv30->fragprog.samplers[unit];

      PUSH_RESET(push, BUFCTX_FRAGTEX(unit));

      if (ss && sv) {
         const struct nv30_texfmt *fmt = nv30_texfmt(pscreen, sv->pipe.format);
         struct pipe_resource *pt = sv->pipe.texture;
         struct nv30_miptree *mt = nv30_miptree(pt);
         unsigned min_lod, max_lod;
         u32 filter = sv->filt | (ss->filt & sv->filt_mask);
         u32 format = sv->fmt | ss->fmt;
         u32 enable = ss->en;

         /* handle base_level when not using a mip filter, min/max level
          * is unfortunately ignored by the hardware otherwise
          */
         if (ss->pipe.min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
            if (sv->base_lod)
               filter += 0x00020000; /* N/L -> NMN/LMN */
            max_lod = sv->base_lod;
            min_lod = sv->base_lod;
         } else {
            max_lod = MIN2(ss->max_lod + sv->base_lod, sv->high_lod);
            min_lod = MIN2(ss->min_lod + sv->base_lod, max_lod);
         }

         if (eng3d->oclass >= NV40_3D_CLASS) {
            /* this is a tad stupid of the hardware, but there's no non-rcomp
             * z16/z24 texture formats to be had, we have to suffer and lose
             * some precision to handle this case.
             */
            if (ss->pipe.compare_mode != PIPE_TEX_COMPARE_R_TO_TEXTURE) {
               if (fmt->nv40 == NV40_3D_TEX_FORMAT_FORMAT_Z16)
                  format |= NV40_3D_TEX_FORMAT_FORMAT_A8L8;
               else
               if (fmt->nv40 == NV40_3D_TEX_FORMAT_FORMAT_Z24)
                  format |= NV40_3D_TEX_FORMAT_FORMAT_A16L16;
               else
                  format |= fmt->nv40;
            } else {
               format |= fmt->nv40;
            }

            enable |= (min_lod << 19) | (max_lod << 7);
            enable |= NV40_3D_TEX_ENABLE_ENABLE;

            BEGIN_NV04(push, NV40_3D(TEX_SIZE1(unit)), 1);
            PUSH_DATA (push, sv->npot_size1);
         } else {
            /* this is a tad stupid of the hardware, but there's no non-rcomp
             * z16/z24 texture formats to be had, we have to suffer and lose
             * some precision to handle this case.
             */
            if (ss->pipe.compare_mode != PIPE_TEX_COMPARE_R_TO_TEXTURE) {
               if (fmt->nv30 == NV30_3D_TEX_FORMAT_FORMAT_Z16) {
                  if (ss->pipe.normalized_coords)
                     format |= NV30_3D_TEX_FORMAT_FORMAT_A8L8;
                  else
                     format |= NV30_3D_TEX_FORMAT_FORMAT_A8L8_RECT;
               } else
               if (fmt->nv30 == NV30_3D_TEX_FORMAT_FORMAT_Z24) {
                  if (ss->pipe.normalized_coords)
                     format |= NV30_3D_TEX_FORMAT_FORMAT_HILO16;
                  else
                     format |= NV30_3D_TEX_FORMAT_FORMAT_HILO16_RECT;
               } else {
                  if (ss->pipe.normalized_coords)
                     format |= fmt->nv30;
                  else
                     format |= fmt->nv30_rect;
               }
            } else {
               if (ss->pipe.normalized_coords)
                  format |= fmt->nv30;
               else
                  format |= fmt->nv30_rect;
            }

            enable |= NV30_3D_TEX_ENABLE_ENABLE;
            enable |= (min_lod << 18) | (max_lod << 6);
         }

         BEGIN_NV04(push, NV30_3D(TEX_OFFSET(unit)), 8);
         PUSH_MTHDl(push, NV30_3D(TEX_OFFSET(unit)), BUFCTX_FRAGTEX(unit),
                          mt->base.bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
         PUSH_MTHDs(push, NV30_3D(TEX_FORMAT(unit)), BUFCTX_FRAGTEX(unit),
                          mt->base.bo, format, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD,
                          NV30_3D_TEX_FORMAT_DMA0,
                          NV30_3D_TEX_FORMAT_DMA1);
         PUSH_DATA (push, sv->wrap | (ss->wrap & sv->wrap_mask));
         PUSH_DATA (push, enable);
         PUSH_DATA (push, sv->swz);
         PUSH_DATA (push, filter);
         PUSH_DATA (push, sv->npot_size0);
         PUSH_DATA (push, ss->bcol);
         BEGIN_NV04(push, NV30_3D(TEX_FILTER_OPTIMIZATION(unit)), 1);
         PUSH_DATA (push, nv30->config.filter);
      } else {
         BEGIN_NV04(push, NV30_3D(TEX_ENABLE(unit)), 1);
         PUSH_DATA (push, 0);
      }

      dirty &= ~(1 << unit);
   }

   nv30->fragprog.dirty_samplers = 0;
}