summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nvc0/nvc0_miptree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/nvc0/nvc0_miptree.c')
-rw-r--r--src/gallium/drivers/nvc0/nvc0_miptree.c368
1 files changed, 185 insertions, 183 deletions
diff --git a/src/gallium/drivers/nvc0/nvc0_miptree.c b/src/gallium/drivers/nvc0/nvc0_miptree.c
index bced3245524..5da73df2d9b 100644
--- a/src/gallium/drivers/nvc0/nvc0_miptree.c
+++ b/src/gallium/drivers/nvc0/nvc0_miptree.c
@@ -29,8 +29,8 @@
#include "nvc0_resource.h"
#include "nvc0_transfer.h"
-static INLINE uint32_t
-get_tile_dims(unsigned nx, unsigned ny, unsigned nz)
+uint32_t
+nvc0_tex_choose_tile_dims(unsigned nx, unsigned ny, unsigned nz)
{
uint32_t tile_mode = 0x000;
@@ -57,66 +57,182 @@ get_tile_dims(unsigned nx, unsigned ny, unsigned nz)
return tile_mode | 0x100;
}
-uint32_t
-nvc0_miptree_zslice_offset(struct nvc0_miptree *mt, unsigned l, unsigned z)
+static uint32_t
+nvc0_mt_choose_storage_type(struct nv50_miptree *mt, boolean compressed)
{
- unsigned nblocksy; /* height of texture level aligned to tile height */
+ const unsigned ms = util_logbase2(mt->base.base.nr_samples);
- unsigned stride_2d; /* to next slice within a 3D tile */
- unsigned stride_3d; /* to slice in the next (in z direction !) 3D tile */
+ uint32_t tile_flags;
- unsigned tile_d_shift = NVC0_TILE_DIM_SHIFT(mt->level[l].tile_mode, 2);
- unsigned tile_d = 1 << tile_d_shift;
+ compressed = FALSE; /* not yet supported */
- nblocksy = util_format_get_nblocksy(mt->base.base.format,
- u_minify(mt->base.base.height0, l));
+ if (mt->base.base.bind & PIPE_BIND_CURSOR)
+ return NOUVEAU_BO_TILE_SCANOUT;
- nblocksy = align(nblocksy, NVC0_TILE_HEIGHT(mt->level[l].tile_mode));
+ switch (mt->base.base.format) {
+ case PIPE_FORMAT_Z16_UNORM:
+ if (compressed)
+ tile_flags = 0x0200 + (ms << 8);
+ else
+ tile_flags = 0x0100;
+ break;
+ case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
+ if (compressed)
+ tile_flags = 0x5100 + (ms << 8);
+ else
+ tile_flags = 0x4600;
+ break;
+ case PIPE_FORMAT_Z24X8_UNORM:
+ case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
+ if (compressed)
+ tile_flags = 0x1700 + (ms << 8);
+ else
+ tile_flags = 0x1100;
+ break;
+ case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED:
+ if (compressed)
+ tile_flags = 0xce00 + (ms << 8);
+ else
+ tile_flags = 0xc300;
+ break;
+ default:
+ switch (util_format_get_blocksizebits(mt->base.base.format)) {
+ case 128:
+ if (compressed)
+ tile_flags = 0xf400 + (ms << 9);
+ else
+ tile_flags = 0xfe00;
+ break;
+ case 64:
+ if (compressed) {
+ switch (ms) {
+ case 0: tile_flags = 0xe600; break;
+ case 1: tile_flags = 0xeb00; break;
+ case 2: tile_flags = 0xed00; break;
+ case 3: tile_flags = 0xf200; break;
+ default:
+ return 0;
+ }
+ } else {
+ tile_flags = 0xfe00;
+ }
+ break;
+ case 32:
+ if (compressed) {
+ switch (ms) {
+ case 0: tile_flags = 0xdb00; break;
+ case 1: tile_flags = 0xdd00; break;
+ case 2: tile_flags = 0xdf00; break;
+ case 3: tile_flags = 0xe400; break;
+ default:
+ return 0;
+ }
+ } else {
+ tile_flags = 0xfe00;
+ }
+ break;
+ case 16:
+ case 8:
+ tile_flags = 0xfe00;
+ break;
+ default:
+ return 0;
+ }
+ break;
+ }
- stride_2d = NVC0_TILE_SIZE_2D(mt->level[l].tile_mode);
+ if (mt->base.base.bind & PIPE_BIND_SCANOUT)
+ tile_flags |= NOUVEAU_BO_TILE_SCANOUT;
- stride_3d = (nblocksy * mt->level[l].pitch) << tile_d_shift;
+ return tile_flags;
+}
- return (z & (tile_d - 1)) * stride_2d + (z >> tile_d_shift) * stride_3d;
+static INLINE boolean
+nvc0_miptree_init_ms_mode(struct nv50_miptree *mt)
+{
+ switch (mt->base.base.nr_samples) {
+ case 8:
+ mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS8;
+ mt->ms_x = 2;
+ mt->ms_y = 1;
+ break;
+ case 4:
+ mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS4;
+ mt->ms_x = 1;
+ mt->ms_y = 1;
+ break;
+ case 2:
+ mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS2;
+ mt->ms_x = 1;
+ break;
+ case 1:
+ case 0:
+ mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS1;
+ break;
+ default:
+ NOUVEAU_ERR("invalid nr_samples: %u\n", mt->base.base.nr_samples);
+ return FALSE;
+ }
+ return TRUE;
}
+boolean
+nv50_miptree_init_layout_linear(struct nv50_miptree *);
+
static void
-nvc0_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt)
+nvc0_miptree_init_layout_tiled(struct nv50_miptree *mt)
{
- struct nvc0_miptree *mt = nvc0_miptree(pt);
+ struct pipe_resource *pt = &mt->base.base;
+ unsigned w, h, d, l;
+ const unsigned blocksize = util_format_get_blocksize(pt->format);
- nouveau_screen_bo_release(pscreen, mt->base.bo);
+ mt->layout_3d = pt->target == PIPE_TEXTURE_3D;
- FREE(mt);
-}
+ w = pt->width0 << mt->ms_x;
+ h = pt->height0 << mt->ms_y;
-static boolean
-nvc0_miptree_get_handle(struct pipe_screen *pscreen,
- struct pipe_resource *pt,
- struct winsys_handle *whandle)
-{
- struct nvc0_miptree *mt = nvc0_miptree(pt);
- unsigned stride;
+ /* For 3D textures, a mipmap is spanned by all the layers, for array
+ * textures and cube maps, each layer contains its own mipmaps.
+ */
+ d = mt->layout_3d ? pt->depth0 : 1;
- if (!mt || !mt->base.bo)
- return FALSE;
+ for (l = 0; l <= pt->last_level; ++l) {
+ struct nv50_miptree_level *lvl = &mt->level[l];
+ unsigned tsx, tsy, tsz;
+ unsigned nbx = util_format_get_nblocksx(pt->format, w);
+ unsigned nby = util_format_get_nblocksy(pt->format, h);
+
+ lvl->offset = mt->total_size;
+
+ lvl->tile_mode = nvc0_tex_choose_tile_dims(nbx, nby, d);
+
+ tsx = NVC0_TILE_SIZE_X(lvl->tile_mode); /* x is tile row pitch in bytes */
+ tsy = NVC0_TILE_SIZE_Y(lvl->tile_mode);
+ tsz = NVC0_TILE_SIZE_Z(lvl->tile_mode);
+
+ lvl->pitch = align(nbx * blocksize, tsx);
- stride = util_format_get_stride(mt->base.base.format,
- mt->base.base.width0);
+ mt->total_size += lvl->pitch * align(nby, tsy) * align(d, tsz);
- return nouveau_screen_bo_get_handle(pscreen,
- mt->base.bo,
- stride,
- whandle);
+ w = u_minify(w, 1);
+ h = u_minify(h, 1);
+ d = u_minify(d, 1);
+ }
+
+ if (pt->array_size > 1) {
+ mt->layer_stride = align(mt->total_size,
+ NVC0_TILE_SIZE(mt->level[0].tile_mode));
+ mt->total_size = mt->layer_stride * pt->array_size;
+ }
}
const struct u_resource_vtbl nvc0_miptree_vtbl =
{
- nvc0_miptree_get_handle, /* get_handle */
- nvc0_miptree_destroy, /* resource_destroy */
+ nv50_miptree_get_handle, /* get_handle */
+ nv50_miptree_destroy, /* resource_destroy */
nvc0_miptree_transfer_new, /* get_transfer */
nvc0_miptree_transfer_del, /* transfer_destroy */
- nvc0_miptree_transfer_map, /* transfer_map */
+ nvc0_miptree_transfer_map, /* transfer_map */
u_default_transfer_flush_region, /* transfer_flush_region */
nvc0_miptree_transfer_unmap, /* transfer_unmap */
u_default_transfer_inline_write /* transfer_inline_write */
@@ -127,10 +243,9 @@ nvc0_miptree_create(struct pipe_screen *pscreen,
const struct pipe_resource *templ)
{
struct nouveau_device *dev = nouveau_screen(pscreen)->device;
- struct nvc0_miptree *mt = CALLOC_STRUCT(nvc0_miptree);
+ struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree);
struct pipe_resource *pt = &mt->base.base;
int ret;
- unsigned w, h, d, l, alloc_size;
uint32_t tile_flags;
if (!mt)
@@ -141,84 +256,23 @@ nvc0_miptree_create(struct pipe_screen *pscreen,
pipe_reference_init(&pt->reference, 1);
pt->screen = pscreen;
- mt->layout_3d = pt->target == PIPE_TEXTURE_3D;
-
- w = pt->width0;
- h = pt->height0;
- d = mt->layout_3d ? pt->depth0 : 1;
+ tile_flags = nvc0_mt_choose_storage_type(mt, TRUE);
- switch (pt->format) {
- case PIPE_FORMAT_Z16_UNORM:
- tile_flags = 0x0700; /* COMPRESSED */
- tile_flags = 0x0100; /* NORMAL */
- break;
- case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
- tile_flags = 0x5300; /* MSAA 4, COMPRESSED */
- tile_flags = 0x4600; /* NORMAL */
- break;
- case PIPE_FORMAT_Z24X8_UNORM:
- case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
- tile_flags = 0x1100; /* NORMAL */
- if (w * h >= 128 * 128 && 0)
- tile_flags = 0x1700; /* COMPRESSED, requires magic */
- break;
- case PIPE_FORMAT_R32G32B32A32_FLOAT:
- tile_flags = 0xf500; /* COMPRESSED */
- tile_flags = 0xf700; /* MSAA 2 */
- tile_flags = 0xf900; /* MSAA 4 */
- tile_flags = 0xfe00; /* NORMAL */
- break;
- case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED:
- tile_flags = 0xce00; /* COMPRESSED */
- tile_flags = 0xcf00; /* MSAA 2, COMPRESSED */
- tile_flags = 0xd000; /* MSAA 4, COMPRESSED */
- tile_flags = 0xc300; /* NORMAL */
- break;
- case PIPE_FORMAT_R16G16B16A16_UNORM:
- tile_flags = 0xe900; /* COMPRESSED */
- tile_flags = 0xfe00; /* NORMAL */
- break;
- default:
- tile_flags = 0xe000; /* MSAA 4, COMPRESSED 32 BIT */
- tile_flags = 0xfe00; /* NORMAL 32 BIT */
- if (w * h >= 128 * 128 && 0)
- tile_flags = 0xdb00; /* COMPRESSED 32 BIT, requires magic */
- break;
- }
-
- /* For 3D textures, a mipmap is spanned by all the layers, for array
- * textures and cube maps, each layer contains its own mipmaps.
- */
- for (l = 0; l <= pt->last_level; ++l) {
- struct nvc0_miptree_level *lvl = &mt->level[l];
- unsigned nbx = util_format_get_nblocksx(pt->format, w);
- unsigned nby = util_format_get_nblocksy(pt->format, h);
- unsigned blocksize = util_format_get_blocksize(pt->format);
-
- lvl->offset = mt->total_size;
- lvl->tile_mode = get_tile_dims(nbx, nby, d);
- lvl->pitch = align(nbx * blocksize, NVC0_TILE_PITCH(lvl->tile_mode));
-
- mt->total_size += lvl->pitch *
- align(nby, NVC0_TILE_HEIGHT(lvl->tile_mode)) *
- align(d, NVC0_TILE_DEPTH(lvl->tile_mode));
-
- w = u_minify(w, 1);
- h = u_minify(h, 1);
- d = u_minify(d, 1);
+ if (!nvc0_miptree_init_ms_mode(mt)) {
+ FREE(mt);
+ return NULL;
}
- if (pt->array_size > 1) {
- mt->layer_stride = align(mt->total_size,
- NVC0_TILE_SIZE(mt->level[0].tile_mode));
- mt->total_size = mt->layer_stride * pt->array_size;
+ if (tile_flags & NOUVEAU_BO_TILE_LAYOUT_MASK) {
+ nvc0_miptree_init_layout_tiled(mt);
+ } else
+ if (!nv50_miptree_init_layout_linear(mt)) {
+ FREE(mt);
+ return NULL;
}
- alloc_size = mt->total_size;
- if (tile_flags == 0x1700)
- alloc_size *= 3; /* HiZ, XXX: correct size */
-
- ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 256, alloc_size,
+ ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 4096,
+ mt->total_size,
mt->level[0].tile_mode, tile_flags,
&mt->base.bo);
if (ret) {
@@ -230,44 +284,26 @@ nvc0_miptree_create(struct pipe_screen *pscreen,
return pt;
}
-struct pipe_resource *
-nvc0_miptree_from_handle(struct pipe_screen *pscreen,
- const struct pipe_resource *templ,
- struct winsys_handle *whandle)
+/* Offset of zslice @z from start of level @l. */
+INLINE unsigned
+nvc0_mt_zslice_offset(const struct nv50_miptree *mt, unsigned l, unsigned z)
{
- struct nvc0_miptree *mt;
- unsigned stride;
-
- /* only supports 2D, non-mipmapped textures for the moment */
- if ((templ->target != PIPE_TEXTURE_2D &&
- templ->target != PIPE_TEXTURE_RECT) ||
- templ->last_level != 0 ||
- templ->depth0 != 1 ||
- templ->array_size > 1)
- return NULL;
+ const struct pipe_resource *pt = &mt->base.base;
- mt = CALLOC_STRUCT(nvc0_miptree);
- if (!mt)
- return NULL;
+ unsigned tds = NVC0_TILE_SHIFT_Z(mt->level[l].tile_mode);
+ unsigned ths = NVC0_TILE_SHIFT_Y(mt->level[l].tile_mode);
- mt->base.bo = nouveau_screen_bo_from_handle(pscreen, whandle, &stride);
- if (mt->base.bo == NULL) {
- FREE(mt);
- return NULL;
- }
+ unsigned nby = util_format_get_nblocksy(pt->format,
+ u_minify(pt->height0, l));
- mt->base.base = *templ;
- mt->base.vtbl = &nvc0_miptree_vtbl;
- pipe_reference_init(&mt->base.base.reference, 1);
- mt->base.base.screen = pscreen;
- mt->level[0].pitch = stride;
- mt->level[0].offset = 0;
- mt->level[0].tile_mode = mt->base.bo->tile_mode;
-
- /* no need to adjust bo reference count */
- return &mt->base.base;
-}
+ /* to next 2D tile slice within a 3D tile */
+ unsigned stride_2d = NVC0_TILE_SIZE_2D(mt->level[l].tile_mode);
+
+ /* to slice in the next (in z direction) 3D tile */
+ unsigned stride_3d = (align(nby, (1 << ths)) * mt->level[l].pitch) << tds;
+ return (z & (1 << (tds - 1))) * stride_2d + (z >> tds) * stride_3d;
+}
/* Surface functions.
*/
@@ -277,43 +313,9 @@ nvc0_miptree_surface_new(struct pipe_context *pipe,
struct pipe_resource *pt,
const struct pipe_surface *templ)
{
- struct nvc0_miptree *mt = nvc0_miptree(pt); /* guaranteed */
- struct nvc0_surface *ns;
- struct pipe_surface *ps;
- struct nvc0_miptree_level *lvl = &mt->level[templ->u.tex.level];
-
- ns = CALLOC_STRUCT(nvc0_surface);
+ struct nv50_surface *ns = nv50_surface_from_miptree(nv50_miptree(pt), templ);
if (!ns)
return NULL;
- ps = &ns->base;
-
- pipe_reference_init(&ps->reference, 1);
- pipe_resource_reference(&ps->texture, pt);
- ps->context = pipe;
- ps->format = templ->format;
- ps->usage = templ->usage;
- ps->u.tex.level = templ->u.tex.level;
- ps->u.tex.first_layer = templ->u.tex.first_layer;
- ps->u.tex.last_layer = templ->u.tex.last_layer;
-
- ns->width = u_minify(pt->width0, ps->u.tex.level);
- ns->height = u_minify(pt->height0, ps->u.tex.level);
- ns->depth = ps->u.tex.last_layer - ps->u.tex.first_layer + 1;
- ns->offset = lvl->offset;
-
- /* comment says there are going to be removed, but they're used by the st */
- ps->width = ns->width;
- ps->height = ns->height;
-
- return ps;
-}
-
-void
-nvc0_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps)
-{
- struct nvc0_surface *s = nvc0_surface(ps);
-
- pipe_resource_reference(&ps->texture, NULL);
-
- FREE(s);
+ ns->base.context = pipe;
+ return &ns->base;
}