X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fnv50%2Fnv50_miptree.c;h=2fbedb6779a0700a7442ced54f70a6173b46bf66;hb=a471497345bcd3aaaa52d3dc73f68367cb4af6a0;hp=b0e8fe2f0b724d63719e77715bf67a314349ba59;hpb=81335d0f1760fe172a106f79e81281c1f0d7dedf;p=mesa.git diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c index b0e8fe2f0b7..2fbedb6779a 100644 --- a/src/gallium/drivers/nv50/nv50_miptree.c +++ b/src/gallium/drivers/nv50/nv50_miptree.c @@ -27,50 +27,118 @@ #include "nv50_context.h" static struct pipe_texture * -nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) +nv50_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *tmp) { - struct pipe_winsys *ws = pscreen->winsys; + struct nouveau_device *dev = nouveau_screen(pscreen)->device; struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree); - unsigned usage, pitch; - - mt->base = *pt; - mt->base.refcount = 1; + struct pipe_texture *pt = &mt->base; + unsigned width = tmp->width[0], height = tmp->height[0]; + unsigned depth = tmp->depth[0]; + uint32_t tile_mode = 0, tile_flags = 0; + int ret, i, l; + + mt->base = *tmp; + pipe_reference_init(&mt->base.reference, 1); mt->base.screen = pscreen; - usage = PIPE_BUFFER_USAGE_PIXEL; switch (pt->format) { case PIPE_FORMAT_Z24S8_UNORM: case PIPE_FORMAT_Z16_UNORM: - usage |= NOUVEAU_BUFFER_USAGE_ZETA; + tile_flags = 0x2800; break; default: + tile_flags = 0x7000; break; } - pitch = ((pt->width[0] + 63) & ~63) * pt->block.size; + switch (pt->target) { + case PIPE_TEXTURE_3D: + mt->image_nr = pt->depth[0]; + break; + case PIPE_TEXTURE_CUBE: + mt->image_nr = 6; + break; + default: + mt->image_nr = 1; + break; + } + + for (l = 0; l <= pt->last_level; l++) { + struct nv50_miptree_level *lvl = &mt->level[l]; + + pt->width[l] = width; + pt->height[l] = height; + pt->depth[l] = depth; + pt->nblocksx[l] = pf_get_nblocksx(&pt->block, width); + pt->nblocksy[l] = pf_get_nblocksy(&pt->block, height); - mt->buffer = ws->buffer_create(ws, 256, usage, pitch * pt->height[0]); - if (!mt->buffer) { + lvl->image_offset = CALLOC(mt->image_nr, sizeof(int)); + lvl->pitch = align(pt->width[l] * pt->block.size, 64); + + width = MAX2(1, width >> 1); + height = MAX2(1, height >> 1); + depth = MAX2(1, depth >> 1); + } + + for (i = 0; i < mt->image_nr; i++) { + for (l = 0; l <= pt->last_level; l++) { + struct nv50_miptree_level *lvl = &mt->level[l]; + int size; + + size = align(pt->width[l], 8) * pt->block.size; + size = align(size, 64); + size *= align(pt->height[l], 8) * pt->block.size; + + lvl->image_offset[i] = mt->total_size; + + mt->total_size += size; + } + } + + ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 256, mt->total_size, + tile_mode, tile_flags, &mt->bo); + if (ret) { FREE(mt); return NULL; } - + return &mt->base; } -static void -nv50_miptree_release(struct pipe_screen *pscreen, struct pipe_texture **ppt) +static struct pipe_texture * +nv50_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt, + const unsigned *stride, struct pipe_buffer *pb) { - struct pipe_texture *pt = *ppt; + struct nouveau_bo *bo = nouveau_bo(pb); + struct nv50_miptree *mt; - *ppt = NULL; + /* Only supports 2D, non-mipmapped textures for the moment */ + if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 || + pt->depth[0] != 1) + return NULL; - if (--pt->refcount <= 0) { - struct nv50_miptree *mt = nv50_miptree(pt); + mt = CALLOC_STRUCT(nv50_miptree); + if (!mt) + return NULL; - pipe_buffer_reference(pscreen, &mt->buffer, NULL); - FREE(mt); - } + mt->base = *pt; + pipe_reference_init(&mt->base.reference, 1); + mt->base.screen = pscreen; + mt->image_nr = 1; + mt->level[0].pitch = *stride; + mt->level[0].image_offset = CALLOC(1, sizeof(unsigned)); + + nouveau_bo_ref(bo, &mt->bo); + return &mt->base; +} + +static void +nv50_miptree_destroy(struct pipe_texture *pt) +{ + struct nv50_miptree *mt = nv50_miptree(pt); + + nouveau_bo_ref(NULL, &mt->bo); + FREE(mt); } static struct pipe_surface * @@ -79,55 +147,51 @@ nv50_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, unsigned flags) { struct nv50_miptree *mt = nv50_miptree(pt); - struct nv50_surface *s; + struct nv50_miptree_level *lvl = &mt->level[level]; struct pipe_surface *ps; - - s = CALLOC_STRUCT(nv50_surface); - if (!s) + int img; + + if (pt->target == PIPE_TEXTURE_CUBE) + img = face; + else + if (pt->target == PIPE_TEXTURE_3D) + img = zslice; + else + img = 0; + + ps = CALLOC_STRUCT(pipe_surface); + if (!ps) return NULL; - ps = &s->base; - - ps->refcount = 1; - ps->winsys = pscreen->winsys; + pipe_texture_reference(&ps->texture, pt); ps->format = pt->format; ps->width = pt->width[level]; ps->height = pt->height[level]; - ps->block = pt->block; - ps->nblocksx = pt->nblocksx[level]; - ps->nblocksy = pt->nblocksy[level]; - ps->stride = ps->width * ps->block.size; - ps->offset = 0; ps->usage = flags; - ps->status = PIPE_SURFACE_STATUS_DEFINED; - - pipe_texture_reference(&ps->texture, pt); - pipe_buffer_reference(pscreen, &ps->buffer, mt->buffer); + pipe_reference_init(&ps->reference, 1); + ps->face = face; + ps->level = level; + ps->zslice = zslice; + ps->offset = lvl->image_offset[img]; return ps; } static void -nv50_miptree_surface_del(struct pipe_screen *pscreen, - struct pipe_surface **psurface) +nv50_miptree_surface_del(struct pipe_surface *ps) { - struct pipe_surface *ps = *psurface; struct nv50_surface *s = nv50_surface(ps); - *psurface = NULL; - - if (--ps->refcount <= 0) { - pipe_texture_reference(&ps->texture, NULL); - pipe_buffer_reference(pscreen, &ps->buffer, NULL); - FREE(s); - } + pipe_texture_reference(&ps->texture, NULL); + FREE(s); } void nv50_screen_init_miptree_functions(struct pipe_screen *pscreen) { pscreen->texture_create = nv50_miptree_create; - pscreen->texture_release = nv50_miptree_release; + pscreen->texture_blanket = nv50_miptree_blanket; + pscreen->texture_destroy = nv50_miptree_destroy; pscreen->get_tex_surface = nv50_miptree_surface_new; - pscreen->tex_surface_release = nv50_miptree_surface_del; + pscreen->tex_surface_destroy = nv50_miptree_surface_del; }