static void i915_texture_layout_3d(struct i915_texture *tex) { struct pipe_resource *pt = &tex->b.b; unsigned level; unsigned width = pt->width0; unsigned height = pt->height0; unsigned depth = pt->depth0; unsigned nblocksy = util_format_get_nblocksy(pt->format, pt->height0); unsigned stack_nblocksy = 0; /* Calculate the size of a single slice. */ tex->stride = align(util_format_get_stride(pt->format, pt->width0), 4); /* XXX: hardware expects/requires 9 levels at minimum. */ for (level = 0; level <= MAX2(8, pt->last_level); level++) { i915_texture_set_level_info(tex, level, depth); stack_nblocksy += MAX2(2, nblocksy); width = u_minify(width, 1); height = u_minify(height, 1); nblocksy = util_format_get_nblocksy(pt->format, height); } /* Fixup depth image_offsets: */ for (level = 0; level <= pt->last_level; level++) { unsigned i; for (i = 0; i < depth; i++) i915_texture_set_image_offset(tex, level, i, 0, i * stack_nblocksy); depth = u_minify(depth, 1); } /* Multiply slice size by texture depth for total size. It's * remarkable how wasteful of memory the i915 texture layouts * are. They are largely fixed in the i945. */ tex->total_nblocksy = stack_nblocksy * pt->depth0; }
static uint32_t setup_slices(struct fd_resource *rsc, uint32_t alignment) { struct pipe_resource *prsc = &rsc->base.b; uint32_t level, size = 0; uint32_t width = prsc->width0; uint32_t height = prsc->height0; uint32_t depth = prsc->depth0; /* in layer_first layout, the level (slice) contains just one * layer (since in fact the layer contains the slices) */ uint32_t layers_in_level = rsc->layer_first ? 1 : prsc->array_size; for (level = 0; level <= prsc->last_level; level++) { struct fd_resource_slice *slice = fd_resource_slice(rsc, level); slice->pitch = width = align(width, 32); slice->offset = size; /* 1d array and 2d array textures must all have the same layer size * for each miplevel on a3xx. 3d textures can have different layer * sizes for high levels, but the hw auto-sizer is buggy (or at least * different than what this code does), so as soon as the layer size * range gets into range, we stop reducing it. */ if (prsc->target == PIPE_TEXTURE_3D && ( level == 1 || (level > 1 && rsc->slices[level - 1].size0 > 0xf000))) slice->size0 = align(slice->pitch * height * rsc->cpp, alignment); else if (level == 0 || rsc->layer_first || alignment == 1) slice->size0 = align(slice->pitch * height * rsc->cpp, alignment); else slice->size0 = rsc->slices[level - 1].size0; size += slice->size0 * depth * layers_in_level; width = u_minify(width, 1); height = u_minify(height, 1); depth = u_minify(depth, 1); } return size; }
/** * When doing GL render to texture, we have to be sure that finalize_texture() * didn't yank out the pipe_resource that we earlier created a surface for. * Check for that here and create a new surface if needed. */ static void update_renderbuffer_surface(struct st_context *st, struct st_renderbuffer *strb) { struct pipe_context *pipe = st->pipe; struct pipe_resource *resource = strb->rtt ? strb->rtt->pt : strb->texture; int rtt_width = strb->Base.Width; int rtt_height = strb->Base.Height; enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format : util_format_linear(resource->format); if (!strb->surface || strb->surface->format != format || strb->surface->texture != resource || strb->surface->width != rtt_width || strb->surface->height != rtt_height) { GLuint level; /* find matching mipmap level size */ for (level = 0; level <= resource->last_level; level++) { if (u_minify(resource->width0, level) == rtt_width && u_minify(resource->height0, level) == rtt_height) { struct pipe_surface surf_tmpl; memset(&surf_tmpl, 0, sizeof(surf_tmpl)); surf_tmpl.format = format; surf_tmpl.u.tex.level = level; surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice; surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice; pipe_surface_reference(&strb->surface, NULL); strb->surface = pipe->create_surface(pipe, resource, &surf_tmpl); #if 0 printf("-- alloc new surface %d x %d into tex %p\n", strb->surface->width, strb->surface->height, texture); #endif break; } } } }
static boolean is_simple_msaa_resolve(const struct pipe_blit_info *info) { unsigned dst_width = u_minify(info->dst.resource->width0, info->dst.level); unsigned dst_height = u_minify(info->dst.resource->height0, info->dst.level); return info->dst.resource->format == info->src.resource->format && info->dst.resource->format == info->dst.format && info->src.resource->format == info->src.format && !info->scissor_enable && info->mask == PIPE_MASK_RGBA && dst_width == info->src.resource->width0 && dst_height == info->src.resource->height0 && info->dst.box.x == 0 && info->dst.box.y == 0 && info->dst.box.width == dst_width && info->dst.box.height == dst_height && info->src.box.x == 0 && info->src.box.y == 0 && info->src.box.width == dst_width && info->src.box.height == dst_height; }
static unsigned r300_texture_get_nblocksy(struct r300_resource *tex, unsigned level, boolean *out_aligned_for_cbzb) { unsigned height, tile_height; height = u_minify(tex->tex.height0, level); /* Mipmapped and 3D textures must have their height aligned to POT. */ if ((tex->b.b.b.target != PIPE_TEXTURE_1D && tex->b.b.b.target != PIPE_TEXTURE_2D && tex->b.b.b.target != PIPE_TEXTURE_RECT) || tex->b.b.b.last_level != 0) { height = util_next_power_of_two(height); } if (util_format_is_plain(tex->b.b.b.format)) { tile_height = r300_get_pixel_alignment(tex->b.b.b.format, tex->b.b.b.nr_samples, tex->tex.microtile, tex->tex.macrotile[level], DIM_HEIGHT, 0); height = align(height, tile_height); /* See if the CBZB clear can be used on the buffer, * taking the texture size into account. */ if (out_aligned_for_cbzb) { if (tex->tex.macrotile[level]) { /* When clearing, the layer (width*height) is horizontally split * into two, and the upper and lower halves are cleared by the CB * and ZB units, respectively. Therefore, the number of macrotiles * in the Y direction must be even. */ /* Align the height so that there is an even number of macrotiles. * Do so for 3 or more macrotiles in the Y direction. */ if (level == 0 && tex->b.b.b.last_level == 0 && (tex->b.b.b.target == PIPE_TEXTURE_1D || tex->b.b.b.target == PIPE_TEXTURE_2D || tex->b.b.b.target == PIPE_TEXTURE_RECT) && height >= tile_height * 3) { height = align(height, tile_height * 2); } *out_aligned_for_cbzb = height % (tile_height * 2) == 0; } else { *out_aligned_for_cbzb = FALSE; } } } return util_format_get_nblocksy(tex->b.b.b.format, height); }
/* Return true if macrotiling should be enabled on the miplevel. */ static boolean r300_texture_macro_switch(struct r300_texture_desc *desc, unsigned level, boolean rv350_mode, enum r300_dim dim) { unsigned tile, texdim; tile = r300_get_pixel_alignment(desc->b.b.format, desc->b.b.nr_samples, desc->microtile, R300_BUFFER_TILED, dim); if (dim == DIM_WIDTH) { texdim = u_minify(desc->b.b.width0, level); } else { texdim = u_minify(desc->b.b.height0, level); } /* See TX_FILTER1_n.MACRO_SWITCH. */ if (rv350_mode) { return texdim >= tile; } else { return texdim > tile; } }
/* * Store SWR HotTiles back to renderTarget surface. */ void swr_store_render_target(struct pipe_context *pipe, uint32_t attachment, enum SWR_TILE_STATE post_tile_state) { struct swr_context *ctx = swr_context(pipe); struct swr_draw_context *pDC = &ctx->swrDC; struct SWR_SURFACE_STATE *renderTarget = &pDC->renderTargets[attachment]; /* Only proceed if there's a valid surface to store to */ if (renderTarget->xpBaseAddress) { swr_update_draw_context(ctx); SWR_RECT full_rect = {0, 0, (int32_t)u_minify(renderTarget->width, renderTarget->lod), (int32_t)u_minify(renderTarget->height, renderTarget->lod)}; ctx->api.pfnSwrStoreTiles(ctx->swrContext, 1 << attachment, post_tile_state, full_rect); } }
/* Return true if macrotiling should be enabled on the miplevel. */ static boolean r300_texture_macro_switch(struct r300_resource *tex, unsigned level, boolean rv350_mode, enum r300_dim dim) { unsigned tile, texdim; tile = r300_get_pixel_alignment(tex->b.b.b.format, tex->b.b.b.nr_samples, tex->tex.microtile, RADEON_LAYOUT_TILED, dim, 0); if (dim == DIM_WIDTH) { texdim = u_minify(tex->tex.width0, level); } else { texdim = u_minify(tex->tex.height0, level); } /* See TX_FILTER1_n.MACRO_SWITCH. */ if (rv350_mode) { return texdim >= tile; } else { return texdim > tile; } }
static boolean is_simple_resolve(const struct pipe_resolve_info *info) { unsigned dst_width = u_minify(info->dst.res->width0, info->dst.level); unsigned dst_height = u_minify(info->dst.res->height0, info->dst.level); struct r600_texture *dst = (struct r600_texture*)info->dst.res; unsigned dst_tile_mode = dst->surface.level[info->dst.level].mode; return info->dst.res->format == info->src.res->format && dst_width == info->src.res->width0 && dst_height == info->src.res->height0 && info->dst.x0 == 0 && info->dst.y0 == 0 && info->dst.x1 == dst_width && info->dst.y1 == dst_height && info->src.x0 == 0 && info->src.y0 == 0 && info->src.x1 == dst_width && info->src.y1 == dst_height && /* Dst must be tiled. If it's not, we have to use a temporary * resource which is tiled. */ dst_tile_mode >= RADEON_SURF_MODE_1D; }
static void get_texcoords(struct pipe_sampler_view *src, unsigned src_width0, unsigned src_height0, unsigned x1, unsigned y1, unsigned x2, unsigned y2, float out[4]) { struct pipe_resource *tex = src->texture; unsigned level = src->u.tex.first_level; boolean normalized = tex->target != PIPE_TEXTURE_RECT; if (normalized) { out[0] = x1 / (float)u_minify(src_width0, level); out[1] = y1 / (float)u_minify(src_height0, level); out[2] = x2 / (float)u_minify(src_width0, level); out[3] = y2 / (float)u_minify(src_height0, level); } else { out[0] = x1; out[1] = y1; out[2] = x2; out[3] = y2; } }
static struct pipe_surface * swr_create_surface(struct pipe_context *pipe, struct pipe_resource *pt, const struct pipe_surface *surf_tmpl) { struct pipe_surface *ps; ps = CALLOC_STRUCT(pipe_surface); if (ps) { pipe_reference_init(&ps->reference, 1); pipe_resource_reference(&ps->texture, pt); ps->context = pipe; ps->format = surf_tmpl->format; if (pt->target != PIPE_BUFFER) { assert(surf_tmpl->u.tex.level <= pt->last_level); ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level); ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level); ps->u.tex.level = surf_tmpl->u.tex.level; ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer; ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer; if (ps->u.tex.first_layer != ps->u.tex.last_layer) { debug_printf("creating surface with multiple layers, rendering " "to first layer only\n"); } } else { /* setting width as number of elements should get us correct * renderbuffer width */ ps->width = surf_tmpl->u.buf.last_element - surf_tmpl->u.buf.first_element + 1; ps->height = pt->height0; ps->u.buf.first_element = surf_tmpl->u.buf.first_element; ps->u.buf.last_element = surf_tmpl->u.buf.last_element; assert(ps->u.buf.first_element <= ps->u.buf.last_element); assert(ps->u.buf.last_element < ps->width); } } return ps; }
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->usage = tmpl->usage; 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; }
static boolean vrend_resource_layout(struct virgl_texture *res, uint32_t *total_size) { struct pipe_resource *pt = &res->base.u.b; unsigned level; unsigned width = pt->width0; unsigned height = pt->height0; unsigned depth = pt->depth0; unsigned buffer_size = 0; for (level = 0; level <= pt->last_level; level++) { unsigned slices; if (pt->target == PIPE_TEXTURE_CUBE) slices = 6; else if (pt->target == PIPE_TEXTURE_3D) slices = depth; else slices = pt->array_size; res->stride[level] = util_format_get_stride(pt->format, width); res->level_offset[level] = buffer_size; buffer_size += (util_format_get_nblocksy(pt->format, height) * slices * res->stride[level]); width = u_minify(width, 1); height = u_minify(height, 1); depth = u_minify(depth, 1); } if (pt->nr_samples <= 1) *total_size = buffer_size; else /* don't create guest backing store for MSAA */ *total_size = 0; return TRUE; }
static struct pipe_sampler_view * vc4_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc, const struct pipe_sampler_view *cso) { struct pipe_sampler_view *so = malloc(sizeof(*so)); if (!so) return NULL; *so = *cso; pipe_reference(NULL, &prsc->reference); /* There is no hardware level clamping, and the start address of a * texture may be misaligned, so in that case we have to copy to a * temporary. */ if (so->u.tex.first_level) { struct vc4_resource *shadow_parent = vc4_resource(prsc); struct pipe_resource tmpl = shadow_parent->base.b; struct vc4_resource *clone; tmpl.width0 = u_minify(tmpl.width0, so->u.tex.first_level); tmpl.height0 = u_minify(tmpl.height0, so->u.tex.first_level); tmpl.last_level = so->u.tex.last_level - so->u.tex.first_level; prsc = vc4_resource_create(pctx->screen, &tmpl); clone = vc4_resource(prsc); clone->shadow_parent = &shadow_parent->base.b; /* Flag it as needing update of the contents from the parent. */ clone->writes = shadow_parent->writes - 1; } so->texture = prsc; so->reference.count = 1; so->context = pctx; return so; }
void svga_validate_sampler_view(struct svga_context *svga, struct svga_sampler_view *v) { struct svga_texture *tex = svga_texture(v->texture); unsigned numFaces; unsigned age = 0; int i; unsigned k; assert(svga); assert(!svga_have_vgpu10(svga)); if (v->handle == tex->handle) return; age = tex->age; if (tex->b.b.target == PIPE_TEXTURE_CUBE) numFaces = 6; else numFaces = 1; for (i = v->min_lod; i <= v->max_lod; i++) { for (k = 0; k < numFaces; k++) { assert(i < ARRAY_SIZE(tex->view_age)); if (v->age < tex->view_age[i]) svga_texture_copy_handle(svga, tex->handle, 0, 0, 0, i, k, v->handle, 0, 0, 0, i - v->min_lod, k, u_minify(tex->b.b.width0, i), u_minify(tex->b.b.height0, i), u_minify(tex->b.b.depth0, i)); } } v->age = age; }
static unsigned u_max_layer(struct pipe_resource *r, unsigned level) { switch (r->target) { case PIPE_TEXTURE_CUBE: return 6 - 1; case PIPE_TEXTURE_3D: return u_minify(r->depth0, level) - 1; case PIPE_TEXTURE_1D_ARRAY: case PIPE_TEXTURE_2D_ARRAY: return r->array_size - 1; default: return 0; } }
static boolean r300_is_simple_msaa_resolve(const struct pipe_blit_info *info) { unsigned dst_width = u_minify(info->dst.resource->width0, info->dst.level); unsigned dst_height = u_minify(info->dst.resource->height0, info->dst.level); return info->dst.resource->format == info->src.resource->format && info->dst.resource->format == info->dst.format && info->src.resource->format == info->src.format && !info->scissor_enable && info->mask == PIPE_MASK_RGBA && dst_width == info->src.resource->width0 && dst_height == info->src.resource->height0 && info->dst.box.x == 0 && info->dst.box.y == 0 && info->dst.box.width == dst_width && info->dst.box.height == dst_height && info->src.box.x == 0 && info->src.box.y == 0 && info->src.box.width == dst_width && info->src.box.height == dst_height && (r300_resource(info->dst.resource)->tex.microtile != RADEON_LAYOUT_LINEAR || r300_resource(info->dst.resource)->tex.macrotile[info->dst.level] != RADEON_LAYOUT_LINEAR); }
/** * Conventional allocation path for non-display textures: * Use a simple, maximally packed layout. */ static boolean softpipe_resource_layout(struct pipe_screen *screen, struct softpipe_resource *spr) { struct pipe_resource *pt = &spr->base; unsigned level; unsigned width = pt->width0; unsigned height = pt->height0; unsigned depth = pt->depth0; unsigned buffer_size = 0; for (level = 0; level <= pt->last_level; level++) { unsigned slices; if (pt->target == PIPE_TEXTURE_CUBE) slices = 6; else if (pt->target == PIPE_TEXTURE_3D) slices = depth; else slices = pt->array_size; spr->stride[level] = util_format_get_stride(pt->format, width); spr->level_offset[level] = buffer_size; buffer_size += (util_format_get_nblocksy(pt->format, height) * slices * spr->stride[level]); width = u_minify(width, 1); height = u_minify(height, 1); depth = u_minify(depth, 1); } spr->data = align_malloc(buffer_size, 16); return spr->data != NULL; }
static void r300_setup_miptree(struct r300_screen* screen, struct r300_texture* tex) { struct pipe_texture* base = &tex->tex; unsigned stride, size, layer_size, nblocksy, i; boolean rv350_mode = screen->caps->family >= CHIP_FAMILY_RV350; SCREEN_DBG(screen, DBG_TEX, "r300: Making miptree for texture, format %s\n", util_format_name(base->format)); for (i = 0; i <= base->last_level; i++) { /* Let's see if this miplevel can be macrotiled. */ tex->mip_macrotile[i] = (tex->macrotile == R300_BUFFER_TILED && r300_texture_macro_switch(tex, i, rv350_mode)) ? R300_BUFFER_TILED : R300_BUFFER_LINEAR; stride = r300_texture_get_stride(screen, tex, i); nblocksy = r300_texture_get_nblocksy(tex, i); layer_size = stride * nblocksy; if (base->target == PIPE_TEXTURE_CUBE) size = layer_size * 6; else size = layer_size * u_minify(base->depth0, i); tex->offset[i] = tex->size; tex->size = tex->offset[i] + size; tex->layer_size[i] = layer_size; tex->pitch[i] = stride / util_format_get_blocksize(base->format); SCREEN_DBG(screen, DBG_TEX, "r300: Texture miptree: Level %d " "(%dx%dx%d px, pitch %d bytes) %d bytes total, macrotiled %s\n", i, u_minify(base->width0, i), u_minify(base->height0, i), u_minify(base->depth0, i), stride, tex->size, tex->mip_macrotile[i] ? "TRUE" : "FALSE"); } }
/** * Map a resource for read/write. */ void * llvmpipe_resource_map(struct pipe_resource *resource, unsigned level, unsigned layer, enum lp_texture_usage tex_usage) { struct llvmpipe_resource *lpr = llvmpipe_resource(resource); uint8_t *map; assert(level < LP_MAX_TEXTURE_LEVELS); assert(layer < (u_minify(resource->depth0, level) + resource->array_size - 1)); assert(tex_usage == LP_TEX_USAGE_READ || tex_usage == LP_TEX_USAGE_READ_WRITE || tex_usage == LP_TEX_USAGE_WRITE_ALL); if (lpr->dt) { /* display target */ struct llvmpipe_screen *screen = llvmpipe_screen(resource->screen); struct sw_winsys *winsys = screen->winsys; unsigned dt_usage; if (tex_usage == LP_TEX_USAGE_READ) { dt_usage = PIPE_TRANSFER_READ; } else { dt_usage = PIPE_TRANSFER_READ_WRITE; } assert(level == 0); assert(layer == 0); /* FIXME: keep map count? */ map = winsys->displaytarget_map(winsys, lpr->dt, dt_usage); /* install this linear image in texture data structure */ lpr->linear_img.data = map; return map; } else if (llvmpipe_resource_is_texture(resource)) { map = llvmpipe_get_texture_image(lpr, layer, level, tex_usage); return map; } else { return lpr->data; } }
static void translate_image(struct fd6_image *img, struct pipe_image_view *pimg) { enum pipe_format format = pimg->format; struct pipe_resource *prsc = pimg->resource; struct fd_resource *rsc = fd_resource(prsc); unsigned lvl; if (!pimg->resource) { memset(img, 0, sizeof(*img)); return; } img->pfmt = format; img->fmt = fd6_pipe2tex(format); img->fetchsize = fd6_pipe2fetchsize(format); img->type = fd6_tex_type(prsc->target); img->srgb = util_format_is_srgb(format); img->cpp = rsc->cpp; img->bo = rsc->bo; if (prsc->target == PIPE_BUFFER) { lvl = 0; img->offset = pimg->u.buf.offset; img->pitch = pimg->u.buf.size; img->array_pitch = 0; } else { lvl = pimg->u.tex.level; img->offset = rsc->slices[lvl].offset; img->pitch = rsc->slices[lvl].pitch * rsc->cpp; img->array_pitch = rsc->layer_size; } img->width = u_minify(prsc->width0, lvl); img->height = u_minify(prsc->height0, lvl); img->depth = u_minify(prsc->depth0, lvl); }
/** * Progagate any changes from surfaces to texture. * pipe is optional context to inline the blit command in. */ void svga_propagate_surface(struct pipe_context *pipe, struct pipe_surface *surf) { struct svga_surface *s = svga_surface(surf); struct svga_texture *tex = svga_texture(surf->texture); struct svga_screen *ss = svga_screen(surf->texture->screen); if (!s->dirty) return; s->dirty = FALSE; ss->texture_timestamp++; tex->view_age[surf->level] = ++(tex->age); if (s->handle != tex->handle) { SVGA_DBG(DEBUG_VIEWS, "svga: Surface propagate: tex %p, level %u, from %p\n", tex, surf->level, surf); svga_texture_copy_handle(svga_context(pipe), s->handle, 0, 0, 0, s->real_level, s->real_face, tex->handle, 0, 0, surf->zslice, surf->level, surf->face, u_minify(tex->b.b.width0, surf->level), u_minify(tex->b.b.height0, surf->level), 1); tex->defined[surf->face][surf->level] = TRUE; } }
/** * Progagate any changes from surfaces to texture. * pipe is optional context to inline the blit command in. */ void svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf) { struct svga_surface *s = svga_surface(surf); struct svga_texture *tex = svga_texture(surf->texture); struct svga_screen *ss = svga_screen(surf->texture->screen); unsigned zslice, face; if (!s->dirty) return; if (surf->texture->target == PIPE_TEXTURE_CUBE) { zslice = 0; face = surf->u.tex.first_layer; } else { zslice = surf->u.tex.first_layer; face = 0; } s->dirty = FALSE; ss->texture_timestamp++; svga_age_texture_view(tex, surf->u.tex.level); if (s->handle != tex->handle) { SVGA_DBG(DEBUG_VIEWS, "svga: Surface propagate: tex %p, level %u, from %p\n", tex, surf->u.tex.level, surf); svga_texture_copy_handle(svga, s->handle, 0, 0, 0, s->real_level, s->real_face, tex->handle, 0, 0, zslice, surf->u.tex.level, face, u_minify(tex->b.b.width0, surf->u.tex.level), u_minify(tex->b.b.height0, surf->u.tex.level), 1); svga_define_texture_level(tex, face, surf->u.tex.level); } }
static unsigned r300_texture_get_nblocksy(struct r300_texture* tex, unsigned level) { unsigned height, tile_height; height = u_minify(tex->tex.height0, level); if (!util_format_is_compressed(tex->tex.format)) { tile_height = r300_texture_get_tile_size(tex, TILE_HEIGHT, tex->mip_macrotile[level]); height = align(height, tile_height); } return util_format_get_nblocksy(tex->tex.format, height); }
/** * Check if a texture image can be pulled into a unified mipmap texture. */ GLboolean st_texture_match_image(struct st_context *st, const struct pipe_resource *pt, const struct gl_texture_image *image) { unsigned ptWidth; uint16_t ptHeight, ptDepth, ptLayers; /* Images with borders are never pulled into mipmap textures. */ if (image->Border) return GL_FALSE; /* Check if this image's format matches the established texture's format. */ if (st_mesa_format_to_pipe_format(st, image->TexFormat) != pt->format) return GL_FALSE; st_gl_texture_dims_to_pipe_dims(image->TexObject->Target, image->Width, image->Height, image->Depth, &ptWidth, &ptHeight, &ptDepth, &ptLayers); /* Test if this image's size matches what's expected in the * established texture. */ if (ptWidth != u_minify(pt->width0, image->Level) || ptHeight != u_minify(pt->height0, image->Level) || ptDepth != u_minify(pt->depth0, image->Level) || ptLayers != pt->array_size) return GL_FALSE; if (image->Level > pt->last_level) return GL_FALSE; return GL_TRUE; }
/* Return true if macrotiling should be enabled on the miplevel. */ static boolean r300_texture_macro_switch(struct r300_texture *tex, unsigned level, boolean rv350_mode) { unsigned tile_width, width; tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH, TRUE); width = u_minify(tex->tex.width0, level); /* See TX_FILTER1_n.MACRO_SWITCH. */ if (rv350_mode) { return width >= tile_width; } else { return width > tile_width; } }
static void blitter_set_texcoords(struct blitter_context_priv *ctx, struct pipe_sampler_view *src, unsigned src_width0, unsigned src_height0, unsigned layer, unsigned x1, unsigned y1, unsigned x2, unsigned y2) { unsigned i; float coord[4]; float face_coord[4][2]; get_texcoords(src, src_width0, src_height0, x1, y1, x2, y2, coord); if (src->texture->target == PIPE_TEXTURE_CUBE) { set_texcoords_in_vertices(coord, &face_coord[0][0], 2); util_map_texcoords2d_onto_cubemap(layer, /* pointer, stride in floats */ &face_coord[0][0], 2, &ctx->vertices[0][1][0], 8); } else { set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8); } /* Set the layer. */ switch (src->texture->target) { case PIPE_TEXTURE_3D: { float r = layer / (float)u_minify(src->texture->depth0, src->u.tex.first_level); for (i = 0; i < 4; i++) ctx->vertices[i][1][2] = r; /*r*/ } break; case PIPE_TEXTURE_1D_ARRAY: for (i = 0; i < 4; i++) ctx->vertices[i][1][1] = layer; /*t*/ break; case PIPE_TEXTURE_2D_ARRAY: for (i = 0; i < 4; i++) ctx->vertices[i][1][2] = layer; /*r*/ break; default:; } }
/** * Copy the image at level=0 in 'src' to the 'dst' resource at 'dstLevel'. * This is used to copy mipmap images from one texture buffer to another. * This typically happens when our initial guess at the total texture size * is incorrect (see the guess_and_alloc_texture() function). */ void st_texture_image_copy(struct pipe_context *pipe, struct pipe_resource *dst, GLuint dstLevel, struct pipe_resource *src, GLuint srcLevel, GLuint face) { GLuint width = u_minify(dst->width0, dstLevel); GLuint height = u_minify(dst->height0, dstLevel); GLuint depth = u_minify(dst->depth0, dstLevel); struct pipe_box src_box; GLuint i; if (u_minify(src->width0, srcLevel) != width || u_minify(src->height0, srcLevel) != height || u_minify(src->depth0, srcLevel) != depth) { /* The source image size doesn't match the destination image size. * This can happen in some degenerate situations such as rendering to a * cube map face which was set up with mismatched texture sizes. */ return; } src_box.x = 0; src_box.y = 0; src_box.width = width; src_box.height = height; src_box.depth = 1; if (src->target == PIPE_TEXTURE_1D_ARRAY || src->target == PIPE_TEXTURE_2D_ARRAY || src->target == PIPE_TEXTURE_CUBE_ARRAY) { face = 0; depth = src->array_size; } /* Loop over 3D image slices */ /* could (and probably should) use "true" 3d box here - but drivers can't quite handle it yet */ for (i = face; i < face + depth; i++) { src_box.z = i; if (0) { print_center_pixel(pipe, src); } pipe->resource_copy_region(pipe, dst, dstLevel, 0, 0, i,/* destX, Y, Z */ src, srcLevel, &src_box); } }
static void r600_setup_miptree(struct pipe_screen *screen, struct r600_resource_texture *rtex, unsigned array_mode) { struct pipe_resource *ptex = &rtex->resource.b.b; enum chip_class chipc = ((struct r600_screen*)screen)->chip_class; unsigned size, layer_size, i, offset; unsigned nblocksx, nblocksy; for (i = 0, offset = 0; i <= ptex->last_level; i++) { unsigned blocksize = util_format_get_blocksize(rtex->real_format); unsigned base_align = r600_get_base_alignment(screen, rtex->real_format, array_mode); r600_texture_set_array_mode(screen, rtex, i, array_mode); nblocksx = r600_texture_get_nblocksx(screen, rtex, i); nblocksy = r600_texture_get_nblocksy(screen, rtex, i); if (array_mode == V_009910_ARRAY_LINEAR_GENERAL) layer_size = align(nblocksx, 64) * nblocksy * blocksize; else layer_size = nblocksx * nblocksy * blocksize; if (ptex->target == PIPE_TEXTURE_CUBE) { if (chipc >= CAYMAN) size = layer_size * 8; } else if (ptex->target == PIPE_TEXTURE_3D) size = layer_size * u_minify(ptex->depth0, i); else size = layer_size * ptex->array_size; /* align base image and start of miptree */ if ((i == 0) || (i == 1)) offset = align(offset, base_align); rtex->offset[i] = offset; rtex->layer_size[i] = layer_size; rtex->pitch_in_blocks[i] = nblocksx; /* CB talks in elements */ rtex->pitch_in_bytes[i] = nblocksx * blocksize; offset += size; } rtex->size = offset; }
/** * Helper function to compute offset (in bytes) for a particular * texture level/face/slice from the start of the buffer. */ static unsigned sp_get_tex_image_offset(const struct softpipe_resource *spr, unsigned level, unsigned layer) { const unsigned hgt = u_minify(spr->base.height0, level); const unsigned nblocksy = util_format_get_nblocksy(spr->base.format, hgt); unsigned offset = spr->level_offset[level]; if (spr->base.target == PIPE_TEXTURE_CUBE || spr->base.target == PIPE_TEXTURE_3D || spr->base.target == PIPE_TEXTURE_2D_ARRAY) { offset += layer * nblocksy * spr->stride[level]; } else if (spr->base.target == PIPE_TEXTURE_1D_ARRAY) { offset += layer * spr->stride[level]; } else { assert(layer == 0); } return offset; }