nvfx: new 2D: rewrite miptree code, adapt transfers
authorLuca Barbieri <luca@luca-barbieri.com>
Fri, 15 Jan 2010 09:11:11 +0000 (10:11 +0100)
committerLuca Barbieri <luca@luca-barbieri.com>
Sat, 21 Aug 2010 18:42:14 +0000 (20:42 +0200)
Changes:
- Disable swizzling on non-RGBA 2D textures, since the current 2D
  code is mostly broken in those cases. A later patch will fix this.
  Thanks to Andrew Randrianasulu who reported this.
- Fix compressed texture transfers and hack around the current 2D
  code inability to copy compressed textures by using direct access.
  Thanks to Andrew Randrianasulu who reported this.

This patch rewrites all the miptree layout and transfer code in the
nvfx driver.

The current code is broken in several ways:
1. 3D textures are laid out first by face, then by level, which is
incorrect
2. Cube maps should have 128-byte aligned faces
3. Swizzled textures have a strange alignment test that seems
unnecessary
4. We store the image_offsets for each face/slice but they can be
easily computed instead
5. "Swizzling" is not supported for compressed formats. They can be
"swizzled" but swizzling only means that there are no gaps (pitch is
level-dependant) and the layout is still linear
6. Swizzling is not supported for non-RGBA formats. All formats (except
possibly depth) can be swizzled according to my testing.

The miptree layout is rewritten based on my empirical testing, which I
posted in the "miptree findings" mail.
The image_offset array is removed, since it can be calculated with a
simple multiplication; the only array in the miptree structure is now
the one for mipmap level starts, which it seems cannot be easily
computed in constant time.

Also, we now directly store a nouveau_bo instead of a pipe_buffer in
the miptree structure, like nv50 does.

Support for render temporaries is removed, and will be readded in a
later patch.

Note that the current temporary code is broken, because it does not
copy the temporary back on render cache flushes.

src/gallium/drivers/nvfx/nv30_fragtex.c
src/gallium/drivers/nvfx/nv40_fragtex.c
src/gallium/drivers/nvfx/nvfx_miptree.c
src/gallium/drivers/nvfx/nvfx_resource.h
src/gallium/drivers/nvfx/nvfx_state_fb.c
src/gallium/drivers/nvfx/nvfx_transfer.c

index 0cd70ca10429b9d2335a0aeee0492038c1a0763f..85489eab287d2700dac11736ee785dc924ae870e 100644 (file)
@@ -92,9 +92,9 @@ void
 nv30_fragtex_set(struct nvfx_context *nvfx, int unit)
 {
        struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit];
-       struct nvfx_miptree *nv30mt = (struct nvfx_miptree *)nvfx->fragment_sampler_views[unit]->texture;
-       struct pipe_resource *pt = &nv30mt->base.base;
-       struct nouveau_bo *bo = nv30mt->base.bo;
+       struct nvfx_miptree *mt = (struct nvfx_miptree *)nvfx->fragment_sampler_views[unit]->texture;
+       struct pipe_resource *pt = &mt->base.base;
+       struct nouveau_bo *bo = mt->base.bo;
        struct nv30_texture_format *tf;
        struct nouveau_channel* chan = nvfx->screen->base.channel;
        uint32_t txf, txs;
index 0d3e90dcb05c303d7408b47996b8c68e3619bdb4..45c34c7ffd5a97e91fed7287fd7340157976d9fc 100644 (file)
@@ -111,9 +111,9 @@ nv40_fragtex_set(struct nvfx_context *nvfx, int unit)
 {
        struct nouveau_channel* chan = nvfx->screen->base.channel;
        struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit];
-       struct nvfx_miptree *nv40mt = (struct nvfx_miptree *)nvfx->fragment_sampler_views[unit]->texture;
-       struct nouveau_bo *bo = nv40mt->base.bo;
-       struct pipe_resource *pt = &nv40mt->base.base;
+       struct nvfx_miptree *mt = (struct nvfx_miptree *)nvfx->fragment_sampler_views[unit]->texture;
+       struct nouveau_bo *bo = mt->base.bo;
+       struct pipe_resource *pt = &mt->base.base;
        struct nv40_texture_format *tf;
 
        uint32_t txf, txs, txp;
@@ -149,10 +149,10 @@ nv40_fragtex_set(struct nvfx_context *nvfx, int unit)
                return;
        }
 
-       if (!(pt->flags & NVFX_RESOURCE_FLAG_LINEAR)) {
+       if (!mt->linear_pitch)
                txp = 0;
-       else {
-               txp  = nv40mt->level[0].pitch;
+       else {
+               txp  = mt->linear_pitch;
                txf |= NV40TCL_TEX_FORMAT_LINEAR;
        }
 
index 1fec1ffa42d212bd0c5d496af126a52ee4af6b0e..0b08f888849502b35e5d34e3e52fe15c9ac29fb7 100644 (file)
 #include "pipe/p_defines.h"
 #include "util/u_inlines.h"
 #include "util/u_format.h"
+#include "util/u_memory.h"
 #include "util/u_math.h"
-
+#include "state_tracker/drm_driver.h"
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_screen.h"
+#include "nv04_surface_2d.h"
 #include "nvfx_context.h"
 #include "nvfx_resource.h"
 #include "nvfx_transfer.h"
-#include "nv04_surface_2d.h"
-
-/* Currently using separate implementations for buffers and textures,
- * even though gallium has a unified abstraction of these objects.
- * Eventually these should be combined, and mechanisms like transfers
- * be adapted to work for both buffer and texture uploads.
- */
 
 static void
-nvfx_miptree_layout(struct nvfx_miptree *mt)
+nvfx_miptree_choose_format(struct nvfx_miptree *mt)
 {
        struct pipe_resource *pt = &mt->base.base;
-       uint width = pt->width0;
-       uint offset = 0;
-       int nr_faces, l, f;
-       uint wide_pitch = pt->bind & (PIPE_BIND_SAMPLER_VIEW |
-                                     PIPE_BIND_DEPTH_STENCIL |
-                                     PIPE_BIND_RENDER_TARGET |
-                                     PIPE_BIND_DISPLAY_TARGET |
-                                     PIPE_BIND_SCANOUT);
-
-       if (pt->target == PIPE_TEXTURE_CUBE) {
-               nr_faces = 6;
-       } else
-       if (pt->target == PIPE_TEXTURE_3D) {
-               nr_faces = pt->depth0;
-       } else {
-               nr_faces = 1;
+       unsigned uniform_pitch = 0;
+       static int no_swizzle = -1;
+       if(no_swizzle < 0)
+               no_swizzle = debug_get_bool_option("NOUVEAU_NO_SWIZZLE", FALSE);
+
+       /* Non-uniform pitch textures must be POT */
+       if (pt->width0 & (pt->width0 - 1) ||
+           pt->height0 & (pt->height0 - 1) ||
+           pt->depth0 & (pt->depth0 - 1)
+           )
+               uniform_pitch = 1;
+
+       /* All texture formats except compressed ones can be swizzled
+        * Unsure about depth, let's prevent swizzling for now
+        */
+       if (
+               (pt->bind & (PIPE_BIND_SCANOUT | PIPE_BIND_DISPLAY_TARGET))
+               || (pt->usage & PIPE_USAGE_DYNAMIC) || (pt->usage & PIPE_USAGE_STAGING)
+               || util_format_is_depth_or_stencil(pt->format)
+               || util_format_is_compressed(pt->format)
+               // disable swizzled textures on NV04-NV20 as our current drivers don't fully support that
+               // TODO: hardware should support them, fix the drivers and reenable
+               || nouveau_screen(pt->screen)->device->chipset < 0x30
+               || no_swizzle
+
+               // disable swizzling for non-RGBA 2D because our current 2D code can't handle anything
+               // else correctly, and even that is semi-broken
+               || pt->target != PIPE_TEXTURE_2D
+               || (pt->format != PIPE_FORMAT_B8G8R8A8_UNORM && pt->format != PIPE_FORMAT_B8G8R8X8_UNORM)
+       )
+               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
+
+       /* non compressed formats with uniform pitch must be linear, and vice versa */
+       if(!util_format_is_s3tc(pt->format)
+               && (uniform_pitch || mt->base.base.flags & NVFX_RESOURCE_FLAG_LINEAR))
+       {
+               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
+               uniform_pitch = 1;
        }
 
-       for (l = 0; l <= pt->last_level; l++) {
-               if (wide_pitch && (pt->flags & NVFX_RESOURCE_FLAG_LINEAR))
-                       mt->level[l].pitch = align(util_format_get_stride(pt->format, pt->width0), 64);
-               else
-                       mt->level[l].pitch = util_format_get_stride(pt->format, width);
+       if(uniform_pitch)
+       {
+               mt->linear_pitch = util_format_get_stride(pt->format, pt->width0);
+
+               // TODO: this is only a constraint for rendering and not sampling, apparently
+               // we may also want this unconditionally
+               if(pt->bind & (PIPE_BIND_SAMPLER_VIEW |
+                       PIPE_BIND_DEPTH_STENCIL |
+                       PIPE_BIND_RENDER_TARGET |
+                       PIPE_BIND_DISPLAY_TARGET |
+                       PIPE_BIND_SCANOUT))
+                       mt->linear_pitch = align(mt->linear_pitch, 64);
+       }
+       else
+               mt->linear_pitch = 0;
+}
 
-               mt->level[l].image_offset =
-                       CALLOC(nr_faces, sizeof(unsigned));
+static unsigned
+nvfx_miptree_layout(struct nvfx_miptree *mt)
+{
+       struct pipe_resource* pt = &mt->base.base;
+        uint offset = 0;
 
-               width  = u_minify(width, 1);
+       if(!nvfx_screen(pt->screen)->is_nv4x)
+       {
+               assert(pt->target == PIPE_TEXTURE_RECT
+                       || (util_is_pot(pt->width0) && util_is_pot(pt->height0)));
        }
 
-       for (f = 0; f < nr_faces; f++) {
-               for (l = 0; l < pt->last_level; l++) {
-                       mt->level[l].image_offset[f] = offset;
+       for (unsigned l = 0; l <= pt->last_level; l++)
+       {
+               unsigned size;
+               mt->level_offset[l] = offset;
+
+               if(mt->linear_pitch)
+                       size = mt->linear_pitch;
+               else
+                       size = util_format_get_stride(pt->format, u_minify(pt->width0, l));
+               size = util_format_get_2d_size(pt->format, size, u_minify(pt->height0, l));
 
-                       if (!(pt->flags & NVFX_RESOURCE_FLAG_LINEAR) &&
-                           u_minify(pt->width0, l + 1) > 1 && u_minify(pt->height0, l + 1) > 1)
-                               offset += align(mt->level[l].pitch * u_minify(pt->height0, l), 64);
-                       else
-                               offset += mt->level[l].pitch * u_minify(pt->height0, l);
-               }
+               if(pt->target == PIPE_TEXTURE_3D)
+                       size *= u_minify(pt->depth0, l);
 
-               mt->level[l].image_offset[f] = offset;
-               offset += mt->level[l].pitch * u_minify(pt->height0, l);
+               offset += size;
        }
 
-       mt->total_size = offset;
+       offset = align(offset, 128);
+       mt->face_size = offset;
+       if(mt->base.base.target == PIPE_TEXTURE_CUBE)
+               offset += 5 * mt->face_size;
+       return offset;
 }
 
 static boolean
@@ -79,7 +121,7 @@ nvfx_miptree_get_handle(struct pipe_screen *pscreen,
 
        return nouveau_screen_bo_get_handle(pscreen,
                                            mt->base.bo,
-                                           mt->level[0].pitch,
+                                           mt->linear_pitch,
                                            whandle);
 }
 
@@ -88,15 +130,7 @@ static void
 nvfx_miptree_destroy(struct pipe_screen *screen, struct pipe_resource *pt)
 {
        struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
-       int l;
-
        nouveau_screen_bo_release(screen, mt->base.bo);
-
-       for (l = 0; l <= pt->last_level; l++) {
-               if (mt->level[l].image_offset)
-                       FREE(mt->level[l].image_offset);
-       }
-
        FREE(mt);
 }
 
@@ -116,76 +150,50 @@ struct u_resource_vtbl nvfx_miptree_vtbl =
    u_default_transfer_inline_write    /* transfer_inline_write */
 };
 
+static struct nvfx_miptree*
+nvfx_miptree_create_skeleton(struct pipe_screen *pscreen, const struct pipe_resource *pt)
+{
+        struct nvfx_miptree *mt;
+
+        if(pt->width0 > 4096 || pt->height0 > 4096)
+                return NULL;
+
+        mt = CALLOC_STRUCT(nvfx_miptree);
+        if (!mt)
+                return NULL;
+
+        mt->base.base = *pt;
+        mt->base.vtbl = &nvfx_miptree_vtbl;
+        pipe_reference_init(&mt->base.base.reference, 1);
+        mt->base.base.screen = pscreen;
+
+        // set this to the actual capabilities, we use it to decide whether to use the 3D engine for copies
+        // TODO: is this the correct way to use Gallium?
+        mt->base.base.bind = pt->bind | PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_DEPTH_STENCIL;
+
+        // on our current driver (and the driver too), format support does not depend on geometry, so don't bother computing it
+        // TODO: may want to revisit this
+        if(!pscreen->is_format_supported(pscreen, pt->format, pt->target, 0, PIPE_BIND_RENDER_TARGET, 0))
+                mt->base.base.bind &=~ PIPE_BIND_RENDER_TARGET;
+        if(!pscreen->is_format_supported(pscreen, pt->format, pt->target, 0, PIPE_BIND_SAMPLER_VIEW, 0))
+                mt->base.base.bind &=~ PIPE_BIND_SAMPLER_VIEW;
+        if(!pscreen->is_format_supported(pscreen, pt->format, pt->target, 0, PIPE_BIND_DEPTH_STENCIL, 0))
+                mt->base.base.bind &=~ PIPE_BIND_DEPTH_STENCIL;
+
+        return mt;
+}
 
 
 struct pipe_resource *
 nvfx_miptree_create(struct pipe_screen *pscreen, const struct pipe_resource *pt)
 {
-       struct nvfx_miptree *mt;
-       static int no_swizzle = -1;
-       if(no_swizzle < 0)
-               no_swizzle = debug_get_bool_option("NOUVEAU_NO_SWIZZLE", FALSE);
-
-       mt = CALLOC_STRUCT(nvfx_miptree);
-       if (!mt)
-               return NULL;
-
-       mt->base.base = *pt;
-       mt->base.vtbl = &nvfx_miptree_vtbl;
-       pipe_reference_init(&mt->base.base.reference, 1);
-       mt->base.base.screen = pscreen;
-
-       /* Swizzled textures must be POT */
-       if (pt->width0 & (pt->width0 - 1) ||
-           pt->height0 & (pt->height0 - 1))
-               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
-       else
-       if (pt->bind & (PIPE_BIND_SCANOUT |
-                       PIPE_BIND_DISPLAY_TARGET |
-                       PIPE_BIND_DEPTH_STENCIL))
-               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
-       else
-       if (pt->usage == PIPE_USAGE_DYNAMIC)
-               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
-       else {
-               switch (pt->format) {
-               case PIPE_FORMAT_B5G6R5_UNORM:
-               case PIPE_FORMAT_L8A8_UNORM:
-               case PIPE_FORMAT_A8_UNORM:
-               case PIPE_FORMAT_L8_UNORM:
-               case PIPE_FORMAT_I8_UNORM:
-                       /* TODO: we can actually swizzle these formats on nv40, we
-                               are just preserving the pre-unification behavior.
-                               The whole 2D code is going to be rewritten anyway. */
-                       if(nvfx_screen(pscreen)->is_nv4x) {
-                               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
-                               break;
-                       }
-               /* TODO: Figure out which formats can be swizzled */
-               case PIPE_FORMAT_B8G8R8A8_UNORM:
-               case PIPE_FORMAT_B8G8R8X8_UNORM:
-               case PIPE_FORMAT_R16_SNORM:
-               {
-                       if (no_swizzle)
-                               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
-                       break;
-               }
-               default:
-                       mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
-               }
-       }
+       struct nvfx_miptree* mt = nvfx_miptree_create_skeleton(pscreen, pt);
+       nvfx_miptree_choose_format(mt);
 
-       /* apparently we can't render to swizzled surfaces smaller than 64 bytes, so make them linear.
-        * If the user did not ask for a render target, they can still render to it, but it will cost them an extra copy.
-        * This also happens for small mipmaps of large textures. */
-       if (pt->bind & PIPE_BIND_RENDER_TARGET &&
-           util_format_get_stride(pt->format, pt->width0) < 64)
-               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
+        unsigned size = nvfx_miptree_layout(mt);
 
-       nvfx_miptree_layout(mt);
+       mt->base.bo = nouveau_screen_bo_new(pscreen, 256, pt->usage, pt->bind, size);
 
-       mt->base.bo = nouveau_screen_bo_new(pscreen, 256,
-            pt->usage, pt->bind, mt->total_size);
        if (!mt->base.bo) {
                FREE(mt);
                return NULL;
@@ -193,54 +201,28 @@ nvfx_miptree_create(struct pipe_screen *pscreen, const struct pipe_resource *pt)
        return &mt->base.base;
 }
 
-
-
-
+// TODO: redo this, just calling miptree_layout
 struct pipe_resource *
-nvfx_miptree_from_handle(struct pipe_screen *pscreen,
-                        const struct pipe_resource *template,
-                        struct winsys_handle *whandle)
+nvfx_miptree_from_handle(struct pipe_screen *pscreen, const struct pipe_resource *template, struct winsys_handle *whandle)
 {
-       struct nvfx_miptree *mt;
-       unsigned stride;
-
-       /* Only supports 2D, non-mipmapped textures for the moment */
-       if ((template->target != PIPE_TEXTURE_2D &&
-             template->target != PIPE_TEXTURE_RECT) ||
-           template->last_level != 0 ||
-           template->depth0 != 1)
-               return NULL;
-
-       mt = CALLOC_STRUCT(nvfx_miptree);
-       if (!mt)
-               return NULL;
-
-       mt->base.bo = nouveau_screen_bo_from_handle(pscreen, whandle, &stride);
-       if (mt->base.bo == NULL) {
-               FREE(mt);
-               return NULL;
-       }
-
-       mt->base.base = *template;
-       mt->base.vtbl = &nvfx_miptree_vtbl;
-       pipe_reference_init(&mt->base.base.reference, 1);
-       mt->base.base.screen = pscreen;
-       mt->level[0].pitch = stride;
-       mt->level[0].image_offset = CALLOC(1, sizeof(unsigned));
-
-       /* Assume whoever created this buffer expects it to be linear for now */
-       mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
-
-       /* XXX: Need to adjust bo refcount??
-        */
-       /* nouveau_bo_ref(bo, &mt->base.bo); */
-       return &mt->base.base;
+        struct nvfx_miptree* mt = nvfx_miptree_create_skeleton(pscreen, template);
+        if(whandle->stride) {
+               mt->linear_pitch = whandle->stride;
+               mt->base.base.flags |= NVFX_RESOURCE_FLAG_LINEAR;
+        } else
+               nvfx_miptree_choose_format(mt);
+
+        nvfx_miptree_layout(mt);
+
+        unsigned stride;
+        mt->base.bo = nouveau_screen_bo_from_handle(pscreen, whandle, &stride);
+        if (mt->base.bo == NULL) {
+                FREE(mt);
+                return NULL;
+        }
+        return &mt->base.base;
 }
 
-
-
-
-
 /* Surface helpers, not strictly required to implement the resource vtbl:
  */
 struct pipe_surface *
@@ -248,7 +230,6 @@ nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt,
                         unsigned face, unsigned level, unsigned zslice,
                         unsigned flags)
 {
-       struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
        struct nv04_surface *ns;
 
        ns = CALLOC_STRUCT(nv04_surface);
@@ -263,33 +244,8 @@ nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt,
        ns->base.face = face;
        ns->base.level = level;
        ns->base.zslice = zslice;
-       ns->pitch = mt->level[level].pitch;
-
-       if (pt->target == PIPE_TEXTURE_CUBE) {
-               ns->base.offset = mt->level[level].image_offset[face];
-       } else
-       if (pt->target == PIPE_TEXTURE_3D) {
-               ns->base.offset = mt->level[level].image_offset[zslice];
-       } else {
-               ns->base.offset = mt->level[level].image_offset[0];
-       }
-
-       /* create a linear temporary that we can render into if
-        * necessary.
-        *
-        * Note that ns->pitch is always a multiple of 64 for linear
-        * surfaces and swizzled surfaces are POT, so ns->pitch & 63
-        * is equivalent to (ns->pitch < 64 && swizzled)
-        */
-
-       if ((ns->pitch & 63) && 
-           (ns->base.usage & PIPE_BIND_RENDER_TARGET))
-       {
-               struct nv04_surface_2d* eng2d  =
-                       ((struct nvfx_screen*)pscreen)->eng2d;
-
-               ns = nv04_surface_wrap_for_render(pscreen, eng2d, ns);
-       }
+       ns->pitch = nvfx_subresource_pitch(pt, level);
+       ns->base.offset = nvfx_subresource_offset(pt, face, level, zslice);
 
        return &ns->base;
 }
index bdbf3dd3d891276cfac0d6e5566be5918090de6a..0e24ec2f1f9898edb9e417552b9b40e58bf9f22d 100644 (file)
@@ -39,15 +39,11 @@ nvfx_resource_on_gpu(struct pipe_resource* pr)
 #define NVFX_MAX_TEXTURE_LEVELS  16
 
 struct nvfx_miptree {
-       struct nvfx_resource base;
-       uint total_size;
+        struct nvfx_resource base;
 
-       struct {
-               uint pitch;
-               uint *image_offset;
-       } level[NVFX_MAX_TEXTURE_LEVELS];
-
-       unsigned image_nr;
+        unsigned linear_pitch; /* for linear textures, 0 for swizzled and compressed textures with level-dependent minimal pitch */
+        unsigned face_size; /* 128-byte aligned face/total size */
+        unsigned level_offset[NVFX_MAX_TEXTURE_LEVELS];
 };
 
 static INLINE 
@@ -103,5 +99,41 @@ nvfx_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_resource *pt,
                         unsigned face, unsigned level, unsigned zslice,
                         unsigned flags);
 
+/* only for miptrees, don't use for buffers */
+
+/* NOTE: for swizzled 3D textures, this just returns the offset of the mipmap level */
+static inline unsigned
+nvfx_subresource_offset(struct pipe_resource* pt, unsigned face, unsigned level, unsigned zslice)
+{
+       if(pt->target == PIPE_BUFFER)
+               return 0;
+       else
+       {
+               struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
+
+               unsigned offset = mt->level_offset[level];
+               if (pt->target == PIPE_TEXTURE_CUBE)
+                       offset += mt->face_size * face;
+               else if (pt->target == PIPE_TEXTURE_3D && mt->linear_pitch)
+                       offset += zslice * util_format_get_2d_size(pt->format, (mt->linear_pitch ? mt->linear_pitch : util_format_get_stride(pt->format, u_minify(pt->width0, level))),  u_minify(pt->height0, level));
+               return offset;
+       }
+}
+
+static inline unsigned
+nvfx_subresource_pitch(struct pipe_resource* pt, unsigned level)
+{
+       if(pt->target == PIPE_BUFFER)
+               return ((struct nvfx_resource*)pt)->bo->size;
+       else
+       {
+               struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
+
+               if(mt->linear_pitch)
+                       return mt->linear_pitch;
+               else
+                       return util_format_get_stride(pt->format, u_minify(pt->width0, level));
+       }
+}
 
 #endif
index 360e569f77c8bdcf328f44a947dbc57fd514256a..657e315f0676387ba7f73535517f93246d1c35c4 100644 (file)
@@ -29,7 +29,7 @@ nvfx_state_framebuffer_validate(struct nvfx_context *nvfx)
                        colour_format = fb->cbufs[i]->format;
 
                rt_enable |= (NV34TCL_RT_ENABLE_COLOR0 << i);
-               nvfx->hw_rt[i].bo = nvfx_surface_buffer(fb->cbufs[i]);
+               nvfx->hw_rt[i].bo = ((struct nvfx_miptree*)fb->cbufs[i]->texture)->base.bo;
                nvfx->hw_rt[i].offset = fb->cbufs[i]->offset;
                nvfx->hw_rt[i].pitch = ((struct nv04_surface *)fb->cbufs[i])->pitch;
        }
@@ -42,7 +42,7 @@ nvfx_state_framebuffer_validate(struct nvfx_context *nvfx)
 
        if (fb->zsbuf) {
                zeta_format = fb->zsbuf->format;
-               nvfx->hw_zeta.bo = nvfx_surface_buffer(fb->zsbuf);
+               nvfx->hw_zeta.bo = ((struct nvfx_miptree*)fb->zsbuf->texture)->base.bo;
                nvfx->hw_zeta.offset = fb->zsbuf->offset;
                nvfx->hw_zeta.pitch = ((struct nv04_surface *)fb->zsbuf)->pitch;
        }
@@ -67,7 +67,7 @@ nvfx_state_framebuffer_validate(struct nvfx_context *nvfx)
                depth_only = 1;
 
                /* Render to depth buffer only */
-               if (!(fb->zsbuf->texture->usage & NVFX_RESOURCE_FLAG_LINEAR)) {
+               if (!(fb->zsbuf->texture->flags & NVFX_RESOURCE_FLAG_LINEAR)) {
                        assert(!(fb->width & (fb->width - 1)) && !(fb->height & (fb->height - 1)));
 
                        rt_format = NV34TCL_RT_FORMAT_TYPE_SWIZZLED |
index 9ff0a93d3077d5b9805457f4ad4eba19002c8bf0..957e586f81d90de9c7f7ff2e48179d0473962188 100644 (file)
@@ -59,14 +59,9 @@ nvfx_miptree_transfer_new(struct pipe_context *pipe,
                          const struct pipe_box *box)
 {
        struct pipe_screen *pscreen = pipe->screen;
-       struct nvfx_miptree *mt = (struct nvfx_miptree *)pt;
        struct nvfx_transfer *tx;
        struct pipe_resource tx_tex_template, *tx_tex;
-       static int no_transfer = -1;
        unsigned bind = nvfx_transfer_bind_flags(usage);
-       if(no_transfer < 0)
-               no_transfer = debug_get_bool_option("NOUVEAU_NO_TRANSFER", FALSE);
-
 
        tx = CALLOC_STRUCT(nvfx_transfer);
        if (!tx)
@@ -78,13 +73,13 @@ nvfx_miptree_transfer_new(struct pipe_context *pipe,
 
        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;
-       tx->base.stride = mt->level[sr.level].pitch;
 
        /* Direct access to texture */
-       if ((pt->usage == PIPE_USAGE_DYNAMIC ||
-            no_transfer) &&
+       if ((util_format_is_s3tc(pt->format) || pt->usage & PIPE_USAGE_DYNAMIC) &&
            pt->flags & NVFX_RESOURCE_FLAG_LINEAR)
        {
                tx->direct = true;
@@ -109,7 +104,8 @@ nvfx_miptree_transfer_new(struct pipe_context *pipe,
                return NULL;
        }
 
-       tx->base.stride = ((struct nvfx_miptree*)tx_tex)->level[0].pitch;
+       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,
@@ -181,27 +177,26 @@ nvfx_miptree_transfer_del(struct pipe_context *pipe,
 void *
 nvfx_miptree_transfer_map(struct pipe_context *pipe, struct pipe_transfer *ptx)
 {
-       struct pipe_screen *pscreen = pipe->screen;
        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(pscreen, mt->base.bo,
+
+       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 + 
-                       ptx->box.y * ns->pitch + 
-                       ptx->box.x * util_format_get_blocksize(ptx->resource->format));
+               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);
 }
 
 void
 nvfx_miptree_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *ptx)
 {
-       struct pipe_screen *pscreen = pipe->screen;
        struct nvfx_transfer *tx = (struct nvfx_transfer *)ptx;
        struct nvfx_miptree *mt = (struct nvfx_miptree *)tx->surface->texture;
 
-       nouveau_screen_bo_unmap(pscreen, mt->base.bo);
+       nouveau_screen_bo_unmap(pipe->screen, mt->base.bo);
 }