nvfx: new 2D: rewrite transfer code to use staging transfers
authorLuca Barbieri <luca@luca-barbieri.com>
Tue, 3 Aug 2010 19:32:42 +0000 (21:32 +0200)
committerLuca Barbieri <luca@luca-barbieri.com>
Sat, 21 Aug 2010 18:42:14 +0000 (20:42 +0200)
This greatly simplifies the code, and avoids ad-hoc copy code.

Also, these new transfers work for buffers too, even though they
are still used for miptrees only.

src/gallium/drivers/nvfx/nvfx_miptree.c
src/gallium/drivers/nvfx/nvfx_transfer.c
src/gallium/drivers/nvfx/nvfx_transfer.h

index 0b08f888849502b35e5d34e3e52fe15c9ac29fb7..27bfa24b282ff940dbaaf401ef1b658c99da9215 100644 (file)
@@ -4,6 +4,7 @@
 #include "util/u_format.h"
 #include "util/u_memory.h"
 #include "util/u_math.h"
+#include "util/u_staging.h"
 #include "state_tracker/drm_driver.h"
 #include "nouveau/nouveau_winsys.h"
 #include "nouveau/nouveau_screen.h"
@@ -142,11 +143,11 @@ struct u_resource_vtbl nvfx_miptree_vtbl =
    nvfx_miptree_get_handle,          /* get_handle */
    nvfx_miptree_destroy,             /* resource_destroy */
    NULL,                             /* is_resource_referenced */
-   nvfx_miptree_transfer_new,        /* get_transfer */
-   nvfx_miptree_transfer_del,     /* transfer_destroy */
-   nvfx_miptree_transfer_map,        /* transfer_map */
+   nvfx_transfer_new,                /* get_transfer */
+   util_staging_transfer_destroy,     /* transfer_destroy */
+   nvfx_transfer_map,                /* transfer_map */
    u_default_transfer_flush_region,   /* transfer_flush_region */
-   nvfx_miptree_transfer_unmap,              /* transfer_unmap */
+   nvfx_transfer_unmap,                      /* transfer_unmap */
    u_default_transfer_inline_write    /* transfer_inline_write */
 };
 
index 957e586f81d90de9c7f7ff2e48179d0473962188..e9c3dd7e551332c09c9c9a5eee8ec1441160d925 100644 (file)
 #include "util/u_format.h"
 #include "util/u_memory.h"
 #include "util/u_math.h"
-#include "nouveau/nouveau_winsys.h"
+#include "util/u_staging.h"
 #include "nvfx_context.h"
 #include "nvfx_screen.h"
 #include "nvfx_state.h"
 #include "nvfx_resource.h"
 #include "nvfx_transfer.h"
 
-struct nvfx_transfer {
-       struct pipe_transfer base;
-       struct pipe_surface *surface;
-       boolean direct;
-};
-
-static void
-nvfx_compatible_transfer_tex(struct pipe_resource *pt, unsigned width, unsigned height,
-                            unsigned bind,
-                             struct pipe_resource *template)
-{
-       memset(template, 0, sizeof(struct pipe_resource));
-       template->target = pt->target;
-       template->format = pt->format;
-       template->width0 = width;
-       template->height0 = height;
-       template->depth0 = 1;
-       template->last_level = 0;
-       template->nr_samples = pt->nr_samples;
-       template->bind = bind;
-       template->usage = PIPE_USAGE_DYNAMIC;
-       template->flags = NVFX_RESOURCE_FLAG_LINEAR;
-}
-
-
-static unsigned nvfx_transfer_bind_flags( unsigned transfer_usage )
+struct nvfx_staging_transfer
 {
-       unsigned bind = 0;
+       struct util_staging_transfer base;
 
-#if 0
-       if (transfer_usage & PIPE_TRANSFER_WRITE)
-               bind |= PIPE_BIND_BLIT_SOURCE;
-
-       if (transfer_usage & PIPE_TRANSFER_READ)
-               bind |= PIPE_BIND_BLIT_DESTINATION;
-#endif
-
-       return bind;
-}
+       unsigned offset;
+       unsigned map_count;
+};
 
 struct pipe_transfer *
-nvfx_miptree_transfer_new(struct pipe_context *pipe,
+nvfx_transfer_new(struct pipe_context *pipe,
                          struct pipe_resource *pt,
                          struct pipe_subresource sr,
                          unsigned usage,
                          const struct pipe_box *box)
 {
-       struct pipe_screen *pscreen = pipe->screen;
-       struct nvfx_transfer *tx;
-       struct pipe_resource tx_tex_template, *tx_tex;
-       unsigned bind = nvfx_transfer_bind_flags(usage);
+       struct nvfx_staging_transfer* tx;
+       bool direct = !nvfx_resource_on_gpu(pt) && pt->flags & NVFX_RESOURCE_FLAG_LINEAR;
 
-       tx = CALLOC_STRUCT(nvfx_transfer);
-       if (!tx)
+       tx = CALLOC_STRUCT(nvfx_staging_transfer);
+       if(!tx)
                return NULL;
 
-       /* Don't handle 3D transfers yet.
-        */
-       assert(box->depth == 1);
-
-       pipe_resource_reference(&tx->base.resource, pt);
-       tx->base.sr = sr;
-       tx->base.stride = nvfx_subresource_pitch(pt, sr.level);
-       tx->base.slice_stride = tx->base.stride * u_minify(pt->height0, sr.level);
-       tx->base.usage = usage;
-       tx->base.box = *box;
+       util_staging_transfer_init(pipe, pt, sr, usage, box, direct, tx);
 
-       /* Direct access to texture */
-       if ((util_format_is_s3tc(pt->format) || pt->usage & PIPE_USAGE_DYNAMIC) &&
-           pt->flags & NVFX_RESOURCE_FLAG_LINEAR)
+       if(pt->target == PIPE_BUFFER)
        {
-               tx->direct = true;
-
-               /* XXX: just call the internal nvfx function.  
-                */
-               tx->surface = pscreen->get_tex_surface(pscreen, pt,
-                                                      sr.face, sr.level,
-                                                      box->z,
-                                                      bind);
-               return &tx->base;
+               tx->base.base.slice_stride = tx->base.base.stride = ((struct nvfx_resource*)tx->base.staging_resource)->bo->size;
+               if(direct)
+                       tx->offset = util_format_get_stride(pt->format, box->x);
+               else
+                       tx->offset = 0;
        }
-
-       tx->direct = false;
-
-       nvfx_compatible_transfer_tex(pt, box->width, box->height, bind, &tx_tex_template);
-
-       tx_tex = pscreen->resource_create(pscreen, &tx_tex_template);
-       if (!tx_tex)
+       else
        {
-               FREE(tx);
-               return NULL;
+               if(direct)
+               {
+                       tx->base.base.stride = nvfx_subresource_pitch(pt, sr.level);
+                       tx->base.base.slice_stride = tx->base.base.stride * u_minify(pt->height0, sr.level);
+                       tx->offset = nvfx_subresource_offset(pt, sr.face, sr.level, box->z)
+                               + util_format_get_2d_size(pt->format, tx->base.base.stride, box->y)
+                               + util_format_get_stride(pt->format, box->x);
+               }
+               else
+               {
+                       tx->base.base.stride = nvfx_subresource_pitch(tx->base.staging_resource, 0);
+                       tx->base.base.slice_stride = tx->base.base.stride * tx->base.staging_resource->height0;
+                       tx->offset = 0;
+               }
+
+               assert(tx->base.base.stride);
+
+               return &tx->base.base;
        }
-
-       tx->base.stride = ((struct nvfx_miptree*)tx_tex)->linear_pitch;
-       tx->base.slice_stride = tx->base.stride * box->height;
-
-       tx->surface = pscreen->get_tex_surface(pscreen, tx_tex,
-                                              0, 0, 0,
-                                              bind);
-
-       pipe_resource_reference(&tx_tex, NULL);
-
-       if (!tx->surface)
-       {
-               pipe_surface_reference(&tx->surface, NULL);
-               FREE(tx);
-               return NULL;
-       }
-
-       if (usage & PIPE_TRANSFER_READ) {
-               struct nvfx_screen *nvscreen = nvfx_screen(pscreen);
-               struct pipe_surface *src;
-
-               src = pscreen->get_tex_surface(pscreen, pt,
-                                              sr.face, sr.level, box->z,
-                                              0 /*PIPE_BIND_BLIT_SOURCE*/);
-
-               /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
-               /* TODO: Check if SIFM can un-swizzle */
-               nvscreen->eng2d->copy(nvscreen->eng2d,
-                                     tx->surface, 0, 0,
-                                     src,
-                                     box->x, box->y,
-                                     box->width, box->height);
-
-               pipe_surface_reference(&src, NULL);
-       }
-
-       return &tx->base;
-}
-
-void
-nvfx_miptree_transfer_del(struct pipe_context *pipe,
-                         struct pipe_transfer *ptx)
-{
-       struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx;
-
-       if (!tx->direct && (ptx->usage & PIPE_TRANSFER_WRITE)) {
-               struct pipe_screen *pscreen = pipe->screen;
-               struct nvfx_screen *nvscreen = nvfx_screen(pscreen);
-               struct pipe_surface *dst;
-
-               dst = pscreen->get_tex_surface(pscreen,
-                                              ptx->resource,
-                                              ptx->sr.face,
-                                              ptx->sr.level,
-                                              ptx->box.z,
-                                              0 /*PIPE_BIND_BLIT_DESTINATION*/);
-
-               /* TODO: Check if SIFM can deal with x,y,w,h when swizzling */
-               nvscreen->eng2d->copy(nvscreen->eng2d,
-                                     dst, ptx->box.x, ptx->box.y,
-                                     tx->surface, 0, 0,
-                                     ptx->box.width, ptx->box.height);
-
-               pipe_surface_reference(&dst, NULL);
-       }
-
-       pipe_surface_reference(&tx->surface, NULL);
-       pipe_resource_reference(&ptx->resource, NULL);
-       FREE(ptx);
 }
 
 void *
-nvfx_miptree_transfer_map(struct pipe_context *pipe, struct pipe_transfer *ptx)
+nvfx_transfer_map(struct pipe_context *pipe, struct pipe_transfer *ptx)
 {
-       struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx;
-       struct nv04_surface *ns = (struct nv04_surface *)tx->surface;
-       struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture;
-
-       uint8_t *map = nouveau_screen_bo_map(pipe->screen, mt->base.bo,
-                                            nouveau_screen_transfer_flags(ptx->usage));
-
-       if(!tx->direct)
-               return map + ns->base.offset;
-       else
-               return map + ns->base.offset
-               + util_format_get_2d_size(ns->base.format, ns->pitch, ptx->box.y)
-               + util_format_get_stride(ptx->resource->format, ptx->box.x);
+       struct nvfx_staging_transfer *tx = (struct nvfx_staging_transfer *)ptx;
+       if(!ptx->data)
+       {
+               struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->base.staging_resource;
+               uint8_t *map = nouveau_screen_bo_map(pipe->screen, mt->base.bo, nouveau_screen_transfer_flags(ptx->usage));
+               ptx->data = map + tx->offset;
+       }
+       ++tx->map_count;
+       return ptx->data;
 }
 
 void
-nvfx_miptree_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *ptx)
+nvfx_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *ptx)
 {
-       struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx;
-       struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture;
+       struct nvfx_staging_transfer *tx = (struct nvfx_staging_transfer *)ptx;
+       struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->base.staging_resource;
 
-       nouveau_screen_bo_unmap(pipe->screen, mt->base.bo);
+       if(!--tx->map_count)
+               nouveau_screen_bo_unmap(pipe->screen, mt->base.bo);
 }
index 3e3317b2c7b46607122a06f950f85baa36f10f12..20f20d5b0b8b0e0ae106670282853d9f71b5cc0b 100644 (file)
@@ -7,19 +7,17 @@
 
 
 struct pipe_transfer *
-nvfx_miptree_transfer_new(struct pipe_context *pcontext,
+nvfx_transfer_new(struct pipe_context *pcontext,
                          struct pipe_resource *pt,
                          struct pipe_subresource sr,
                          unsigned usage,
                          const struct pipe_box *box);
-void
-nvfx_miptree_transfer_del(struct pipe_context *pcontext,
-                         struct pipe_transfer *ptx);
+
 void *
-nvfx_miptree_transfer_map(struct pipe_context *pcontext,
+nvfx_transfer_map(struct pipe_context *pcontext,
                          struct pipe_transfer *ptx);
 void
-nvfx_miptree_transfer_unmap(struct pipe_context *pcontext,
+nvfx_transfer_unmap(struct pipe_context *pcontext,
                            struct pipe_transfer *ptx);