vbo: pass the stream from DrawTransformFeedbackStream to drivers
[mesa.git] / src / mesa / drivers / dri / nouveau / nv04_surface.c
index e3febf7d2f76540bcb7b323e0fbbebc1f10bd00d..968c05f6593d8fbc5f39dfc99add5615ba53fed1 100644 (file)
  */
 
 #include "nouveau_driver.h"
-#include "nouveau_class.h"
+#include "nv_object.xml.h"
+#include "nv_m2mf.xml.h"
+#include "nv01_2d.xml.h"
+#include "nv04_3d.xml.h"
 #include "nouveau_context.h"
 #include "nouveau_util.h"
 #include "nv04_driver.h"
 
 static inline int
-swzsurf_format(gl_format format)
+swzsurf_format(mesa_format format)
 {
        switch (format) {
-       case MESA_FORMAT_A8:
-       case MESA_FORMAT_L8:
-       case MESA_FORMAT_I8:
-       case MESA_FORMAT_RGB332:
-       case MESA_FORMAT_CI8:
+       case MESA_FORMAT_A_UNORM8:
+       case MESA_FORMAT_L_UNORM8:
+       case MESA_FORMAT_I_UNORM8:
+       case MESA_FORMAT_B2G3R3_UNORM:
                return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y8;
 
-       case MESA_FORMAT_RGB565:
-       case MESA_FORMAT_RGB565_REV:
-       case MESA_FORMAT_ARGB4444:
-       case MESA_FORMAT_ARGB4444_REV:
-       case MESA_FORMAT_ARGB1555:
-       case MESA_FORMAT_RGBA5551:
-       case MESA_FORMAT_ARGB1555_REV:
-       case MESA_FORMAT_AL88:
-       case MESA_FORMAT_AL88_REV:
+       case MESA_FORMAT_B5G6R5_UNORM:
+       case MESA_FORMAT_R5G6B5_UNORM:
+       case MESA_FORMAT_B4G4R4A4_UNORM:
+       case MESA_FORMAT_A4R4G4B4_UNORM:
+       case MESA_FORMAT_B5G5R5A1_UNORM:
+       case MESA_FORMAT_A1B5G5R5_UNORM:
+       case MESA_FORMAT_A1R5G5B5_UNORM:
+       case MESA_FORMAT_L8A8_UNORM:
+       case MESA_FORMAT_A8L8_UNORM:
        case MESA_FORMAT_YCBCR:
        case MESA_FORMAT_YCBCR_REV:
-       case MESA_FORMAT_Z16:
+       case MESA_FORMAT_Z_UNORM16:
                return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_R5G6B5;
 
-       case MESA_FORMAT_RGBA8888:
-       case MESA_FORMAT_RGBA8888_REV:
-       case MESA_FORMAT_XRGB8888:
-       case MESA_FORMAT_ARGB8888:
-       case MESA_FORMAT_ARGB8888_REV:
-       case MESA_FORMAT_S8_Z24:
-       case MESA_FORMAT_Z24_S8:
-       case MESA_FORMAT_Z32:
+       case MESA_FORMAT_A8B8G8R8_UNORM:
+       case MESA_FORMAT_R8G8B8A8_UNORM:
+       case MESA_FORMAT_B8G8R8X8_UNORM:
+       case MESA_FORMAT_B8G8R8A8_UNORM:
+       case MESA_FORMAT_A8R8G8B8_UNORM:
+       case MESA_FORMAT_Z24_UNORM_S8_UINT:
+       case MESA_FORMAT_S8_UINT_Z24_UNORM:
+       case MESA_FORMAT_Z_UNORM32:
                return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_A8R8G8B8;
 
        default:
@@ -71,38 +73,37 @@ swzsurf_format(gl_format format)
 }
 
 static inline int
-surf2d_format(gl_format format)
+surf2d_format(mesa_format format)
 {
        switch (format) {
-       case MESA_FORMAT_A8:
-       case MESA_FORMAT_L8:
-       case MESA_FORMAT_I8:
-       case MESA_FORMAT_RGB332:
-       case MESA_FORMAT_CI8:
+       case MESA_FORMAT_A_UNORM8:
+       case MESA_FORMAT_L_UNORM8:
+       case MESA_FORMAT_I_UNORM8:
+       case MESA_FORMAT_B2G3R3_UNORM:
                return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
 
-       case MESA_FORMAT_RGB565:
-       case MESA_FORMAT_RGB565_REV:
-       case MESA_FORMAT_ARGB4444:
-       case MESA_FORMAT_ARGB4444_REV:
-       case MESA_FORMAT_ARGB1555:
-       case MESA_FORMAT_RGBA5551:
-       case MESA_FORMAT_ARGB1555_REV:
-       case MESA_FORMAT_AL88:
-       case MESA_FORMAT_AL88_REV:
+       case MESA_FORMAT_B5G6R5_UNORM:
+       case MESA_FORMAT_R5G6B5_UNORM:
+       case MESA_FORMAT_B4G4R4A4_UNORM:
+       case MESA_FORMAT_A4R4G4B4_UNORM:
+       case MESA_FORMAT_B5G5R5A1_UNORM:
+       case MESA_FORMAT_A1B5G5R5_UNORM:
+       case MESA_FORMAT_A1R5G5B5_UNORM:
+       case MESA_FORMAT_L8A8_UNORM:
+       case MESA_FORMAT_A8L8_UNORM:
        case MESA_FORMAT_YCBCR:
        case MESA_FORMAT_YCBCR_REV:
-       case MESA_FORMAT_Z16:
+       case MESA_FORMAT_Z_UNORM16:
                return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
 
-       case MESA_FORMAT_RGBA8888:
-       case MESA_FORMAT_RGBA8888_REV:
-       case MESA_FORMAT_XRGB8888:
-       case MESA_FORMAT_ARGB8888:
-       case MESA_FORMAT_ARGB8888_REV:
-       case MESA_FORMAT_S8_Z24:
-       case MESA_FORMAT_Z24_S8:
-       case MESA_FORMAT_Z32:
+       case MESA_FORMAT_A8B8G8R8_UNORM:
+       case MESA_FORMAT_R8G8B8A8_UNORM:
+       case MESA_FORMAT_B8G8R8X8_UNORM:
+       case MESA_FORMAT_B8G8R8A8_UNORM:
+       case MESA_FORMAT_A8R8G8B8_UNORM:
+       case MESA_FORMAT_Z24_UNORM_S8_UINT:
+       case MESA_FORMAT_S8_UINT_Z24_UNORM:
+       case MESA_FORMAT_Z_UNORM32:
                return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
 
        default:
@@ -111,38 +112,37 @@ surf2d_format(gl_format format)
 }
 
 static inline int
-rect_format(gl_format format)
+rect_format(mesa_format format)
 {
        switch (format) {
-       case MESA_FORMAT_A8:
-       case MESA_FORMAT_L8:
-       case MESA_FORMAT_I8:
-       case MESA_FORMAT_RGB332:
-       case MESA_FORMAT_CI8:
+       case MESA_FORMAT_A_UNORM8:
+       case MESA_FORMAT_L_UNORM8:
+       case MESA_FORMAT_I_UNORM8:
+       case MESA_FORMAT_B2G3R3_UNORM:
                return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
 
-       case MESA_FORMAT_RGB565:
-       case MESA_FORMAT_RGB565_REV:
-       case MESA_FORMAT_ARGB4444:
-       case MESA_FORMAT_ARGB4444_REV:
-       case MESA_FORMAT_ARGB1555:
-       case MESA_FORMAT_RGBA5551:
-       case MESA_FORMAT_ARGB1555_REV:
-       case MESA_FORMAT_AL88:
-       case MESA_FORMAT_AL88_REV:
+       case MESA_FORMAT_B5G6R5_UNORM:
+       case MESA_FORMAT_R5G6B5_UNORM:
+       case MESA_FORMAT_B4G4R4A4_UNORM:
+       case MESA_FORMAT_A4R4G4B4_UNORM:
+       case MESA_FORMAT_B5G5R5A1_UNORM:
+       case MESA_FORMAT_A1B5G5R5_UNORM:
+       case MESA_FORMAT_A1R5G5B5_UNORM:
+       case MESA_FORMAT_L8A8_UNORM:
+       case MESA_FORMAT_A8L8_UNORM:
        case MESA_FORMAT_YCBCR:
        case MESA_FORMAT_YCBCR_REV:
-       case MESA_FORMAT_Z16:
+       case MESA_FORMAT_Z_UNORM16:
                return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
 
-       case MESA_FORMAT_RGBA8888:
-       case MESA_FORMAT_RGBA8888_REV:
-       case MESA_FORMAT_XRGB8888:
-       case MESA_FORMAT_ARGB8888:
-       case MESA_FORMAT_ARGB8888_REV:
-       case MESA_FORMAT_S8_Z24:
-       case MESA_FORMAT_Z24_S8:
-       case MESA_FORMAT_Z32:
+       case MESA_FORMAT_A8B8G8R8_UNORM:
+       case MESA_FORMAT_R8G8B8A8_UNORM:
+       case MESA_FORMAT_B8G8R8X8_UNORM:
+       case MESA_FORMAT_B8G8R8A8_UNORM:
+       case MESA_FORMAT_A8R8G8B8_UNORM:
+       case MESA_FORMAT_Z24_UNORM_S8_UINT:
+       case MESA_FORMAT_S8_UINT_Z24_UNORM:
+       case MESA_FORMAT_Z_UNORM32:
                return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
 
        default:
@@ -151,38 +151,37 @@ rect_format(gl_format format)
 }
 
 static inline int
-sifm_format(gl_format format)
+sifm_format(mesa_format format)
 {
        switch (format) {
-       case MESA_FORMAT_A8:
-       case MESA_FORMAT_L8:
-       case MESA_FORMAT_I8:
-       case MESA_FORMAT_RGB332:
-       case MESA_FORMAT_CI8:
+       case MESA_FORMAT_A_UNORM8:
+       case MESA_FORMAT_L_UNORM8:
+       case MESA_FORMAT_I_UNORM8:
+       case MESA_FORMAT_B2G3R3_UNORM:
                return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_AY8;
 
-       case MESA_FORMAT_RGB565:
-       case MESA_FORMAT_RGB565_REV:
-       case MESA_FORMAT_ARGB4444:
-       case MESA_FORMAT_ARGB4444_REV:
-       case MESA_FORMAT_ARGB1555:
-       case MESA_FORMAT_RGBA5551:
-       case MESA_FORMAT_ARGB1555_REV:
-       case MESA_FORMAT_AL88:
-       case MESA_FORMAT_AL88_REV:
+       case MESA_FORMAT_B5G6R5_UNORM:
+       case MESA_FORMAT_R5G6B5_UNORM:
+       case MESA_FORMAT_B4G4R4A4_UNORM:
+       case MESA_FORMAT_A4R4G4B4_UNORM:
+       case MESA_FORMAT_B5G5R5A1_UNORM:
+       case MESA_FORMAT_A1B5G5R5_UNORM:
+       case MESA_FORMAT_A1R5G5B5_UNORM:
+       case MESA_FORMAT_L8A8_UNORM:
+       case MESA_FORMAT_A8L8_UNORM:
        case MESA_FORMAT_YCBCR:
        case MESA_FORMAT_YCBCR_REV:
-       case MESA_FORMAT_Z16:
+       case MESA_FORMAT_Z_UNORM16:
                return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
 
-       case MESA_FORMAT_RGBA8888:
-       case MESA_FORMAT_RGBA8888_REV:
-       case MESA_FORMAT_XRGB8888:
-       case MESA_FORMAT_ARGB8888:
-       case MESA_FORMAT_ARGB8888_REV:
-       case MESA_FORMAT_S8_Z24:
-       case MESA_FORMAT_Z24_S8:
-       case MESA_FORMAT_Z32:
+       case MESA_FORMAT_A8B8G8R8_UNORM:
+       case MESA_FORMAT_R8G8B8A8_UNORM:
+       case MESA_FORMAT_B8G8R8X8_UNORM:
+       case MESA_FORMAT_B8G8R8A8_UNORM:
+       case MESA_FORMAT_A8R8G8B8_UNORM:
+       case MESA_FORMAT_Z24_UNORM_S8_UINT:
+       case MESA_FORMAT_S8_UINT_Z24_UNORM:
+       case MESA_FORMAT_Z_UNORM32:
                return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
 
        default:
@@ -191,18 +190,20 @@ sifm_format(gl_format format)
 }
 
 static void
-nv04_surface_copy_swizzle(GLcontext *ctx,
+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_channel *chan = context_chan(ctx);
+       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_grobj *swzsurf = hw->swzsurf;
-       struct nouveau_grobj *sifm = hw->sifm;
-       struct nouveau_bo_context *bctx = context_bctx(ctx, SURFACE);
-       const unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART;
+       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;
@@ -214,25 +215,10 @@ nv04_surface_copy_swizzle(GLcontext *ctx,
        assert(_mesa_is_pow_two(dst->width) &&
               _mesa_is_pow_two(dst->height));
 
-        /* If area is too large to copy in one shot we must copy it in
-        * POT chunks to meet alignment requirements */
-       assert(sub_w == w || _mesa_is_pow_two(w));
-       assert(sub_h == h || _mesa_is_pow_two(h));
-
-       nouveau_bo_marko(bctx, sifm, NV03_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE,
-                        src->bo, bo_flags | NOUVEAU_BO_RD);
-       nouveau_bo_marko(bctx, swzsurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE,
-                        dst->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-       nouveau_bo_markl(bctx, swzsurf, NV04_SWIZZLED_SURFACE_OFFSET,
-                        dst->bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-
-       BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_FORMAT, 1);
-       OUT_RING  (chan, swzsurf_format(dst->format) |
-                  log2i(dst->width) << 16 |
-                  log2i(dst->height) << 24);
-
-       BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE, 1);
-       OUT_RING  (chan, swzsurf->handle);
+       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);
@@ -240,85 +226,91 @@ nv04_surface_copy_swizzle(GLcontext *ctx,
                for (x = 0; x < w; x += sub_w) {
                        sub_w = MIN2(sub_w, w - x);
 
-                       MARK_RING(chan, 15, 1);
-
-                       BEGIN_RING(chan, sifm,
-                                  NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT, 8);
-                       OUT_RING(chan, sifm_format(src->format));
-                       OUT_RING(chan, NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
-                       OUT_RING(chan, (y + dy) << 16 | (x + dx));
-                       OUT_RING(chan, sub_h << 16 | sub_w);
-                       OUT_RING(chan, (y + dy) << 16 | (x + dx));
-                       OUT_RING(chan, sub_h << 16 | sub_w);
-                       OUT_RING(chan, 1 << 20);
-                       OUT_RING(chan, 1 << 20);
-
-                       BEGIN_RING(chan, sifm,
-                                  NV03_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
-                       OUT_RING(chan, sub_h << 16 | sub_w);
-                       OUT_RING(chan, src->pitch  |
-                                NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
-                                NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
-                       OUT_RELOCl(chan, src->bo, src->offset +
-                                  (y + sy) * src->pitch +
-                                  (x + sx) * src->cpp,
-                                  bo_flags | NOUVEAU_BO_RD);
-                       OUT_RING(chan, 0);
+                       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);
                }
        }
 
-       nouveau_bo_context_reset(bctx);
-
-       if (context_chipset(ctx) < 0x10)
-               FIRE_RING(chan);
+       if (context_chipset(ctx) < 0x10) {
+               BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1);
+               PUSH_DATA (push, hw->surf3d->handle);
+       }
 }
 
 static void
-nv04_surface_copy_m2mf(GLcontext *ctx,
+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_channel *chan = context_chan(ctx);
+       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 nouveau_grobj *m2mf = hw->m2mf;
-       struct nouveau_bo_context *bctx = context_bctx(ctx, SURFACE);
-       const unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART;
+       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;
 
-       nouveau_bo_marko(bctx, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN,
-                        src->bo, bo_flags | NOUVEAU_BO_RD);
-       nouveau_bo_marko(bctx, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_OUT,
-                        dst->bo, bo_flags | NOUVEAU_BO_WR);
-
        while (h) {
                int count = (h > 2047) ? 2047 : h;
 
-               MARK_RING(chan, 9, 2);
-
-               BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
-               OUT_RELOCl(chan, src->bo, src_offset,
-                          bo_flags | NOUVEAU_BO_RD);
-               OUT_RELOCl(chan, dst->bo, dst_offset,
-                          bo_flags | NOUVEAU_BO_WR);
-               OUT_RING  (chan, src->pitch);
-               OUT_RING  (chan, dst->pitch);
-               OUT_RING  (chan, w * src->cpp);
-               OUT_RING  (chan, count);
-               OUT_RING  (chan, 0x0101);
-               OUT_RING  (chan, 0);
+               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);
 
-               h -= count;
                src_offset += src->pitch * count;
                dst_offset += dst->pitch * count;
+               h -= count;
        }
-
-       nouveau_bo_context_reset(bctx);
-
-       if (context_chipset(ctx) < 0x10)
-               FIRE_RING(chan);
 }
 
 typedef unsigned (*get_offset_t)(struct nouveau_surface *s,
@@ -367,7 +359,7 @@ get_swizzled_offset(struct nouveau_surface *s, unsigned x, unsigned y)
 }
 
 static void
-nv04_surface_copy_cpu(GLcontext *ctx,
+nv04_surface_copy_cpu(struct gl_context *ctx,
                      struct nouveau_surface *dst,
                      struct nouveau_surface *src,
                      int dx, int dy, int sx, int sy,
@@ -380,8 +372,8 @@ nv04_surface_copy_cpu(GLcontext *ctx,
                                get_swizzled_offset : get_linear_offset);
        void *dp, *sp;
 
-       nouveau_bo_map(dst->bo, NOUVEAU_BO_WR);
-       nouveau_bo_map(src->bo, NOUVEAU_BO_RD);
+       nouveau_bo_map(dst->bo, NOUVEAU_BO_WR, context_client(ctx));
+       nouveau_bo_map(src->bo, NOUVEAU_BO_RD, context_client(ctx));
 
        dp = dst->bo->map + dst->offset;
        sp = src->bo->map + src->offset;
@@ -392,18 +384,24 @@ nv04_surface_copy_cpu(GLcontext *ctx,
                               sp + get_src(src, sx + x, sy + y), dst->cpp);
                }
        }
-
-       nouveau_bo_unmap(src->bo);
-       nouveau_bo_unmap(dst->bo);
 }
 
 void
-nv04_surface_copy(GLcontext *ctx,
+nv04_surface_copy(struct gl_context *ctx,
                  struct nouveau_surface *dst,
                  struct nouveau_surface *src,
                  int dx, int dy, int sx, int sy,
                  int w, int h)
 {
+       if (_mesa_is_format_compressed(src->format)) {
+               sx = get_format_blocksx(src->format, sx);
+               sy = get_format_blocksy(src->format, sy);
+               dx = get_format_blocksx(dst->format, dx);
+               dy = get_format_blocksy(dst->format, dy);
+               w = get_format_blocksx(src->format, w);
+               h = get_format_blocksy(src->format, h);
+       }
+
        /* Linear texture copy. */
        if ((src->layout == LINEAR && dst->layout == LINEAR) ||
            dst->width <= 2 || dst->height <= 1) {
@@ -423,170 +421,188 @@ nv04_surface_copy(GLcontext *ctx,
 }
 
 void
-nv04_surface_fill(GLcontext *ctx,
+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_channel *chan = context_chan(ctx);
+       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 nouveau_grobj *surf2d = hw->surf2d;
-       struct nouveau_grobj *patt = hw->patt;
-       struct nouveau_grobj *rect = hw->rect;
-       unsigned bo_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART;
-
-       MARK_RING (chan, 19, 4);
-
-       BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
-       OUT_RELOCo(chan, dst->bo, bo_flags | NOUVEAU_BO_WR);
-       OUT_RELOCo(chan, dst->bo, bo_flags | NOUVEAU_BO_WR);
-       BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
-       OUT_RING  (chan, surf2d_format(dst->format));
-       OUT_RING  (chan, (dst->pitch << 16) | dst->pitch);
-       OUT_RELOCl(chan, dst->bo, dst->offset, bo_flags | NOUVEAU_BO_WR);
-       OUT_RELOCl(chan, dst->bo, dst->offset, bo_flags | NOUVEAU_BO_WR);
-
-       BEGIN_RING(chan, patt, NV04_IMAGE_PATTERN_COLOR_FORMAT, 1);
-       OUT_RING  (chan, rect_format(dst->format));
-       BEGIN_RING(chan, patt, NV04_IMAGE_PATTERN_MONOCHROME_COLOR1, 1);
-       OUT_RING  (chan, mask | ~0ll << (8 * dst->cpp));
-
-       BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
-       OUT_RING  (chan, rect_format(dst->format));
-       BEGIN_RING(chan, rect, NV04_GDI_RECTANGLE_TEXT_COLOR1_A, 1);
-       OUT_RING  (chan, value);
-       BEGIN_RING(chan, rect,
-                  NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
-       OUT_RING  (chan, (dx << 16) | dy);
-       OUT_RING  (chan, ( w << 16) |  h);
+       struct nv04_fifo *fifo = hw->chan->data;
 
-       if (context_chipset(ctx) < 0x10)
-               FIRE_RING(chan);
+       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);
 }
 
 void
-nv04_surface_takedown(GLcontext *ctx)
+nv04_surface_takedown(struct gl_context *ctx)
 {
        struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
 
-       nouveau_grobj_free(&hw->swzsurf);
-       nouveau_grobj_free(&hw->sifm);
-       nouveau_grobj_free(&hw->rect);
-       nouveau_grobj_free(&hw->rop);
-       nouveau_grobj_free(&hw->patt);
-       nouveau_grobj_free(&hw->surf2d);
-       nouveau_grobj_free(&hw->m2mf);
-       nouveau_notifier_free(&hw->ntfy);
+       nouveau_object_del(&hw->swzsurf);
+       nouveau_object_del(&hw->sifm);
+       nouveau_object_del(&hw->rect);
+       nouveau_object_del(&hw->rop);
+       nouveau_object_del(&hw->patt);
+       nouveau_object_del(&hw->surf2d);
+       nouveau_object_del(&hw->m2mf);
+       nouveau_object_del(&hw->ntfy);
 }
 
 GLboolean
-nv04_surface_init(GLcontext *ctx)
+nv04_surface_init(struct gl_context *ctx)
 {
-       struct nouveau_channel *chan = context_chan(ctx);
+       struct nouveau_pushbuf *push = context_push(ctx);
        struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
+       struct nouveau_object *chan = hw->chan;
        unsigned handle = 0x88000000, class;
        int ret;
 
        /* Notifier object. */
-       ret = nouveau_notifier_alloc(chan, handle++, 1, &hw->ntfy);
+       ret = nouveau_object_new(chan, handle++, NOUVEAU_NOTIFIER_CLASS,
+                                &(struct nv04_notify) {
+                                       .length = 32,
+                                }, sizeof(struct nv04_notify), &hw->ntfy);
        if (ret)
                goto fail;
 
        /* Memory to memory format. */
-       ret = nouveau_grobj_alloc(chan, handle++, NV04_MEMORY_TO_MEMORY_FORMAT,
-                                 &hw->m2mf);
+       ret = nouveau_object_new(chan, handle++, NV03_M2MF_CLASS,
+                                NULL, 0, &hw->m2mf);
        if (ret)
                goto fail;
 
-       BEGIN_RING(chan, hw->m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
-       OUT_RING  (chan, hw->ntfy->handle);
+       BEGIN_NV04(push, NV01_SUBC(M2MF, OBJECT), 1);
+       PUSH_DATA (push, hw->m2mf->handle);
+       BEGIN_NV04(push, NV03_M2MF(DMA_NOTIFY), 1);
+       PUSH_DATA (push, hw->ntfy->handle);
 
        /* Context surfaces 2D. */
        if (context_chipset(ctx) < 0x10)
-               class = NV04_CONTEXT_SURFACES_2D;
+               class = NV04_SURFACE_2D_CLASS;
        else
-               class = NV10_CONTEXT_SURFACES_2D;
+               class = NV10_SURFACE_2D_CLASS;
 
-       ret = nouveau_grobj_alloc(chan, handle++, class, &hw->surf2d);
+       ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->surf2d);
        if (ret)
                goto fail;
 
+       BEGIN_NV04(push, NV01_SUBC(SF2D, OBJECT), 1);
+       PUSH_DATA (push, hw->surf2d->handle);
+
        /* Raster op. */
-       ret = nouveau_grobj_alloc(chan, handle++, NV03_CONTEXT_ROP, &hw->rop);
+       ret = nouveau_object_new(chan, handle++, NV03_ROP_CLASS,
+                                NULL, 0, &hw->rop);
        if (ret)
                goto fail;
 
-       BEGIN_RING(chan, hw->rop, NV03_CONTEXT_ROP_DMA_NOTIFY, 1);
-       OUT_RING  (chan, hw->ntfy->handle);
+       BEGIN_NV04(push, NV01_SUBC(PATT, OBJECT), 1);
+       PUSH_DATA (push, hw->rop->handle);
+       BEGIN_NV04(push, NV01_ROP(DMA_NOTIFY), 1);
+       PUSH_DATA (push, hw->ntfy->handle);
 
-       BEGIN_RING(chan, hw->rop, NV03_CONTEXT_ROP_ROP, 1);
-       OUT_RING  (chan, 0xca); /* DPSDxax in the GDI speech. */
+       BEGIN_NV04(push, NV01_ROP(ROP), 1);
+       PUSH_DATA (push, 0xca); /* DPSDxax in the GDI speech. */
 
        /* Image pattern. */
-       ret = nouveau_grobj_alloc(chan, handle++, NV04_IMAGE_PATTERN,
-                                 &hw->patt);
+       ret = nouveau_object_new(chan, handle++, NV04_PATTERN_CLASS,
+                                NULL, 0, &hw->patt);
        if (ret)
                goto fail;
 
-       BEGIN_RING(chan, hw->patt, NV04_IMAGE_PATTERN_DMA_NOTIFY, 1);
-       OUT_RING  (chan, hw->ntfy->handle);
+       BEGIN_NV04(push, NV01_SUBC(PATT, OBJECT), 1);
+       PUSH_DATA (push, hw->patt->handle);
+       BEGIN_NV04(push, NV01_PATT(DMA_NOTIFY), 1);
+       PUSH_DATA (push, hw->ntfy->handle);
 
-       BEGIN_RING(chan, hw->patt, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT, 3);
-       OUT_RING  (chan, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_LE);
-       OUT_RING  (chan, NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8);
-       OUT_RING  (chan, NV04_IMAGE_PATTERN_PATTERN_SELECT_MONO);
+       BEGIN_NV04(push, NV01_PATT(MONOCHROME_FORMAT), 3);
+       PUSH_DATA (push, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_LE);
+       PUSH_DATA (push, NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8);
+       PUSH_DATA (push, NV04_IMAGE_PATTERN_PATTERN_SELECT_MONO);
 
-       BEGIN_RING(chan, hw->patt, NV04_IMAGE_PATTERN_MONOCHROME_COLOR0, 4);
-       OUT_RING  (chan, 0);
-       OUT_RING  (chan, 0);
-       OUT_RING  (chan, ~0);
-       OUT_RING  (chan, ~0);
+       BEGIN_NV04(push, NV01_PATT(MONOCHROME_COLOR0), 4);
+       PUSH_DATA (push, 0);
+       PUSH_DATA (push, 0);
+       PUSH_DATA (push, ~0);
+       PUSH_DATA (push, ~0);
 
        /* GDI rectangle text. */
-       ret = nouveau_grobj_alloc(chan, handle++, NV04_GDI_RECTANGLE_TEXT,
-                                 &hw->rect);
+       ret = nouveau_object_new(chan, handle++, NV04_GDI_CLASS,
+                                NULL, 0, &hw->rect);
        if (ret)
                goto fail;
 
-       BEGIN_RING(chan, hw->rect, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1);
-       OUT_RING  (chan, hw->ntfy->handle);
-       BEGIN_RING(chan, hw->rect, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
-       OUT_RING  (chan, hw->surf2d->handle);
-       BEGIN_RING(chan, hw->rect, NV04_GDI_RECTANGLE_TEXT_ROP, 1);
-       OUT_RING  (chan, hw->rop->handle);
-       BEGIN_RING(chan, hw->rect, NV04_GDI_RECTANGLE_TEXT_PATTERN, 1);
-       OUT_RING  (chan, hw->patt->handle);
-
-       BEGIN_RING(chan, hw->rect, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
-       OUT_RING  (chan, NV04_GDI_RECTANGLE_TEXT_OPERATION_ROP_AND);
-       BEGIN_RING(chan, hw->rect,
-                  NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1);
-       OUT_RING  (chan, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
+       BEGIN_NV04(push, NV01_SUBC(GDI, OBJECT), 1);
+       PUSH_DATA (push, hw->rect->handle);
+       BEGIN_NV04(push, NV04_GDI(DMA_NOTIFY), 1);
+       PUSH_DATA (push, hw->ntfy->handle);
+       BEGIN_NV04(push, NV04_GDI(SURFACE), 1);
+       PUSH_DATA (push, hw->surf2d->handle);
+       BEGIN_NV04(push, NV04_GDI(ROP), 1);
+       PUSH_DATA (push, hw->rop->handle);
+       BEGIN_NV04(push, NV04_GDI(PATTERN), 1);
+       PUSH_DATA (push, hw->patt->handle);
+
+       BEGIN_NV04(push, NV04_GDI(OPERATION), 1);
+       PUSH_DATA (push, NV04_GDI_RECTANGLE_TEXT_OPERATION_ROP_AND);
+       BEGIN_NV04(push, NV04_GDI(MONOCHROME_FORMAT), 1);
+       PUSH_DATA (push, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
 
        /* Swizzled surface. */
        if (context_chipset(ctx) < 0x20)
-               class = NV04_SWIZZLED_SURFACE;
+               class = NV04_SURFACE_SWZ_CLASS;
        else
-               class = NV20_SWIZZLED_SURFACE;
+               class = NV20_SURFACE_SWZ_CLASS;
 
-       ret = nouveau_grobj_alloc(chan, handle++, class, &hw->swzsurf);
+       ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->swzsurf);
        if (ret)
                goto fail;
 
+       BEGIN_NV04(push, NV01_SUBC(SURF, OBJECT), 1);
+       PUSH_DATA (push, hw->swzsurf->handle);
+
        /* Scaled image from memory. */
        if  (context_chipset(ctx) < 0x10)
-               class = NV04_SCALED_IMAGE_FROM_MEMORY;
+               class = NV04_SIFM_CLASS;
        else
-               class = NV10_SCALED_IMAGE_FROM_MEMORY;
+               class = NV10_SIFM_CLASS;
 
-       ret = nouveau_grobj_alloc(chan, handle++, class, &hw->sifm);
+       ret = nouveau_object_new(chan, handle++, class, NULL, 0, &hw->sifm);
        if (ret)
                goto fail;
 
+       BEGIN_NV04(push, NV01_SUBC(SIFM, OBJECT), 1);
+       PUSH_DATA (push, hw->sifm->handle);
+
        if (context_chipset(ctx) >= 0x10) {
-               BEGIN_RING(chan, hw->sifm,
-                          NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 1);
-               OUT_RING(chan, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
+               BEGIN_NV04(push, NV05_SIFM(COLOR_CONVERSION), 1);
+               PUSH_DATA (push, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
        }
 
        return GL_TRUE;