예제 #1
0
static void
nouveau_vpe_fini(struct nouveau_decoder *dec) {
   struct nouveau_pushbuf *push = dec->push;
   if (!dec->cmds)
      return;

   nouveau_pushbuf_space(push, 16, 2, 0);
   nouveau_bufctx_reset(dec->bufctx, NV31_VIDEO_BIND_CMD);

#define BCTX_ARGS dec->bufctx, NV31_VIDEO_BIND_CMD, NOUVEAU_BO_RD

   BEGIN_NV04(push, NV31_MPEG(CMD_OFFSET), 2);
   PUSH_MTHDl(push, NV31_MPEG(CMD_OFFSET), dec->cmd_bo, 0, BCTX_ARGS);
   PUSH_DATA (push, dec->ofs * 4);

   BEGIN_NV04(push, NV31_MPEG(DATA_OFFSET), 2);
   PUSH_MTHDl(push, NV31_MPEG(DATA_OFFSET), dec->data_bo, 0, BCTX_ARGS);
   PUSH_DATA (push, dec->data_pos * 4);

#undef BCTX_ARGS

   if (unlikely(nouveau_pushbuf_validate(dec->push)))
      return;

   BEGIN_NV04(push, NV31_MPEG(EXEC), 1);
   PUSH_DATA (push, 1);

   nouveau_vpe_synch(dec);
   dec->ofs = dec->data_pos = dec->num_surfaces = 0;
   dec->cmds = dec->data = NULL;
   dec->current = dec->future = dec->past = 8;
}
예제 #2
0
파일: nv30_clear.c 프로젝트: DirectFB/mesa
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
void
nvc0_query_pushbuf_submit(struct nouveau_pushbuf *push,
                          struct pipe_query *pq, unsigned result_offset)
{
   struct nvc0_query *q = nvc0_query(pq);

#define NVC0_IB_ENTRY_1_NO_PREFETCH (1 << (31 - 8))

   nouveau_pushbuf_space(push, 0, 0, 1);
   nouveau_pushbuf_data(push, q->bo, q->offset + result_offset, 4 |
                        NVC0_IB_ENTRY_1_NO_PREFETCH);
}
예제 #4
0
void
nv50_query_pushbuf_submit(struct nouveau_pushbuf *push,
                          struct pipe_query *pq, unsigned result_offset)
{
    struct nv50_query *q = nv50_query(pq);

    /* XXX: does this exist ? */
#define NV50_IB_ENTRY_1_NO_PREFETCH (0 << (31 - 8))

    nouveau_pushbuf_space(push, 0, 0, 1);
    nouveau_pushbuf_data(push, q->bo, q->offset + result_offset, 4 |
                         NV50_IB_ENTRY_1_NO_PREFETCH);
}
예제 #5
0
static void
nv30_transfer_rect_m2mf(XFER_ARGS)
{
   struct nouveau_pushbuf *push = nv30->base.pushbuf;
   struct nouveau_pushbuf_refn refs[] = {
      { src->bo, src->domain | NOUVEAU_BO_RD },
      { dst->bo, dst->domain | NOUVEAU_BO_WR },
   };
   struct nv04_fifo *fifo = push->channel->data;
   unsigned src_offset = src->offset;
   unsigned dst_offset = dst->offset;
   unsigned w = dst->x1 - dst->x0;
   unsigned h = dst->y1 - dst->y0;

   src_offset += (src->y0 * src->pitch) + (src->x0 * src->cpp);
   dst_offset += (dst->y0 * dst->pitch) + (dst->x0 * dst->cpp);

   BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2);
   PUSH_DATA (push, (src->domain == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart);
   PUSH_DATA (push, (dst->domain == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart);

   while (h) {
      unsigned lines = (h > 2047) ? 2047 : h;

      if (nouveau_pushbuf_space(push, 13, 2, 0) ||
          nouveau_pushbuf_refn (push, refs, 2))
         return;

      BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8);
      PUSH_RELOC(push, src->bo, src_offset, NOUVEAU_BO_LOW, 0, 0);
      PUSH_RELOC(push, dst->bo, dst_offset, NOUVEAU_BO_LOW, 0, 0);
      PUSH_DATA (push, src->pitch);
      PUSH_DATA (push, dst->pitch);
      PUSH_DATA (push, w * src->cpp);
      PUSH_DATA (push, lines);
      PUSH_DATA (push, NV03_M2MF_FORMAT_INPUT_INC_1 |
                       NV03_M2MF_FORMAT_OUTPUT_INC_1);
      PUSH_DATA (push, 0x00000000);
      BEGIN_NV04(push, NV04_GRAPH(M2MF, NOP), 1);
      PUSH_DATA (push, 0x00000000);
      BEGIN_NV04(push, NV03_M2MF(OFFSET_OUT), 1);
      PUSH_DATA (push, 0x00000000);

      h -= lines;
      src_offset += src->pitch * lines;
      dst_offset += dst->pitch * lines;
   }
}
예제 #6
0
static void
nouveau_finish(struct gl_context *ctx)
{
	struct nouveau_context *nctx = to_nouveau_context(ctx);
	struct nouveau_pushbuf *push = context_push(ctx);
	struct nouveau_pushbuf_refn refn =
		{ nctx->fence, NOUVEAU_BO_VRAM | NOUVEAU_BO_RDWR };

	nouveau_flush(ctx);

	if (!nouveau_pushbuf_space(push, 16, 0, 0) &&
	    !nouveau_pushbuf_refn(push, &refn, 1)) {
		PUSH_DATA(push, 0);
		PUSH_KICK(push);
	}

	nouveau_bo_wait(nctx->fence, NOUVEAU_BO_RDWR, context_client(ctx));
}
예제 #7
0
static void
nv04_surface_copy_m2mf(struct gl_context *ctx,
                       struct nouveau_surface *dst,
                       struct nouveau_surface *src,
                       int dx, int dy, int sx, int sy,
                       int w, int h)
{
    struct nouveau_pushbuf_refn refs[] = {
        { src->bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
        { dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
    };
    struct nouveau_pushbuf *push = context_push(ctx);
    struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
    struct nv04_fifo *fifo = hw->chan->data;
    unsigned dst_offset = dst->offset + dy * dst->pitch + dx * dst->cpp;
    unsigned src_offset = src->offset + sy * src->pitch + sx * src->cpp;

    while (h) {
        int count = (h > 2047) ? 2047 : h;

        if (nouveau_pushbuf_space(push, 16, 4, 0) ||
                nouveau_pushbuf_refn (push, refs, 2))
            return;

        BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2);
        PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
        PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
        BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8);
        PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0);
        PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
        PUSH_DATA (push, src->pitch);
        PUSH_DATA (push, dst->pitch);
        PUSH_DATA (push, w * src->cpp);
        PUSH_DATA (push, count);
        PUSH_DATA (push, 0x0101);
        PUSH_DATA (push, 0);

        src_offset += src->pitch * count;
        dst_offset += dst->pitch * count;
        h -= count;
    }
}
예제 #8
0
void
nv04_surface_fill(struct gl_context *ctx,
                  struct nouveau_surface *dst,
                  unsigned mask, unsigned value,
                  int dx, int dy, int w, int h)
{
    struct nouveau_pushbuf_refn refs[] = {
        { dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
    };
    struct nouveau_pushbuf *push = context_push(ctx);
    struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
    struct nv04_fifo *fifo = hw->chan->data;

    if (nouveau_pushbuf_space(push, 64, 4, 0) ||
            nouveau_pushbuf_refn (push, refs, 1))
        return;

    BEGIN_NV04(push, NV04_SF2D(DMA_IMAGE_SOURCE), 2);
    PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
    PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
    BEGIN_NV04(push, NV04_SF2D(FORMAT), 4);
    PUSH_DATA (push, surf2d_format(dst->format));
    PUSH_DATA (push, (dst->pitch << 16) | dst->pitch);
    PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
    PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);

    BEGIN_NV04(push, NV01_PATT(COLOR_FORMAT), 1);
    PUSH_DATA (push, rect_format(dst->format));
    BEGIN_NV04(push, NV01_PATT(MONOCHROME_COLOR1), 1);
    PUSH_DATA (push, mask | ~0ll << (8 * dst->cpp));

    BEGIN_NV04(push, NV04_GDI(COLOR_FORMAT), 1);
    PUSH_DATA (push, rect_format(dst->format));
    BEGIN_NV04(push, NV04_GDI(COLOR1_A), 1);
    PUSH_DATA (push, value);
    BEGIN_NV04(push, NV04_GDI(UNCLIPPED_RECTANGLE_POINT(0)), 2);
    PUSH_DATA (push, (dx << 16) | dy);
    PUSH_DATA (push, ( w << 16) |  h);
}
예제 #9
0
static void
nv30_transfer_rect_sifm(XFER_ARGS)

{
   struct nouveau_pushbuf *push = nv30->base.pushbuf;
   struct nouveau_pushbuf_refn refs[] = {
      { src->bo, src->domain | NOUVEAU_BO_RD },
      { dst->bo, dst->domain | NOUVEAU_BO_WR },
   };
   struct nv04_fifo *fifo = push->channel->data;
   unsigned si_fmt, si_arg;
   unsigned ss_fmt;

   switch (dst->cpp) {
   case 4: ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_A8R8G8B8; break;
   case 2: ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_R5G6B5; break;
   default:
      ss_fmt = NV04_SURFACE_SWZ_FORMAT_COLOR_Y8;
      break;
   }

   switch (src->cpp) {
   case 4: si_fmt = NV03_SIFM_COLOR_FORMAT_A8R8G8B8; break;
   case 2: si_fmt = NV03_SIFM_COLOR_FORMAT_R5G6B5; break;
   default:
      si_fmt = NV03_SIFM_COLOR_FORMAT_AY8;
      break;
   }

   if (filter == NEAREST) {
      si_arg  = NV03_SIFM_FORMAT_ORIGIN_CENTER;
      si_arg |= NV03_SIFM_FORMAT_FILTER_POINT_SAMPLE;
   } else {
      si_arg  = NV03_SIFM_FORMAT_ORIGIN_CORNER;
      si_arg |= NV03_SIFM_FORMAT_FILTER_BILINEAR;
   }

   if (nouveau_pushbuf_space(push, 32, 6, 0) ||
       nouveau_pushbuf_refn (push, refs, 2))
      return;

   if (dst->pitch) {
      BEGIN_NV04(push, NV04_SF2D(DMA_IMAGE_SOURCE), 2);
      PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
      PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
      BEGIN_NV04(push, NV04_SF2D(FORMAT), 4);
      PUSH_DATA (push, ss_fmt);
      PUSH_DATA (push, dst->pitch << 16 | dst->pitch);
      PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
      PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
      BEGIN_NV04(push, NV05_SIFM(SURFACE), 1);
      PUSH_DATA (push, nv30->screen->surf2d->handle);
   } else {
      BEGIN_NV04(push, NV04_SSWZ(DMA_IMAGE), 1);
      PUSH_RELOC(push, dst->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
      BEGIN_NV04(push, NV04_SSWZ(FORMAT), 2);
      PUSH_DATA (push, ss_fmt | (util_logbase2(dst->w) << 16) |
                                (util_logbase2(dst->h) << 24));
      PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
      BEGIN_NV04(push, NV05_SIFM(SURFACE), 1);
      PUSH_DATA (push, nv30->screen->swzsurf->handle);
   }

   BEGIN_NV04(push, NV03_SIFM(DMA_IMAGE), 1);
   PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
   BEGIN_NV04(push, NV03_SIFM(COLOR_FORMAT), 8);
   PUSH_DATA (push, si_fmt);
   PUSH_DATA (push, NV03_SIFM_OPERATION_SRCCOPY);
   PUSH_DATA (push, (           dst->y0  << 16) |            dst->x0);
   PUSH_DATA (push, ((dst->y1 - dst->y0) << 16) | (dst->x1 - dst->x0));
   PUSH_DATA (push, (           dst->y0  << 16) |            dst->x0);
   PUSH_DATA (push, ((dst->y1 - dst->y0) << 16) | (dst->x1 - dst->x0));
   PUSH_DATA (push, ((src->x1 - src->x0) << 20) / (dst->x1 - dst->x0));
   PUSH_DATA (push, ((src->y1 - src->y0) << 20) / (dst->y1 - dst->y0));
   BEGIN_NV04(push, NV03_SIFM(SIZE), 4);
   PUSH_DATA (push, align(src->h, 2) << 16 | align(src->w, 2));
   PUSH_DATA (push, src->pitch | si_arg);
   PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0);
   PUSH_DATA (push, (src->y0 << 20) | src->x0 << 4);
}
예제 #10
0
파일: nv30_clear.c 프로젝트: DirectFB/mesa
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;
}
예제 #11
0
void
nvc0_tfb_validate(struct nvc0_context *nvc0)
{
   struct nouveau_pushbuf *push = nvc0->base.pushbuf;
   struct nvc0_transform_feedback_state *tfb;
   unsigned b;

   if (nvc0->gmtyprog) tfb = nvc0->gmtyprog->tfb;
   else
   if (nvc0->tevlprog) tfb = nvc0->tevlprog->tfb;
   else
      tfb = nvc0->vertprog->tfb;

   IMMED_NVC0(push, NVC0_3D(TFB_ENABLE), (tfb && nvc0->num_tfbbufs) ? 1 : 0);

   if (tfb && tfb != nvc0->state.tfb) {
      for (b = 0; b < 4; ++b) {
         if (tfb->varying_count[b]) {
            unsigned n = (tfb->varying_count[b] + 3) / 4;

            BEGIN_NVC0(push, NVC0_3D(TFB_STREAM(b)), 3);
            PUSH_DATA (push, tfb->stream[b]);
            PUSH_DATA (push, tfb->varying_count[b]);
            PUSH_DATA (push, tfb->stride[b]);
            BEGIN_NVC0(push, NVC0_3D(TFB_VARYING_LOCS(b, 0)), n);
            PUSH_DATAp(push, tfb->varying_index[b], n);

            if (nvc0->tfbbuf[b])
               nvc0_so_target(nvc0->tfbbuf[b])->stride = tfb->stride[b];
         } else {
            IMMED_NVC0(push, NVC0_3D(TFB_VARYING_COUNT(b)), 0);
         }
      }
   }
   nvc0->state.tfb = tfb;

   if (!(nvc0->dirty_3d & NVC0_NEW_3D_TFB_TARGETS))
      return;

   for (b = 0; b < nvc0->num_tfbbufs; ++b) {
      struct nvc0_so_target *targ = nvc0_so_target(nvc0->tfbbuf[b]);
      struct nv04_resource *buf;

      if (!targ) {
         IMMED_NVC0(push, NVC0_3D(TFB_BUFFER_ENABLE(b)), 0);
         continue;
      }

      if (tfb)
         targ->stride = tfb->stride[b];

      buf = nv04_resource(targ->pipe.buffer);

      BCTX_REFN(nvc0->bufctx_3d, 3D_TFB, buf, WR);

      if (!(nvc0->tfbbuf_dirty & (1 << b)))
         continue;

      if (!targ->clean)
         nvc0_hw_query_fifo_wait(nvc0, nvc0_query(targ->pq));
      nouveau_pushbuf_space(push, 0, 0, 1);
      BEGIN_NVC0(push, NVC0_3D(TFB_BUFFER_ENABLE(b)), 5);
      PUSH_DATA (push, 1);
      PUSH_DATAh(push, buf->address + targ->pipe.buffer_offset);
      PUSH_DATA (push, buf->address + targ->pipe.buffer_offset);
      PUSH_DATA (push, targ->pipe.buffer_size);
      if (!targ->clean) {
         nvc0_hw_query_pushbuf_submit(push, nvc0_query(targ->pq), 0x4);
      } else {
         PUSH_DATA(push, 0); /* TFB_BUFFER_OFFSET */
         targ->clean = false;
      }
   }
   for (; b < 4; ++b)
      IMMED_NVC0(push, NVC0_3D(TFB_BUFFER_ENABLE(b)), 0);
}
예제 #12
0
void
nvc0_launch_grid(struct pipe_context *pipe, const struct pipe_grid_info *info)
{
   struct nvc0_context *nvc0 = nvc0_context(pipe);
   struct nouveau_pushbuf *push = nvc0->base.pushbuf;
   struct nvc0_program *cp = nvc0->compprog;
   int ret;

   ret = !nvc0_state_validate_cp(nvc0, ~0);
   if (ret) {
      NOUVEAU_ERR("Failed to launch grid !\n");
      return;
   }

   nvc0_compute_upload_input(nvc0, info);

   BEGIN_NVC0(push, NVC0_CP(CP_START_ID), 1);
   PUSH_DATA (push, nvc0_program_symbol_offset(cp, info->pc));

   BEGIN_NVC0(push, NVC0_CP(LOCAL_POS_ALLOC), 3);
   PUSH_DATA (push, (cp->hdr[1] & 0xfffff0) + align(cp->cp.lmem_size, 0x10));
   PUSH_DATA (push, 0);
   PUSH_DATA (push, 0x800); /* WARP_CSTACK_SIZE */

   BEGIN_NVC0(push, NVC0_CP(SHARED_SIZE), 3);
   PUSH_DATA (push, align(cp->cp.smem_size, 0x100));
   PUSH_DATA (push, info->block[0] * info->block[1] * info->block[2]);
   PUSH_DATA (push, cp->num_barriers);
   BEGIN_NVC0(push, NVC0_CP(CP_GPR_ALLOC), 1);
   PUSH_DATA (push, cp->num_gprs);

   /* launch preliminary setup */
   BEGIN_NVC0(push, NVC0_CP(GRIDID), 1);
   PUSH_DATA (push, 0x1);
   BEGIN_NVC0(push, SUBC_CP(0x036c), 1);
   PUSH_DATA (push, 0);
   BEGIN_NVC0(push, NVC0_CP(FLUSH), 1);
   PUSH_DATA (push, NVC0_COMPUTE_FLUSH_GLOBAL | NVC0_COMPUTE_FLUSH_UNK8);

   /* block setup */
   BEGIN_NVC0(push, NVC0_CP(BLOCKDIM_YX), 2);
   PUSH_DATA (push, (info->block[1] << 16) | info->block[0]);
   PUSH_DATA (push, info->block[2]);

   if (unlikely(info->indirect)) {
      struct nv04_resource *res = nv04_resource(info->indirect);
      uint32_t offset = res->offset + info->indirect_offset;
      unsigned macro = NVC0_CP_MACRO_LAUNCH_GRID_INDIRECT;

      nouveau_pushbuf_space(push, 16, 0, 1);
      PUSH_REFN(push, res->bo, NOUVEAU_BO_RD | res->domain);
      PUSH_DATA(push, NVC0_FIFO_PKHDR_1I(1, macro, 3));
      nouveau_pushbuf_data(push, res->bo, offset,
                           NVC0_IB_ENTRY_1_NO_PREFETCH | 3 * 4);
   } else {
      /* grid setup */
      BEGIN_NVC0(push, NVC0_CP(GRIDDIM_YX), 2);
      PUSH_DATA (push, (info->grid[1] << 16) | info->grid[0]);
      PUSH_DATA (push, info->grid[2]);

      /* kernel launching */
      BEGIN_NVC0(push, NVC0_CP(COMPUTE_BEGIN), 1);
      PUSH_DATA (push, 0);
      BEGIN_NVC0(push, SUBC_CP(0x0a08), 1);
      PUSH_DATA (push, 0);
      BEGIN_NVC0(push, NVC0_CP(LAUNCH), 1);
      PUSH_DATA (push, 0x1000);
      BEGIN_NVC0(push, NVC0_CP(COMPUTE_END), 1);
      PUSH_DATA (push, 0);
      BEGIN_NVC0(push, SUBC_CP(0x0360), 1);
      PUSH_DATA (push, 0x1);
   }

   /* TODO: Not sure if this is really necessary. */
   nvc0_compute_invalidate_surfaces(nvc0, 5);
   nouveau_bufctx_reset(nvc0->bufctx_cp, NVC0_BIND_CP_SUF);
   nvc0->dirty_cp |= NVC0_NEW_CP_SURFACES;
   nvc0->images_dirty[5] |= nvc0->images_valid[5];
}
예제 #13
0
struct pipe_video_decoder *
nvc0_create_decoder(struct pipe_context *context,
                    enum pipe_video_profile profile,
                    enum pipe_video_entrypoint entrypoint,
                    enum pipe_video_chroma_format chroma_format,
                    unsigned width, unsigned height, unsigned max_references,
                    bool chunked_decode)
{
   struct nouveau_screen *screen = &((struct nvc0_context *)context)->screen->base;
   struct nvc0_decoder *dec;
   struct nouveau_pushbuf **push;
   union nouveau_bo_config cfg;
   bool kepler = screen->device->chipset >= 0xe0;

   cfg.nvc0.tile_mode = 0x10;
   cfg.nvc0.memtype = 0xfe;

   int ret, i;
   uint32_t codec = 1, ppp_codec = 3;
   uint32_t timeout;
   u32 tmp_size = 0;

   if (getenv("XVMC_VL"))
       return vl_create_decoder(context, profile, entrypoint,
                                chroma_format, width, height,
                                max_references, chunked_decode);

   if (entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
      debug_printf("%x\n", entrypoint);
      return NULL;
   }

   dec = CALLOC_STRUCT(nvc0_decoder);
   if (!dec)
      return NULL;
   dec->client = screen->client;

   if (!kepler) {
      dec->bsp_idx = 5;
      dec->vp_idx = 6;
      dec->ppp_idx = 7;
   } else {
      dec->bsp_idx = 2;
      dec->vp_idx = 2;
      dec->ppp_idx = 2;
   }

   for (i = 0; i < 3; ++i)
      if (i && !kepler) {
         dec->channel[i] = dec->channel[0];
         dec->pushbuf[i] = dec->pushbuf[0];
      } else {
         void *data;
         u32 size;
         struct nvc0_fifo nvc0_args = {};
         struct nve0_fifo nve0_args = {};

         if (!kepler) {
            size = sizeof(nvc0_args);
            data = &nvc0_args;
         } else {
            unsigned engine[] = {
               NVE0_FIFO_ENGINE_BSP,
               NVE0_FIFO_ENGINE_VP,
               NVE0_FIFO_ENGINE_PPP
            };

            nve0_args.engine = engine[i];
            size = sizeof(nve0_args);
            data = &nve0_args;
         }

         ret = nouveau_object_new(&screen->device->object, 0,
                                  NOUVEAU_FIFO_CHANNEL_CLASS,
                                  data, size, &dec->channel[i]);

         if (!ret)
            ret = nouveau_pushbuf_new(screen->client, dec->channel[i], 4,
                                   32 * 1024, true, &dec->pushbuf[i]);
         if (ret)
            break;
      }
   push = dec->pushbuf;

   if (!kepler) {
      if (!ret)
         ret = nouveau_object_new(dec->channel[0], 0x390b1, 0x90b1, NULL, 0, &dec->bsp);
      if (!ret)
         ret = nouveau_object_new(dec->channel[1], 0x190b2, 0x90b2, NULL, 0, &dec->vp);
      if (!ret)
         ret = nouveau_object_new(dec->channel[2], 0x290b3, 0x90b3, NULL, 0, &dec->ppp);
   } else {
      if (!ret)
         ret = nouveau_object_new(dec->channel[0], 0x95b1, 0x95b1, NULL, 0, &dec->bsp);
      if (!ret)
         ret = nouveau_object_new(dec->channel[1], 0x95b2, 0x95b2, NULL, 0, &dec->vp);
      if (!ret)
         ret = nouveau_object_new(dec->channel[2], 0x90b3, 0x90b3, NULL, 0, &dec->ppp);
   }
   if (ret)
      goto fail;

   BEGIN_NVC0(push[0], SUBC_BSP(NV01_SUBCHAN_OBJECT), 1);
   PUSH_DATA (push[0], dec->bsp->handle);

   BEGIN_NVC0(push[1], SUBC_VP(NV01_SUBCHAN_OBJECT), 1);
   PUSH_DATA (push[1], dec->vp->handle);

   BEGIN_NVC0(push[2], SUBC_PPP(NV01_SUBCHAN_OBJECT), 1);
   PUSH_DATA (push[2], dec->ppp->handle);

   dec->base.context = context;
   dec->base.profile = profile;
   dec->base.entrypoint = entrypoint;
   dec->base.chroma_format = chroma_format;
   dec->base.width = width;
   dec->base.height = height;
   dec->base.max_references = max_references;
   dec->base.destroy = nvc0_decoder_destroy;
   dec->base.flush = nvc0_decoder_flush;
   dec->base.decode_bitstream = nvc0_decoder_decode_bitstream;
   dec->base.begin_frame = nvc0_decoder_begin_frame;
   dec->base.end_frame = nvc0_decoder_end_frame;

   for (i = 0; i < NVC0_VIDEO_QDEPTH && !ret; ++i)
      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
                           0, 1 << 20, &cfg, &dec->bsp_bo[i]);
   if (!ret)
      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
                           0x100, 4 << 20, &cfg, &dec->inter_bo[0]);
   if (!ret) {
      if (!kepler)
         nouveau_bo_ref(dec->inter_bo[0], &dec->inter_bo[1]);
      else
         ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
                              0x100, dec->inter_bo[0]->size, &cfg,
                              &dec->inter_bo[1]);
   }
   if (ret)
      goto fail;

   switch (u_reduce_video_profile(profile)) {
   case PIPE_VIDEO_CODEC_MPEG12: {
      codec = 1;
      assert(max_references <= 2);
      break;
   }
   case PIPE_VIDEO_CODEC_MPEG4: {
      codec = 4;
      tmp_size = mb(height)*16 * mb(width)*16;
      assert(max_references <= 2);
      break;
   }
   case PIPE_VIDEO_CODEC_VC1: {
      ppp_codec = codec = 2;
      tmp_size = mb(height)*16 * mb(width)*16;
      assert(max_references <= 2);
      break;
   }
   case PIPE_VIDEO_CODEC_MPEG4_AVC: {
      codec = 3;
      dec->tmp_stride = 16 * mb_half(width) * nvc0_video_align(height) * 3 / 2;
      tmp_size = dec->tmp_stride * (max_references + 1);
      assert(max_references <= 16);
      break;
   }
   default:
      fprintf(stderr, "invalid codec\n");
      goto fail;
   }

   if (screen->device->chipset < 0xd0) {
      int fd;
      char path[PATH_MAX];
      ssize_t r;
      uint32_t *end, endval;

      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
                           0x4000, &cfg, &dec->fw_bo);
      if (!ret)
         ret = nouveau_bo_map(dec->fw_bo, NOUVEAU_BO_WR, dec->client);
      if (ret)
         goto fail;

      nvc0_video_getpath(profile, path);

      fd = open(path, O_RDONLY | O_CLOEXEC);
      if (fd < 0) {
         fprintf(stderr, "opening firmware file %s failed: %m\n", path);
         goto fw_fail;
      }
      r = read(fd, dec->fw_bo->map, 0x4000);
      close(fd);

      if (r < 0) {
         fprintf(stderr, "reading firmware file %s failed: %m\n", path);
         goto fw_fail;
      }

      if (r == 0x4000) {
         fprintf(stderr, "firmware file %s too large!\n", path);
         goto fw_fail;
      }

      if (r & 0xff) {
         fprintf(stderr, "firmware file %s wrong size!\n", path);
         goto fw_fail;
      }

      end = dec->fw_bo->map + r - 4;
      endval = *end;
      while (endval == *end)
         end--;

      r = (intptr_t)end - (intptr_t)dec->fw_bo->map + 4;

      switch (u_reduce_video_profile(profile)) {
      case PIPE_VIDEO_CODEC_MPEG12: {
         assert((r & 0xff) == 0xe0);
         dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0);
         break;
      }
      case PIPE_VIDEO_CODEC_MPEG4: {
         assert((r & 0xff) == 0xe0);
         dec->fw_sizes = (0x2e0<<16) | (r - 0x2e0);
         break;
      }
      case PIPE_VIDEO_CODEC_VC1: {
         assert((r & 0xff) == 0xac);
         dec->fw_sizes = (0x3ac<<16) | (r - 0x3ac);
         break;
      }
      case PIPE_VIDEO_CODEC_MPEG4_AVC: {
         assert((r & 0xff) == 0x70);
         dec->fw_sizes = (0x370<<16) | (r - 0x370);
         break;
      }
      default:
         goto fw_fail;
      }
      munmap(dec->fw_bo->map, dec->fw_bo->size);
      dec->fw_bo->map = NULL;
   }

   if (codec != 3) {
      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
                           0x400, &cfg, &dec->bitplane_bo);
      if (ret)
         goto fail;
   }

   dec->ref_stride = mb(width)*16 * (mb_half(height)*32 + nvc0_video_align(height)/2);
   ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
                        dec->ref_stride * (max_references+2) + tmp_size,
                        &cfg, &dec->ref_bo);
   if (ret)
      goto fail;

   timeout = 0;

   BEGIN_NVC0(push[0], SUBC_BSP(0x200), 2);
   PUSH_DATA (push[0], codec);
   PUSH_DATA (push[0], timeout);

   BEGIN_NVC0(push[1], SUBC_VP(0x200), 2);
   PUSH_DATA (push[1], codec);
   PUSH_DATA (push[1], timeout);

   BEGIN_NVC0(push[2], SUBC_PPP(0x200), 2);
   PUSH_DATA (push[2], ppp_codec);
   PUSH_DATA (push[2], timeout);

   ++dec->fence_seq;

#if NVC0_DEBUG_FENCE
   ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP,
                        0, 0x1000, NULL, &dec->fence_bo);
   if (ret)
      goto fail;

   nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client);
   dec->fence_map = dec->fence_bo->map;
   dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0;
   dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map)));

   /* So lets test if the fence is working? */
   nouveau_pushbuf_space(push[0], 6, 1, 0);
   PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
   BEGIN_NVC0(push[0], SUBC_BSP(0x240), 3);
   PUSH_DATAh(push[0], dec->fence_bo->offset);
   PUSH_DATA (push[0], dec->fence_bo->offset);
   PUSH_DATA (push[0], dec->fence_seq);

   BEGIN_NVC0(push[0], SUBC_BSP(0x304), 1);
   PUSH_DATA (push[0], 0);
   PUSH_KICK (push[0]);

   nouveau_pushbuf_space(push[1], 6, 1, 0);
   PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
   BEGIN_NVC0(push[1], SUBC_VP(0x240), 3);
   PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10));
   PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10));
   PUSH_DATA (push[1], dec->fence_seq);

   BEGIN_NVC0(push[1], SUBC_VP(0x304), 1);
   PUSH_DATA (push[1], 0);
   PUSH_KICK (push[1]);

   nouveau_pushbuf_space(push[2], 6, 1, 0);
   PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
   BEGIN_NVC0(push[2], SUBC_PPP(0x240), 3);
   PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20));
   PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20));
   PUSH_DATA (push[2], dec->fence_seq);

   BEGIN_NVC0(push[2], SUBC_PPP(0x304), 1);
   PUSH_DATA (push[2], 0);
   PUSH_KICK (push[2]);

   usleep(100);
   while (dec->fence_seq > dec->fence_map[0] ||
          dec->fence_seq > dec->fence_map[4] ||
          dec->fence_seq > dec->fence_map[8]) {
      debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
      usleep(100);
   }
   debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
#endif

   return &dec->base;

fw_fail:
   debug_printf("Cannot create decoder without firmware..\n");
   nvc0_decoder_destroy(&dec->base);
   return NULL;

fail:
   debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret);
   nvc0_decoder_destroy(&dec->base);
   return NULL;
}
예제 #14
0
static void
nv04_surface_copy_swizzle(struct gl_context *ctx,
                          struct nouveau_surface *dst,
                          struct nouveau_surface *src,
                          int dx, int dy, int sx, int sy,
                          int w, int h)
{
    struct nouveau_pushbuf_refn refs[] = {
        { src->bo, NOUVEAU_BO_RD | NOUVEAU_BO_VRAM | NOUVEAU_BO_GART },
        { dst->bo, NOUVEAU_BO_WR | NOUVEAU_BO_VRAM },
    };
    struct nouveau_pushbuf *push = context_push(ctx);
    struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
    struct nouveau_object *swzsurf = hw->swzsurf;
    struct nv04_fifo *fifo = hw->chan->data;
    /* Max width & height may not be the same on all HW, but must be POT */
    const unsigned max_w = 1024;
    const unsigned max_h = 1024;
    unsigned sub_w = w > max_w ? max_w : w;
    unsigned sub_h = h > max_h ? max_h : h;
    unsigned x, y;

    /* Swizzled surfaces must be POT  */
    assert(_mesa_is_pow_two(dst->width) &&
           _mesa_is_pow_two(dst->height));

    if (context_chipset(ctx) < 0x10) {
        BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1);
        PUSH_DATA (push, swzsurf->handle);
    }

    for (y = 0; y < h; y += sub_h) {
        sub_h = MIN2(sub_h, h - y);

        for (x = 0; x < w; x += sub_w) {
            sub_w = MIN2(sub_w, w - x);

            if (nouveau_pushbuf_space(push, 64, 4, 0) ||
                    nouveau_pushbuf_refn (push, refs, 2))
                return;

            BEGIN_NV04(push, NV04_SSWZ(DMA_IMAGE), 1);
            PUSH_DATA (push, fifo->vram);
            BEGIN_NV04(push, NV04_SSWZ(FORMAT), 2);
            PUSH_DATA (push, swzsurf_format(dst->format) |
                       log2i(dst->width) << 16 |
                       log2i(dst->height) << 24);
            PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);

            BEGIN_NV04(push, NV03_SIFM(DMA_IMAGE), 1);
            PUSH_RELOC(push, src->bo, 0, NOUVEAU_BO_OR, fifo->vram, fifo->gart);
            BEGIN_NV04(push, NV05_SIFM(SURFACE), 1);
            PUSH_DATA (push, swzsurf->handle);

            BEGIN_NV04(push, NV03_SIFM(COLOR_FORMAT), 8);
            PUSH_DATA (push, sifm_format(src->format));
            PUSH_DATA (push, NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
            PUSH_DATA (push, (y + dy) << 16 | (x + dx));
            PUSH_DATA (push, sub_h << 16 | sub_w);
            PUSH_DATA (push, (y + dy) << 16 | (x + dx));
            PUSH_DATA (push, sub_h << 16 | sub_w);
            PUSH_DATA (push, 1 << 20);
            PUSH_DATA (push, 1 << 20);

            BEGIN_NV04(push, NV03_SIFM(SIZE), 4);
            PUSH_DATA (push, align(sub_h, 2) << 16 | align(sub_w, 2));
            PUSH_DATA (push, src->pitch  |
                       NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
                       NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
            PUSH_RELOC(push, src->bo, src->offset + (y + sy) * src->pitch +
                       (x + sx) * src->cpp, NOUVEAU_BO_LOW, 0, 0);
            PUSH_DATA (push, 0);
        }
    }

    if (context_chipset(ctx) < 0x10) {
        BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1);
        PUSH_DATA (push, hw->surf3d->handle);
    }
}
예제 #15
0
void
nv30_transfer_copy_data(struct nouveau_context *nv,
                        struct nouveau_bo *dst, unsigned d_off, unsigned d_dom,
                        struct nouveau_bo *src, unsigned s_off, unsigned s_dom,
                        unsigned size)
{
   struct nv04_fifo *fifo = nv->screen->channel->data;
   struct nouveau_pushbuf_refn refs[] = {
      { src, s_dom | NOUVEAU_BO_RD },
      { dst, d_dom | NOUVEAU_BO_WR },
   };
   struct nouveau_pushbuf *push = nv->pushbuf;
   unsigned pages, lines;

   pages = size >> 12;
   size -= (pages << 12);

   BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2);
   PUSH_DATA (push, (s_dom == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart);
   PUSH_DATA (push, (d_dom == NOUVEAU_BO_VRAM) ? fifo->vram : fifo->gart);

   while (pages) {
      lines  = (pages > 2047) ? 2047 : pages;
      pages -= lines;

      if (nouveau_pushbuf_space(push, 13, 2, 0) ||
          nouveau_pushbuf_refn (push, refs, 2))
         return;

      BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8);
      PUSH_RELOC(push, src, s_off, NOUVEAU_BO_LOW, 0, 0);
      PUSH_RELOC(push, dst, d_off, NOUVEAU_BO_LOW, 0, 0);
      PUSH_DATA (push, 4096);
      PUSH_DATA (push, 4096);
      PUSH_DATA (push, 4096);
      PUSH_DATA (push, lines);
      PUSH_DATA (push, NV03_M2MF_FORMAT_INPUT_INC_1 |
                       NV03_M2MF_FORMAT_OUTPUT_INC_1);
      PUSH_DATA (push, 0x00000000);
      BEGIN_NV04(push, NV04_GRAPH(M2MF, NOP), 1);
      PUSH_DATA (push, 0x00000000);
      BEGIN_NV04(push, NV03_M2MF(OFFSET_OUT), 1);
      PUSH_DATA (push, 0x00000000);

      s_off += (lines << 12);
      d_off += (lines << 12);
   }

   if (size) {
      if (nouveau_pushbuf_space(push, 13, 2, 0) ||
          nouveau_pushbuf_refn (push, refs, 2))
         return;

      BEGIN_NV04(push, NV03_M2MF(OFFSET_IN), 8);
      PUSH_RELOC(push, src, s_off, NOUVEAU_BO_LOW, 0, 0);
      PUSH_RELOC(push, dst, d_off, NOUVEAU_BO_LOW, 0, 0);
      PUSH_DATA (push, size);
      PUSH_DATA (push, size);
      PUSH_DATA (push, size);
      PUSH_DATA (push, 1);
      PUSH_DATA (push, NV03_M2MF_FORMAT_INPUT_INC_1 |
                       NV03_M2MF_FORMAT_OUTPUT_INC_1);
      PUSH_DATA (push, 0x00000000);
      BEGIN_NV04(push, NV04_GRAPH(M2MF, NOP), 1);
      PUSH_DATA (push, 0x00000000);
      BEGIN_NV04(push, NV03_M2MF(OFFSET_OUT), 1);
      PUSH_DATA (push, 0x00000000);
   }
}
예제 #16
0
struct pipe_video_codec *
nvc0_create_decoder(struct pipe_context *context,
                    const struct pipe_video_codec *templ)
{
   struct nouveau_screen *screen = &((struct nvc0_context *)context)->screen->base;
   struct nouveau_vp3_decoder *dec;
   struct nouveau_pushbuf **push;
   union nouveau_bo_config cfg;
   bool kepler = screen->device->chipset >= 0xe0;

   cfg.nvc0.tile_mode = 0x10;
   cfg.nvc0.memtype = 0xfe;

   int ret, i;
   uint32_t codec = 1, ppp_codec = 3;
   uint32_t timeout;
   u32 tmp_size = 0;

   if (getenv("XVMC_VL"))
       return vl_create_decoder(context, templ);

   if (templ->entrypoint != PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
      debug_printf("%x\n", templ->entrypoint);
      return NULL;
   }

   dec = CALLOC_STRUCT(nouveau_vp3_decoder);
   if (!dec)
      return NULL;
   dec->client = screen->client;
   dec->base = *templ;
   nouveau_vp3_decoder_init_common(&dec->base);

   if (!kepler) {
      dec->bsp_idx = 5;
      dec->vp_idx = 6;
      dec->ppp_idx = 7;
   } else {
      dec->bsp_idx = 2;
      dec->vp_idx = 2;
      dec->ppp_idx = 2;
   }

   for (i = 0; i < 3; ++i)
      if (i && !kepler) {
         dec->channel[i] = dec->channel[0];
         dec->pushbuf[i] = dec->pushbuf[0];
      } else {
         void *data;
         u32 size;
         struct nvc0_fifo nvc0_args = {};
         struct nve0_fifo nve0_args = {};

         if (!kepler) {
            size = sizeof(nvc0_args);
            data = &nvc0_args;
         } else {
            unsigned engine[] = {
               NVE0_FIFO_ENGINE_BSP,
               NVE0_FIFO_ENGINE_VP,
               NVE0_FIFO_ENGINE_PPP
            };

            nve0_args.engine = engine[i];
            size = sizeof(nve0_args);
            data = &nve0_args;
         }

         ret = nouveau_object_new(&screen->device->object, 0,
                                  NOUVEAU_FIFO_CHANNEL_CLASS,
                                  data, size, &dec->channel[i]);

         if (!ret)
            ret = nouveau_pushbuf_new(screen->client, dec->channel[i], 4,
                                   32 * 1024, true, &dec->pushbuf[i]);
         if (ret)
            break;
      }
   push = dec->pushbuf;

   if (!kepler) {
      if (!ret)
         ret = nouveau_object_new(dec->channel[0], 0x390b1, 0x90b1, NULL, 0, &dec->bsp);
      if (!ret)
         ret = nouveau_object_new(dec->channel[1], 0x190b2, 0x90b2, NULL, 0, &dec->vp);
      if (!ret)
         ret = nouveau_object_new(dec->channel[2], 0x290b3, 0x90b3, NULL, 0, &dec->ppp);
   } else {
      if (!ret)
         ret = nouveau_object_new(dec->channel[0], 0x95b1, 0x95b1, NULL, 0, &dec->bsp);
      if (!ret)
         ret = nouveau_object_new(dec->channel[1], 0x95b2, 0x95b2, NULL, 0, &dec->vp);
      if (!ret)
         ret = nouveau_object_new(dec->channel[2], 0x90b3, 0x90b3, NULL, 0, &dec->ppp);
   }
   if (ret)
      goto fail;

   BEGIN_NVC0(push[0], SUBC_BSP(NV01_SUBCHAN_OBJECT), 1);
   PUSH_DATA (push[0], dec->bsp->handle);

   BEGIN_NVC0(push[1], SUBC_VP(NV01_SUBCHAN_OBJECT), 1);
   PUSH_DATA (push[1], dec->vp->handle);

   BEGIN_NVC0(push[2], SUBC_PPP(NV01_SUBCHAN_OBJECT), 1);
   PUSH_DATA (push[2], dec->ppp->handle);

   dec->base.context = context;
   dec->base.decode_bitstream = nvc0_decoder_decode_bitstream;

   for (i = 0; i < NOUVEAU_VP3_VIDEO_QDEPTH && !ret; ++i)
      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
                           0, 1 << 20, &cfg, &dec->bsp_bo[i]);
   if (!ret)
      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
                           0x100, 4 << 20, &cfg, &dec->inter_bo[0]);
   if (!ret) {
      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM,
                           0x100, dec->inter_bo[0]->size, &cfg,
                           &dec->inter_bo[1]);
   }
   if (ret)
      goto fail;
   switch (u_reduce_video_profile(templ->profile)) {
   case PIPE_VIDEO_FORMAT_MPEG12: {
      codec = 1;
      assert(templ->max_references <= 2);
      break;
   }
   case PIPE_VIDEO_FORMAT_MPEG4: {
      codec = 4;
      tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
      assert(templ->max_references <= 2);
      break;
   }
   case PIPE_VIDEO_FORMAT_VC1: {
      ppp_codec = codec = 2;
      tmp_size = mb(templ->height)*16 * mb(templ->width)*16;
      assert(templ->max_references <= 2);
      break;
   }
   case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
      codec = 3;
      dec->tmp_stride = 16 * mb_half(templ->width) * nouveau_vp3_video_align(templ->height) * 3 / 2;
      tmp_size = dec->tmp_stride * (templ->max_references + 1);
      assert(templ->max_references <= 16);
      break;
   }
   default:
      fprintf(stderr, "invalid codec\n");
      goto fail;
   }

   if (screen->device->chipset < 0xd0) {
      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
                           0x4000, &cfg, &dec->fw_bo);
      if (ret)
         goto fail;

      ret = nouveau_vp3_load_firmware(dec, templ->profile, screen->device->chipset);
      if (ret)
         goto fw_fail;
   }

   if (codec != 3) {
      ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
                           0x400, &cfg, &dec->bitplane_bo);
      if (ret)
         goto fail;
   }

   dec->ref_stride = mb(templ->width)*16 * (mb_half(templ->height)*32 + nouveau_vp3_video_align(templ->height)/2);
   ret = nouveau_bo_new(screen->device, NOUVEAU_BO_VRAM, 0,
                        dec->ref_stride * (templ->max_references+2) + tmp_size,
                        &cfg, &dec->ref_bo);
   if (ret)
      goto fail;

   timeout = 0;

   BEGIN_NVC0(push[0], SUBC_BSP(0x200), 2);
   PUSH_DATA (push[0], codec);
   PUSH_DATA (push[0], timeout);

   BEGIN_NVC0(push[1], SUBC_VP(0x200), 2);
   PUSH_DATA (push[1], codec);
   PUSH_DATA (push[1], timeout);

   BEGIN_NVC0(push[2], SUBC_PPP(0x200), 2);
   PUSH_DATA (push[2], ppp_codec);
   PUSH_DATA (push[2], timeout);

   ++dec->fence_seq;

#if NOUVEAU_VP3_DEBUG_FENCE
   ret = nouveau_bo_new(screen->device, NOUVEAU_BO_GART|NOUVEAU_BO_MAP,
                        0, 0x1000, NULL, &dec->fence_bo);
   if (ret)
      goto fail;

   nouveau_bo_map(dec->fence_bo, NOUVEAU_BO_RDWR, screen->client);
   dec->fence_map = dec->fence_bo->map;
   dec->fence_map[0] = dec->fence_map[4] = dec->fence_map[8] = 0;
   dec->comm = (struct comm *)(dec->fence_map + (COMM_OFFSET/sizeof(*dec->fence_map)));

   /* So lets test if the fence is working? */
   nouveau_pushbuf_space(push[0], 6, 1, 0);
   PUSH_REFN (push[0], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
   BEGIN_NVC0(push[0], SUBC_BSP(0x240), 3);
   PUSH_DATAh(push[0], dec->fence_bo->offset);
   PUSH_DATA (push[0], dec->fence_bo->offset);
   PUSH_DATA (push[0], dec->fence_seq);

   BEGIN_NVC0(push[0], SUBC_BSP(0x304), 1);
   PUSH_DATA (push[0], 0);
   PUSH_KICK (push[0]);

   nouveau_pushbuf_space(push[1], 6, 1, 0);
   PUSH_REFN (push[1], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
   BEGIN_NVC0(push[1], SUBC_VP(0x240), 3);
   PUSH_DATAh(push[1], (dec->fence_bo->offset + 0x10));
   PUSH_DATA (push[1], (dec->fence_bo->offset + 0x10));
   PUSH_DATA (push[1], dec->fence_seq);

   BEGIN_NVC0(push[1], SUBC_VP(0x304), 1);
   PUSH_DATA (push[1], 0);
   PUSH_KICK (push[1]);

   nouveau_pushbuf_space(push[2], 6, 1, 0);
   PUSH_REFN (push[2], dec->fence_bo, NOUVEAU_BO_GART|NOUVEAU_BO_RDWR);
   BEGIN_NVC0(push[2], SUBC_PPP(0x240), 3);
   PUSH_DATAh(push[2], (dec->fence_bo->offset + 0x20));
   PUSH_DATA (push[2], (dec->fence_bo->offset + 0x20));
   PUSH_DATA (push[2], dec->fence_seq);

   BEGIN_NVC0(push[2], SUBC_PPP(0x304), 1);
   PUSH_DATA (push[2], 0);
   PUSH_KICK (push[2]);

   usleep(100);
   while (dec->fence_seq > dec->fence_map[0] ||
          dec->fence_seq > dec->fence_map[4] ||
          dec->fence_seq > dec->fence_map[8]) {
      debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
      usleep(100);
   }
   debug_printf("%u: %u %u %u\n", dec->fence_seq, dec->fence_map[0], dec->fence_map[4], dec->fence_map[8]);
#endif

   return &dec->base;

fw_fail:
   debug_printf("Cannot create decoder without firmware..\n");
   dec->base.destroy(&dec->base);
   return NULL;

fail:
   debug_printf("Creation failed: %s (%i)\n", strerror(-ret), ret);
   dec->base.destroy(&dec->base);
   return NULL;
}
예제 #17
0
static void
nv30_transfer_rect_blit(XFER_ARGS)
{
   struct nv04_resource *fp = nv30_transfer_rect_fragprog(nv30);
   struct nouveau_heap *vp = nv30_transfer_rect_vertprog(nv30);
   struct nouveau_pushbuf *push = nv30->base.pushbuf;
   struct nouveau_pushbuf_refn refs[] = {
      { fp->bo, fp->domain | NOUVEAU_BO_RD },
      { src->bo, src->domain | NOUVEAU_BO_RD },
      { dst->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR },
   };
   u32 texfmt, texswz;
   u32 format, stride;

   if (nouveau_pushbuf_space(push, 512, 8, 0) ||
       nouveau_pushbuf_refn (push, refs, sizeof(refs) / sizeof(refs[0])))
      return;

   /* various switches depending on cpp of the transfer */
   switch (dst->cpp) {
   case 4:
      format = NV30_3D_RT_FORMAT_COLOR_A8R8G8B8 |
               NV30_3D_RT_FORMAT_ZETA_Z24S8;
      texfmt = NV40_3D_TEX_FORMAT_FORMAT_A8R8G8B8;
      texswz = 0x0000aae4;
      break;
   case 2:
      format = NV30_3D_RT_FORMAT_COLOR_R5G6B5 |
               NV30_3D_RT_FORMAT_ZETA_Z16;
      texfmt = NV40_3D_TEX_FORMAT_FORMAT_R5G6B5;
      texswz = 0x0000a9e4;
      break;
   case 1:
      format = NV30_3D_RT_FORMAT_COLOR_B8 |
               NV30_3D_RT_FORMAT_ZETA_Z16;
      texfmt = NV40_3D_TEX_FORMAT_FORMAT_L8;
      texswz = 0x0000aaff;
      break;
   default:
      assert(0);
      return;
   }

   /* render target */
   if (!dst->pitch) {
      format |= NV30_3D_RT_FORMAT_TYPE_SWIZZLED;
      format |= util_logbase2(dst->w) << 16;
      format |= util_logbase2(dst->h) << 24;
      stride  = 64;
   } else {
      format |= NV30_3D_RT_FORMAT_TYPE_LINEAR;
      stride  = dst->pitch;
   }

   BEGIN_NV04(push, NV30_3D(VIEWPORT_HORIZ), 2);
   PUSH_DATA (push, dst->w << 16);
   PUSH_DATA (push, dst->h << 16);
   BEGIN_NV04(push, NV30_3D(RT_HORIZ), 5);
   PUSH_DATA (push, dst->w << 16);
   PUSH_DATA (push, dst->h << 16);
   PUSH_DATA (push, format);
   PUSH_DATA (push, stride);
   PUSH_RELOC(push, dst->bo, dst->offset, NOUVEAU_BO_LOW, 0, 0);
   BEGIN_NV04(push, NV30_3D(RT_ENABLE), 1);
   PUSH_DATA (push, NV30_3D_RT_ENABLE_COLOR0);

   nv30->dirty |= NV30_NEW_FRAMEBUFFER;

   /* viewport state */
   BEGIN_NV04(push, NV30_3D(VIEWPORT_TRANSLATE_X), 8);
   PUSH_DATAf(push, 0.0);
   PUSH_DATAf(push, 0.0);
   PUSH_DATAf(push, 0.0);
   PUSH_DATAf(push, 0.0);
   PUSH_DATAf(push, 1.0);
   PUSH_DATAf(push, 1.0);
   PUSH_DATAf(push, 1.0);
   PUSH_DATAf(push, 1.0);
   BEGIN_NV04(push, NV30_3D(DEPTH_RANGE_NEAR), 2);
   PUSH_DATAf(push, 0.0);
   PUSH_DATAf(push, 1.0);

   nv30->dirty |= NV30_NEW_VIEWPORT;

   /* blend state */
   BEGIN_NV04(push, NV30_3D(COLOR_LOGIC_OP_ENABLE), 1);
   PUSH_DATA (push, 0);
   BEGIN_NV04(push, NV30_3D(DITHER_ENABLE), 1);
   PUSH_DATA (push, 0);
   BEGIN_NV04(push, NV30_3D(BLEND_FUNC_ENABLE), 1);
   PUSH_DATA (push, 0);
   BEGIN_NV04(push, NV30_3D(COLOR_MASK), 1);
   PUSH_DATA (push, 0x01010101);

   nv30->dirty |= NV30_NEW_BLEND;

   /* depth-stencil-alpha state */
   BEGIN_NV04(push, NV30_3D(DEPTH_WRITE_ENABLE), 2);
   PUSH_DATA (push, 0);
   PUSH_DATA (push, 0);
   BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(0)), 1);
   PUSH_DATA (push, 0);
   BEGIN_NV04(push, NV30_3D(STENCIL_ENABLE(1)), 1);
   PUSH_DATA (push, 0);
   BEGIN_NV04(push, NV30_3D(ALPHA_FUNC_ENABLE), 1);
   PUSH_DATA (push, 0);

   nv30->dirty |= NV30_NEW_ZSA;

   /* rasterizer state */
   BEGIN_NV04(push, NV30_3D(SHADE_MODEL), 1);
   PUSH_DATA (push, NV30_3D_SHADE_MODEL_FLAT);
   BEGIN_NV04(push, NV30_3D(CULL_FACE_ENABLE), 1);
   PUSH_DATA (push, 0);
   BEGIN_NV04(push, NV30_3D(POLYGON_MODE_FRONT), 2);
   PUSH_DATA (push, NV30_3D_POLYGON_MODE_FRONT_FILL);
   PUSH_DATA (push, NV30_3D_POLYGON_MODE_BACK_FILL);
   BEGIN_NV04(push, NV30_3D(POLYGON_OFFSET_FILL_ENABLE), 1);
   PUSH_DATA (push, 0);
   BEGIN_NV04(push, NV30_3D(POLYGON_STIPPLE_ENABLE), 1);
   PUSH_DATA (push, 0);

   nv30->state.scissor_off = 0;
   nv30->dirty |= NV30_NEW_RASTERIZER;

   /* vertex program */
   BEGIN_NV04(push, NV30_3D(VP_START_FROM_ID), 1);
   PUSH_DATA (push, vp->start);
   BEGIN_NV04(push, NV40_3D(VP_ATTRIB_EN), 2);
   PUSH_DATA (push, 0x00000101); /* attrib: 0, 8 */
   PUSH_DATA (push, 0x00004000); /* result: hpos, tex0 */
   BEGIN_NV04(push, NV30_3D(ENGINE), 1);
   PUSH_DATA (push, 0x00000103);
   BEGIN_NV04(push, NV30_3D(VP_CLIP_PLANES_ENABLE), 1);
   PUSH_DATA (push, 0x00000000);

   nv30->dirty |= NV30_NEW_VERTPROG;
   nv30->dirty |= NV30_NEW_CLIP;

   /* fragment program */
   BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1);
   PUSH_RELOC(push, fp->bo, fp->offset, fp->domain |
                    NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
                    NV30_3D_FP_ACTIVE_PROGRAM_DMA0,
                    NV30_3D_FP_ACTIVE_PROGRAM_DMA1);
   BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1);
   PUSH_DATA (push, 0x02000000);

   nv30->state.fragprog = NULL;
   nv30->dirty |= NV30_NEW_FRAGPROG;

   /* texture */
   texfmt |= 1 << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT;
   texfmt |= NV30_3D_TEX_FORMAT_NO_BORDER;
   texfmt |= NV40_3D_TEX_FORMAT_RECT;
   texfmt |= 0x00008000;
   if (src->d < 2)
      texfmt |= NV30_3D_TEX_FORMAT_DIMS_2D;
   else
      texfmt |= NV30_3D_TEX_FORMAT_DIMS_3D;
   if (src->pitch)
      texfmt |= NV40_3D_TEX_FORMAT_LINEAR;

   BEGIN_NV04(push, NV30_3D(TEX_OFFSET(0)), 8);
   PUSH_RELOC(push, src->bo, src->offset, NOUVEAU_BO_LOW, 0, 0);
   PUSH_RELOC(push, src->bo, texfmt, NOUVEAU_BO_OR,
                    NV30_3D_TEX_FORMAT_DMA0, NV30_3D_TEX_FORMAT_DMA1);
   PUSH_DATA (push, NV30_3D_TEX_WRAP_S_CLAMP_TO_EDGE |
                    NV30_3D_TEX_WRAP_T_CLAMP_TO_EDGE |
                    NV30_3D_TEX_WRAP_R_CLAMP_TO_EDGE);
   PUSH_DATA (push, NV40_3D_TEX_ENABLE_ENABLE);
   PUSH_DATA (push, texswz);
   switch (filter) {
   case BILINEAR:
      PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_LINEAR |
                       NV30_3D_TEX_FILTER_MAG_LINEAR | 0x00002000);
      break;
   default:
      PUSH_DATA (push, NV30_3D_TEX_FILTER_MIN_NEAREST |
                       NV30_3D_TEX_FILTER_MAG_NEAREST | 0x00002000);
      break;
   }
   PUSH_DATA (push, (src->w << 16) | src->h);
   PUSH_DATA (push, 0x00000000);
   BEGIN_NV04(push, NV40_3D(TEX_SIZE1(0)), 1);
   PUSH_DATA (push, 0x00100000 | src->pitch);
   BEGIN_NV04(push, SUBC_3D(0x0b40), 1);
   PUSH_DATA (push, src->d < 2 ? 0x00000001 : 0x00000000);
   BEGIN_NV04(push, NV40_3D(TEX_CACHE_CTL), 1);
   PUSH_DATA (push, 1);

   nv30->fragprog.dirty_samplers |= 1;
   nv30->dirty |= NV30_NEW_FRAGTEX;

   /* blit! */
   BEGIN_NV04(push, NV30_3D(SCISSOR_HORIZ), 2);
   PUSH_DATA (push, (dst->x1 - dst->x0) << 16 | dst->x0);
   PUSH_DATA (push, (dst->y1 - dst->y0) << 16 | dst->y0);
   BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
   PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_QUADS);
   BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3);
   PUSH_DATAf(push, src->x0);
   PUSH_DATAf(push, src->y0);
   PUSH_DATAf(push, src->z);
   BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);
   PUSH_DATA (push, (dst->y0 << 16) | dst->x0);
   BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3);
   PUSH_DATAf(push, src->x1);
   PUSH_DATAf(push, src->y0);
   PUSH_DATAf(push, src->z);
   BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);
   PUSH_DATA (push, (dst->y0 << 16) | dst->x1);
   BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3);
   PUSH_DATAf(push, src->x1);
   PUSH_DATAf(push, src->y1);
   PUSH_DATAf(push, src->z);
   BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);
   PUSH_DATA (push, (dst->y1 << 16) | dst->x1);
   BEGIN_NV04(push, NV30_3D(VTX_ATTR_3F(8)), 3);
   PUSH_DATAf(push, src->x0);
   PUSH_DATAf(push, src->y1);
   PUSH_DATAf(push, src->z);
   BEGIN_NV04(push, NV30_3D(VTX_ATTR_2I(0)), 1);
   PUSH_DATA (push, (dst->y1 << 16) | dst->x0);
   BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1);
   PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP);
}