X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fnv30%2Fnv30_miptree.c;h=d4dcacb85069fe14d6d9b084d6510ea8736e830a;hb=f04dd3d0035f57854f0715c7e0f6a0fbe6b41f15;hp=ce95d9700f60702ad7ff6a1aa377d49e64bf2c55;hpb=9eb7fc6661a1d46c06cec8584b898e3e690af6fa;p=mesa.git diff --git a/src/gallium/drivers/nv30/nv30_miptree.c b/src/gallium/drivers/nv30/nv30_miptree.c index ce95d9700f6..d4dcacb8506 100644 --- a/src/gallium/drivers/nv30/nv30_miptree.c +++ b/src/gallium/drivers/nv30/nv30_miptree.c @@ -1,217 +1,489 @@ -#include "pipe/p_state.h" -#include "pipe/p_defines.h" -#include "pipe/p_inlines.h" +/* + * Copyright 2012 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Authors: Ben Skeggs + * + */ + #include "util/u_format.h" -#include "util/u_math.h" +#include "util/u_inlines.h" +#include "util/u_surface.h" +#include "nouveau/nv_m2mf.xml.h" +#include "nv30_screen.h" #include "nv30_context.h" +#include "nv30_resource.h" +#include "nv30_transfer.h" + +static INLINE unsigned +layer_offset(struct pipe_resource *pt, unsigned level, unsigned layer) +{ + struct nv30_miptree *mt = nv30_miptree(pt); + struct nv30_miptree_level *lvl = &mt->level[level]; + + if (pt->target == PIPE_TEXTURE_CUBE) + return (layer * mt->layer_size) + lvl->offset; + + return lvl->offset + (layer * lvl->zslice_size); +} + +static boolean +nv30_miptree_get_handle(struct pipe_screen *pscreen, + struct pipe_resource *pt, + struct winsys_handle *handle) +{ + struct nv30_miptree *mt = nv30_miptree(pt); + unsigned stride; + + if (!mt || !mt->base.bo) + return FALSE; + + stride = mt->level[0].pitch; + + return nouveau_screen_bo_get_handle(pscreen, mt->base.bo, stride, handle); +} static void -nv30_miptree_layout(struct nv30_miptree *nv30mt) +nv30_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt) +{ + struct nv30_miptree *mt = nv30_miptree(pt); + + nouveau_bo_ref(NULL, &mt->base.bo); + FREE(mt); +} + +struct nv30_transfer { + struct pipe_transfer base; + struct nv30_rect img; + struct nv30_rect tmp; + unsigned nblocksx; + unsigned nblocksy; +}; + +static INLINE struct nv30_transfer * +nv30_transfer(struct pipe_transfer *ptx) { - struct pipe_texture *pt = &nv30mt->base; - uint width = pt->width0; - uint offset = 0; - int nr_faces, l, f; - uint wide_pitch = pt->tex_usage & (PIPE_TEXTURE_USAGE_SAMPLER | - PIPE_TEXTURE_USAGE_DEPTH_STENCIL | - PIPE_TEXTURE_USAGE_RENDER_TARGET | - PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_PRIMARY); - - if (pt->target == PIPE_TEXTURE_CUBE) { - nr_faces = 6; - } else - if (pt->target == PIPE_TEXTURE_3D) { - nr_faces = pt->depth0; - } else { - nr_faces = 1; - } - - for (l = 0; l <= pt->last_level; l++) { - if (wide_pitch && (pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR)) - nv30mt->level[l].pitch = align(util_format_get_stride(pt->format, pt->width0), 64); - else - nv30mt->level[l].pitch = util_format_get_stride(pt->format, width); - - nv30mt->level[l].image_offset = - CALLOC(nr_faces, sizeof(unsigned)); - - width = u_minify(width, 1); - } - - for (f = 0; f < nr_faces; f++) { - for (l = 0; l < pt->last_level; l++) { - nv30mt->level[l].image_offset[f] = offset; - - if (!(pt->tex_usage & NOUVEAU_TEXTURE_USAGE_LINEAR) && - u_minify(pt->width0, l + 1) > 1 && u_minify(pt->height0, l + 1) > 1) - offset += align(nv30mt->level[l].pitch * u_minify(pt->height0, l), 64); - else - offset += nv30mt->level[l].pitch * u_minify(pt->height0, l); - } - - nv30mt->level[l].image_offset[f] = offset; - offset += nv30mt->level[l].pitch * u_minify(pt->height0, l); - } - - nv30mt->total_size = offset; + return (struct nv30_transfer *)ptx; } -static struct pipe_texture * -nv30_miptree_create(struct pipe_screen *pscreen, const struct pipe_texture *pt) +static INLINE void +define_rect(struct pipe_resource *pt, unsigned level, unsigned z, + unsigned x, unsigned y, unsigned w, unsigned h, + struct nv30_rect *rect) { - struct nv30_miptree *mt; - unsigned buf_usage = PIPE_BUFFER_USAGE_PIXEL | - NOUVEAU_BUFFER_USAGE_TEXTURE; - - mt = MALLOC(sizeof(struct nv30_miptree)); - if (!mt) - return NULL; - mt->base = *pt; - pipe_reference_init(&mt->base.reference, 1); - mt->base.screen = pscreen; - - /* Swizzled textures must be POT */ - if (pt->width0 & (pt->width0 - 1) || - pt->height0 & (pt->height0 - 1)) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - else - if (pt->tex_usage & (PIPE_TEXTURE_USAGE_PRIMARY | - PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_DEPTH_STENCIL)) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - else - if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - else { - switch (pt->format) { - /* TODO: Figure out which formats can be swizzled */ - case PIPE_FORMAT_A8R8G8B8_UNORM: - case PIPE_FORMAT_X8R8G8B8_UNORM: - case PIPE_FORMAT_R16_SNORM: - case PIPE_FORMAT_R5G6B5_UNORM: - case PIPE_FORMAT_A8L8_UNORM: - case PIPE_FORMAT_A8_UNORM: - case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_I8_UNORM: - { - if (debug_get_bool_option("NOUVEAU_NO_SWIZZLE", FALSE)) - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - break; - } - default: - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; - } - } - - if (pt->tex_usage & PIPE_TEXTURE_USAGE_DYNAMIC) - buf_usage |= PIPE_BUFFER_USAGE_CPU_READ_WRITE; - - nv30_miptree_layout(mt); - - mt->buffer = pscreen->buffer_create(pscreen, 256, buf_usage, - mt->total_size); - if (!mt->buffer) { - FREE(mt); - return NULL; - } - mt->bo = nouveau_bo(mt->buffer); - - return &mt->base; + struct nv30_miptree *mt = nv30_miptree(pt); + struct nv30_miptree_level *lvl = &mt->level[level]; + + rect->w = u_minify(pt->width0, level) << mt->ms_x; + rect->w = util_format_get_nblocksx(pt->format, rect->w); + rect->h = u_minify(pt->height0, level) << mt->ms_y; + rect->h = util_format_get_nblocksy(pt->format, rect->h); + rect->d = 1; + rect->z = 0; + if (mt->swizzled) { + if (pt->target == PIPE_TEXTURE_3D) { + rect->d = u_minify(pt->depth0, level); + rect->z = z; z = 0; + } + rect->pitch = 0; + } else { + rect->pitch = lvl->pitch; + } + + rect->bo = mt->base.bo; + rect->domain = NOUVEAU_BO_VRAM; + rect->offset = layer_offset(pt, level, z); + rect->cpp = util_format_get_blocksize(pt->format); + + rect->x0 = util_format_get_nblocksx(pt->format, x) << mt->ms_x; + rect->y0 = util_format_get_nblocksy(pt->format, y) << mt->ms_y; + rect->x1 = rect->x0 + (w << mt->ms_x); + rect->y1 = rect->y0 + (h << mt->ms_y); } -static struct pipe_texture * -nv30_miptree_blanket(struct pipe_screen *pscreen, const struct pipe_texture *pt, - const unsigned *stride, struct pipe_buffer *pb) +void +nv30_resource_copy_region(struct pipe_context *pipe, + struct pipe_resource *dstres, unsigned dst_level, + unsigned dstx, unsigned dsty, unsigned dstz, + struct pipe_resource *srcres, unsigned src_level, + const struct pipe_box *src_box) { - struct nv30_miptree *mt; + struct nv30_context *nv30 = nv30_context(pipe); + struct nv30_rect src, dst; + + if (dstres->target == PIPE_BUFFER && srcres->target == PIPE_BUFFER) { + util_resource_copy_region(pipe, dstres, dst_level, dstx, dsty, dstz, + srcres, src_level, src_box); + return; + } - /* Only supports 2D, non-mipmapped textures for the moment */ - if (pt->target != PIPE_TEXTURE_2D || pt->last_level != 0 || - pt->depth0 != 1) - return NULL; + define_rect(srcres, src_level, src_box->z, src_box->x, src_box->y, + src_box->width, src_box->height, &src); + define_rect(dstres, dst_level, dstz, dstx, dsty, + src_box->width, src_box->height, &dst); - mt = CALLOC_STRUCT(nv30_miptree); - if (!mt) - return NULL; + nv30_transfer_rect(nv30, NEAREST, &src, &dst); +} - mt->base = *pt; - pipe_reference_init(&mt->base.reference, 1); - mt->base.screen = pscreen; - mt->level[0].pitch = stride[0]; - mt->level[0].image_offset = CALLOC(1, sizeof(unsigned)); +void +nv30_resource_resolve(struct pipe_context *pipe, + const struct pipe_resolve_info *info) +{ +#if 0 + struct nv30_context *nv30 = nv30_context(pipe); + struct nv30_rect src, dst; - /* Assume whoever created this buffer expects it to be linear for now */ - mt->base.tex_usage |= NOUVEAU_TEXTURE_USAGE_LINEAR; + define_rect(info->src.res, 0, 0, info->src.x0, info->src.y0, + info->src.x1 - info->src.x0, info->src.y1 - info->src.y0, &src); + define_rect(info->dst.res, info->dst.level, 0, info->dst.x0, info->dst.y0, + info->dst.x1 - info->dst.x0, info->dst.y1 - info->dst.y0, &dst); - pipe_buffer_reference(&mt->buffer, pb); - mt->bo = nouveau_bo(mt->buffer); - return &mt->base; + nv30_transfer_rect(nv30, BILINEAR, &src, &dst); +#endif +} + +void +nv30_blit(struct pipe_context *pipe, + const struct pipe_blit_info *blit_info) +{ + struct nv30_context *nv30 = nv30_context(pipe); + struct pipe_blit_info info = *blit_info; + + if (info.src.resource->nr_samples > 1 && + info.dst.resource->nr_samples <= 1 && + !util_format_is_depth_or_stencil(info.src.resource->format) && + !util_format_is_pure_integer(info.src.resource->format)) { + debug_printf("nv30: color resolve unimplemented\n"); + return; + } + + if (util_try_blit_via_copy_region(pipe, &info)) { + return; /* done */ + } + + if (info.mask & PIPE_MASK_S) { + debug_printf("nv30: cannot blit stencil, skipping\n"); + info.mask &= ~PIPE_MASK_S; + } + + if (!util_blitter_is_blit_supported(nv30->blitter, &info)) { + debug_printf("nv30: blit unsupported %s -> %s\n", + util_format_short_name(info.src.resource->format), + util_format_short_name(info.dst.resource->format)); + return; + } + + /* XXX turn off occlusion queries */ + + util_blitter_save_vertex_buffer_slot(nv30->blitter, nv30->vtxbuf); + util_blitter_save_vertex_elements(nv30->blitter, nv30->vertex); + util_blitter_save_vertex_shader(nv30->blitter, nv30->vertprog.program); + util_blitter_save_rasterizer(nv30->blitter, nv30->rast); + util_blitter_save_viewport(nv30->blitter, &nv30->viewport); + util_blitter_save_scissor(nv30->blitter, &nv30->scissor); + util_blitter_save_fragment_shader(nv30->blitter, nv30->fragprog.program); + util_blitter_save_blend(nv30->blitter, nv30->blend); + util_blitter_save_depth_stencil_alpha(nv30->blitter, + nv30->zsa); + util_blitter_save_stencil_ref(nv30->blitter, &nv30->stencil_ref); + util_blitter_save_sample_mask(nv30->blitter, nv30->sample_mask); + util_blitter_save_framebuffer(nv30->blitter, &nv30->framebuffer); + util_blitter_save_fragment_sampler_states(nv30->blitter, + nv30->fragprog.num_samplers, + (void**)nv30->fragprog.samplers); + util_blitter_save_fragment_sampler_views(nv30->blitter, + nv30->fragprog.num_textures, nv30->fragprog.textures); + util_blitter_save_render_condition(nv30->blitter, nv30->render_cond_query, + nv30->render_cond_mode); + util_blitter_blit(nv30->blitter, &info); +} + +static void * +nv30_miptree_transfer_map(struct pipe_context *pipe, struct pipe_resource *pt, + unsigned level, unsigned usage, + const struct pipe_box *box, + struct pipe_transfer **ptransfer) +{ + struct nv30_context *nv30 = nv30_context(pipe); + struct nouveau_device *dev = nv30->screen->base.device; + struct nv30_transfer *tx; + unsigned access = 0; + int ret; + + tx = CALLOC_STRUCT(nv30_transfer); + if (!tx) + return NULL; + pipe_resource_reference(&tx->base.resource, pt); + tx->base.level = level; + tx->base.usage = usage; + tx->base.box = *box; + tx->base.stride = util_format_get_nblocksx(pt->format, box->width) * + util_format_get_blocksize(pt->format); + tx->base.layer_stride = util_format_get_nblocksy(pt->format, box->height) * + tx->base.stride; + + tx->nblocksx = util_format_get_nblocksx(pt->format, box->width); + tx->nblocksy = util_format_get_nblocksy(pt->format, box->height); + + define_rect(pt, level, box->z, box->x, box->y, + tx->nblocksx, tx->nblocksy, &tx->img); + + ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, + tx->base.layer_stride, NULL, &tx->tmp.bo); + if (ret) { + pipe_resource_reference(&tx->base.resource, NULL); + FREE(tx); + return NULL; + } + + tx->tmp.domain = NOUVEAU_BO_GART; + tx->tmp.offset = 0; + tx->tmp.pitch = tx->base.stride; + tx->tmp.cpp = tx->img.cpp; + tx->tmp.w = tx->nblocksx; + tx->tmp.h = tx->nblocksy; + tx->tmp.d = 1; + tx->tmp.x0 = 0; + tx->tmp.y0 = 0; + tx->tmp.x1 = tx->tmp.w; + tx->tmp.y1 = tx->tmp.h; + tx->tmp.z = 0; + + if (usage & PIPE_TRANSFER_READ) + nv30_transfer_rect(nv30, NEAREST, &tx->img, &tx->tmp); + + if (tx->tmp.bo->map) { + *ptransfer = &tx->base; + return tx->tmp.bo->map; + } + + if (usage & PIPE_TRANSFER_READ) + access |= NOUVEAU_BO_RD; + if (usage & PIPE_TRANSFER_WRITE) + access |= NOUVEAU_BO_WR; + + ret = nouveau_bo_map(tx->tmp.bo, access, nv30->base.client); + if (ret) { + pipe_resource_reference(&tx->base.resource, NULL); + FREE(tx); + return NULL; + } + + *ptransfer = &tx->base; + return tx->tmp.bo->map; } static void -nv30_miptree_destroy(struct pipe_texture *pt) +nv30_miptree_transfer_unmap(struct pipe_context *pipe, + struct pipe_transfer *ptx) { - struct nv30_miptree *mt = (struct nv30_miptree *)pt; - int l; + struct nv30_context *nv30 = nv30_context(pipe); + struct nv30_transfer *tx = nv30_transfer(ptx); - pipe_buffer_reference(&mt->buffer, NULL); - for (l = 0; l <= pt->last_level; l++) { - if (mt->level[l].image_offset) - FREE(mt->level[l].image_offset); - } + if (ptx->usage & PIPE_TRANSFER_WRITE) + nv30_transfer_rect(nv30, NEAREST, &tx->tmp, &tx->img); - FREE(mt); + nouveau_bo_ref(NULL, &tx->tmp.bo); + pipe_resource_reference(&ptx->resource, NULL); + FREE(tx); } -static struct pipe_surface * -nv30_miptree_surface_new(struct pipe_screen *pscreen, struct pipe_texture *pt, - unsigned face, unsigned level, unsigned zslice, - unsigned flags) +const struct u_resource_vtbl nv30_miptree_vtbl = { + nv30_miptree_get_handle, + nv30_miptree_destroy, + nv30_miptree_transfer_map, + u_default_transfer_flush_region, + nv30_miptree_transfer_unmap, + u_default_transfer_inline_write +}; + +struct pipe_resource * +nv30_miptree_create(struct pipe_screen *pscreen, + const struct pipe_resource *tmpl) { - struct nv30_miptree *nv30mt = (struct nv30_miptree *)pt; - struct nv04_surface *ns; - - ns = CALLOC_STRUCT(nv04_surface); - if (!ns) - return NULL; - pipe_texture_reference(&ns->base.texture, pt); - ns->base.format = pt->format; - ns->base.width = u_minify(pt->width0, level); - ns->base.height = u_minify(pt->height0, level); - ns->base.usage = flags; - pipe_reference_init(&ns->base.reference, 1); - ns->base.face = face; - ns->base.level = level; - ns->base.zslice = zslice; - ns->pitch = nv30mt->level[level].pitch; - - if (pt->target == PIPE_TEXTURE_CUBE) { - ns->base.offset = nv30mt->level[level].image_offset[face]; - } else - if (pt->target == PIPE_TEXTURE_3D) { - ns->base.offset = nv30mt->level[level].image_offset[zslice]; - } else { - ns->base.offset = nv30mt->level[level].image_offset[0]; - } - - return &ns->base; + struct nouveau_device *dev = nouveau_screen(pscreen)->device; + struct nv30_miptree *mt = CALLOC_STRUCT(nv30_miptree); + struct pipe_resource *pt = &mt->base.base; + unsigned blocksz, size; + unsigned w, h, d, l; + int ret; + + switch (tmpl->nr_samples) { + case 4: + mt->ms_mode = 0x00004000; + mt->ms_x = 1; + mt->ms_y = 1; + break; + case 2: + mt->ms_mode = 0x00003000; + mt->ms_x = 1; + mt->ms_y = 0; + break; + default: + mt->ms_mode = 0x00000000; + mt->ms_x = 0; + mt->ms_y = 0; + break; + } + + mt->base.vtbl = &nv30_miptree_vtbl; + *pt = *tmpl; + pipe_reference_init(&pt->reference, 1); + pt->screen = pscreen; + + w = pt->width0 << mt->ms_x; + h = pt->height0 << mt->ms_y; + d = (pt->target == PIPE_TEXTURE_3D) ? pt->depth0 : 1; + blocksz = util_format_get_blocksize(pt->format); + + if ((pt->target == PIPE_TEXTURE_RECT) || + !util_is_power_of_two(pt->width0) || + !util_is_power_of_two(pt->height0) || + !util_is_power_of_two(pt->depth0) || + util_format_is_compressed(pt->format) || + util_format_is_float(pt->format) || mt->ms_mode) { + mt->uniform_pitch = util_format_get_nblocksx(pt->format, w) * blocksz; + mt->uniform_pitch = align(mt->uniform_pitch, 64); + } + + if (!mt->uniform_pitch) + mt->swizzled = TRUE; + + size = 0; + for (l = 0; l <= pt->last_level; l++) { + struct nv30_miptree_level *lvl = &mt->level[l]; + unsigned nbx = util_format_get_nblocksx(pt->format, w); + unsigned nby = util_format_get_nblocksx(pt->format, h); + + lvl->offset = size; + lvl->pitch = mt->uniform_pitch; + if (!lvl->pitch) + lvl->pitch = nbx * blocksz; + + lvl->zslice_size = lvl->pitch * nby; + size += lvl->zslice_size * d; + + w = u_minify(w, 1); + h = u_minify(h, 1); + d = u_minify(d, 1); + } + + mt->layer_size = size; + if (pt->target == PIPE_TEXTURE_CUBE) { + if (!mt->uniform_pitch) + mt->layer_size = align(mt->layer_size, 128); + size = mt->layer_size * 6; + } + + ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 256, size, NULL, &mt->base.bo); + if (ret) { + FREE(mt); + return NULL; + } + + mt->base.domain = NOUVEAU_BO_VRAM; + return &mt->base.base; } -static void -nv30_miptree_surface_del(struct pipe_surface *ps) +struct pipe_resource * +nv30_miptree_from_handle(struct pipe_screen *pscreen, + const struct pipe_resource *tmpl, + struct winsys_handle *handle) { - pipe_texture_reference(&ps->texture, NULL); - FREE(ps); + struct nv30_miptree *mt; + unsigned stride; + + /* only supports 2D, non-mipmapped textures for the moment */ + if ((tmpl->target != PIPE_TEXTURE_2D && + tmpl->target != PIPE_TEXTURE_RECT) || + tmpl->last_level != 0 || + tmpl->depth0 != 1 || + tmpl->array_size > 1) + return NULL; + + mt = CALLOC_STRUCT(nv30_miptree); + if (!mt) + return NULL; + + mt->base.bo = nouveau_screen_bo_from_handle(pscreen, handle, &stride); + if (mt->base.bo == NULL) { + FREE(mt); + return NULL; + } + + mt->base.base = *tmpl; + mt->base.vtbl = &nv30_miptree_vtbl; + pipe_reference_init(&mt->base.base.reference, 1); + mt->base.base.screen = pscreen; + mt->uniform_pitch = stride; + mt->level[0].pitch = mt->uniform_pitch; + mt->level[0].offset = 0; + + /* no need to adjust bo reference count */ + return &mt->base.base; +} + +struct pipe_surface * +nv30_miptree_surface_new(struct pipe_context *pipe, + struct pipe_resource *pt, + const struct pipe_surface *tmpl) +{ + struct nv30_miptree *mt = nv30_miptree(pt); /* guaranteed */ + struct nv30_surface *ns; + struct pipe_surface *ps; + struct nv30_miptree_level *lvl = &mt->level[tmpl->u.tex.level]; + + ns = CALLOC_STRUCT(nv30_surface); + if (!ns) + return NULL; + ps = &ns->base; + + pipe_reference_init(&ps->reference, 1); + pipe_resource_reference(&ps->texture, pt); + ps->context = pipe; + ps->format = tmpl->format; + ps->u.tex.level = tmpl->u.tex.level; + ps->u.tex.first_layer = tmpl->u.tex.first_layer; + ps->u.tex.last_layer = tmpl->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 = layer_offset(pt, ps->u.tex.level, ps->u.tex.first_layer); + if (mt->swizzled) + ns->pitch = 4096; /* random, just something the hw won't reject.. */ + else + ns->pitch = lvl->pitch; + + /* 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 -nv30_screen_init_miptree_functions(struct pipe_screen *pscreen) +nv30_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps) { - pscreen->texture_create = nv30_miptree_create; - pscreen->texture_blanket = nv30_miptree_blanket; - pscreen->texture_destroy = nv30_miptree_destroy; - pscreen->get_tex_surface = nv30_miptree_surface_new; - pscreen->tex_surface_destroy = nv30_miptree_surface_del; + struct nv30_surface *ns = nv30_surface(ps); + + pipe_resource_reference(&ps->texture, NULL); + FREE(ns); }