예제 #1
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;
   }
}
예제 #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
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;
    }
}
예제 #4
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);
}
예제 #5
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;
}
예제 #6
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);
   }
}
예제 #7
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);
}
예제 #8
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);
}
예제 #9
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);
    }
}