summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers
diff options
context:
space:
mode:
authorLuca Barbieri <[email protected]>2010-01-15 10:11:11 +0100
committerLuca Barbieri <[email protected]>2010-08-21 20:42:14 +0200
commited2930e7e2c064458da33089cff902574008bf30 (patch)
tree34f3e56774f1bf861fca7c3d589f09801061c78b /src/gallium/drivers
parentac97e8dba654b9b3c5a9459953ce27056bcbb021 (diff)
nvfx: new 2D: rewrite miptree code, adapt transfers
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.
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r--src/gallium/drivers/nvfx/nv30_fragtex.c6
-rw-r--r--src/gallium/drivers/nvfx/nv40_fragtex.c12
-rw-r--r--src/gallium/drivers/nvfx/nvfx_miptree.c332
-rw-r--r--src/gallium/drivers/nvfx/nvfx_resource.h48
-rw-r--r--src/gallium/drivers/nvfx/nvfx_state_fb.c6
-rw-r--r--src/gallium/drivers/nvfx/nvfx_transfer.c27
6 files changed, 207 insertions, 224 deletions
diff --git a/src/gallium/drivers/nvfx/nv30_fragtex.c b/src/gallium/drivers/nvfx/nv30_fragtex.c
index 0cd70ca1042..85489eab287 100644
--- a/src/gallium/drivers/nvfx/nv30_fragtex.c
+++ b/src/gallium/drivers/nvfx/nv30_fragtex.c
@@ -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;
diff --git a/src/gallium/drivers/nvfx/nv40_fragtex.c b/src/gallium/drivers/nvfx/nv40_fragtex.c
index 0d3e90dcb05..45c34c7ffd5 100644
--- a/src/gallium/drivers/nvfx/nv40_fragtex.c
+++ b/src/gallium/drivers/nvfx/nv40_fragtex.c
@@ -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;
}
diff --git a/src/gallium/drivers/nvfx/nvfx_miptree.c b/src/gallium/drivers/nvfx/nvfx_miptree.c
index 1fec1ffa42d..0b08f888849 100644
--- a/src/gallium/drivers/nvfx/nvfx_miptree.c
+++ b/src/gallium/drivers/nvfx/nvfx_miptree.c
@@ -2,69 +2,111 @@
#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;
}
diff --git a/src/gallium/drivers/nvfx/nvfx_resource.h b/src/gallium/drivers/nvfx/nvfx_resource.h
index bdbf3dd3d89..0e24ec2f1f9 100644
--- a/src/gallium/drivers/nvfx/nvfx_resource.h
+++ b/src/gallium/drivers/nvfx/nvfx_resource.h
@@ -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
diff --git a/src/gallium/drivers/nvfx/nvfx_state_fb.c b/src/gallium/drivers/nvfx/nvfx_state_fb.c
index 360e569f77c..657e315f067 100644
--- a/src/gallium/drivers/nvfx/nvfx_state_fb.c
+++ b/src/gallium/drivers/nvfx/nvfx_state_fb.c
@@ -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 |
diff --git a/src/gallium/drivers/nvfx/nvfx_transfer.c b/src/gallium/drivers/nvfx/nvfx_transfer.c
index 9ff0a93d307..957e586f81d 100644
--- a/src/gallium/drivers/nvfx/nvfx_transfer.c
+++ b/src/gallium/drivers/nvfx/nvfx_transfer.c
@@ -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);
}