/** * Return the stride, in bytes, of the texture image of the given texture * at the given level. */ static unsigned r300_texture_get_stride(struct r300_screen *screen, struct r300_texture_desc *desc, unsigned level) { unsigned tile_width, width, stride; if (desc->stride_in_bytes_override) return desc->stride_in_bytes_override; /* Check the level. */ if (level > desc->b.b.last_level) { SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n", __FUNCTION__, level, desc->b.b.last_level); return 0; } width = u_minify(desc->b.b.width0, level); if (util_format_is_plain(desc->b.b.format)) { tile_width = r300_get_pixel_alignment(desc->b.b.format, desc->b.b.nr_samples, desc->microtile, desc->macrotile[level], DIM_WIDTH); width = align(width, tile_width); stride = util_format_get_stride(desc->b.b.format, width); /* Some IGPs need a minimum stride of 64 bytes, hmm... */ if (!desc->macrotile[level] && (screen->caps.family == CHIP_FAMILY_RS600 || screen->caps.family == CHIP_FAMILY_RS690 || screen->caps.family == CHIP_FAMILY_RS740)) { unsigned min_stride; if (desc->microtile) { unsigned tile_height = r300_get_pixel_alignment(desc->b.b.format, desc->b.b.nr_samples, desc->microtile, desc->macrotile[level], DIM_HEIGHT); min_stride = 64 / tile_height; } else { min_stride = 64; } return stride < min_stride ? min_stride : stride; } /* The alignment to 32 bytes is sort of implied by the layout... */ return stride; } else { return align(util_format_get_stride(desc->b.b.format, width), 32); } }
/* 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; if (tex->b.b.nr_samples > 1) { return TRUE; } tile = r300_get_pixel_alignment(tex->b.b.format, tex->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 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; } }
/** * Return the stride, in bytes, of the texture image of the given texture * at the given level. */ static unsigned r300_texture_get_stride(struct r300_screen *screen, struct r300_resource *tex, unsigned level) { unsigned tile_width, width, stride; boolean is_rs690 = (screen->caps.family == CHIP_FAMILY_RS600 || screen->caps.family == CHIP_FAMILY_RS690 || screen->caps.family == CHIP_FAMILY_RS740); if (tex->tex.stride_in_bytes_override) return tex->tex.stride_in_bytes_override; /* Check the level. */ if (level > tex->b.b.b.last_level) { SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n", __FUNCTION__, level, tex->b.b.b.last_level); return 0; } width = u_minify(tex->tex.width0, level); if (util_format_is_plain(tex->b.b.b.format)) { tile_width = r300_get_pixel_alignment(tex->b.b.b.format, tex->b.b.b.nr_samples, tex->tex.microtile, tex->tex.macrotile[level], DIM_WIDTH, is_rs690); width = align(width, tile_width); stride = util_format_get_stride(tex->b.b.b.format, width); /* The alignment to 32 bytes is sort of implied by the layout... */ return stride; } else { return align(util_format_get_stride(tex->b.b.b.format, width), is_rs690 ? 64 : 32); } }
/* Not required to implement u_resource_vtbl, consider moving to another file: */ struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen, struct pipe_resource* texture, unsigned face, unsigned level, unsigned zslice, unsigned flags) { struct r300_texture* tex = r300_texture(texture); struct r300_surface* surface = CALLOC_STRUCT(r300_surface); if (surface) { uint32_t offset, tile_height; pipe_reference_init(&surface->base.reference, 1); pipe_resource_reference(&surface->base.texture, texture); surface->base.format = texture->format; surface->base.width = u_minify(texture->width0, level); surface->base.height = u_minify(texture->height0, level); surface->base.usage = flags; surface->base.zslice = zslice; surface->base.face = face; surface->base.level = level; surface->buffer = tex->buffer; /* Prefer VRAM if there are multiple domains to choose from. */ surface->domain = tex->domain; if (surface->domain & R300_DOMAIN_VRAM) surface->domain &= ~R300_DOMAIN_GTT; surface->offset = r300_texture_get_offset(&tex->desc, level, zslice, face); surface->pitch = tex->fb_state.pitch[level]; surface->format = tex->fb_state.format; /* Parameters for the CBZB clear. */ surface->cbzb_allowed = tex->desc.cbzb_allowed[level]; surface->cbzb_width = align(surface->base.width, 64); /* Height must be aligned to the size of a tile. */ tile_height = r300_get_pixel_alignment(tex->desc.b.b.format, tex->desc.b.b.nr_samples, tex->desc.microtile, tex->desc.macrotile[level], DIM_HEIGHT, 0); surface->cbzb_height = align((surface->base.height + 1) / 2, tile_height); /* Offset must be aligned to 2K and must point at the beginning * of a scanline. */ offset = surface->offset + tex->desc.stride_in_bytes[level] * surface->cbzb_height; surface->cbzb_midpoint_offset = offset & ~2047; surface->cbzb_pitch = surface->pitch & 0x1ffffc; if (util_format_get_blocksizebits(surface->base.format) == 32) surface->cbzb_format = R300_DEPTHFORMAT_24BIT_INT_Z_8BIT_STENCIL; else surface->cbzb_format = R300_DEPTHFORMAT_16BIT_INT_Z; SCREEN_DBG(r300_screen(screen), DBG_CBZB, "CBZB Allowed: %s, Dim: %ix%i, Misalignment: %i, Micro: %s, Macro: %s\n", surface->cbzb_allowed ? "YES" : " NO", surface->cbzb_width, surface->cbzb_height, offset & 2047, tex->desc.microtile ? "YES" : " NO", tex->desc.macrotile[level] ? "YES" : " NO"); } return &surface->base; }