static void r300_setup_miptree(struct r300_screen *screen, struct r300_resource *tex, boolean align_for_cbzb) { struct pipe_resource *base = &tex->b.b.b; unsigned stride, size, layer_size, nblocksy, i; boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_R350; boolean aligned_for_cbzb; tex->tex.size_in_bytes = 0; SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Making miptree for texture, format %s\n", util_format_short_name(base->format)); for (i = 0; i <= base->last_level; i++) { /* Let's see if this miplevel can be macrotiled. */ tex->tex.macrotile[i] = (tex->tex.macrotile[0] == RADEON_LAYOUT_TILED && r300_texture_macro_switch(tex, i, rv350_mode, DIM_WIDTH) && r300_texture_macro_switch(tex, i, rv350_mode, DIM_HEIGHT)) ? RADEON_LAYOUT_TILED : RADEON_LAYOUT_LINEAR; stride = r300_texture_get_stride(screen, tex, i); /* Compute the number of blocks in Y, see if the CBZB clear can be * used on the texture. */ aligned_for_cbzb = FALSE; if (align_for_cbzb && tex->tex.cbzb_allowed[i]) nblocksy = r300_texture_get_nblocksy(tex, i, &aligned_for_cbzb); else nblocksy = r300_texture_get_nblocksy(tex, i, NULL); layer_size = stride * nblocksy; if (base->nr_samples) { layer_size *= base->nr_samples; } if (base->target == PIPE_TEXTURE_CUBE) size = layer_size * 6; else size = layer_size * u_minify(tex->tex.depth0, i); tex->tex.offset_in_bytes[i] = tex->tex.size_in_bytes; tex->tex.size_in_bytes = tex->tex.offset_in_bytes[i] + size; tex->tex.layer_size_in_bytes[i] = layer_size; tex->tex.stride_in_bytes[i] = stride; tex->tex.stride_in_pixels[i] = stride_to_width(tex->b.b.b.format, stride); tex->tex.cbzb_allowed[i] = tex->tex.cbzb_allowed[i] && aligned_for_cbzb; SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Texture miptree: Level %d " "(%dx%dx%d px, pitch %d bytes) %d bytes total, macrotiled %s\n", i, u_minify(tex->tex.width0, i), u_minify(tex->tex.height0, i), u_minify(tex->tex.depth0, i), stride, tex->tex.size_in_bytes, tex->tex.macrotile[i] ? "TRUE" : "FALSE"); } }
/** * Return the stride, in bytes, of the texture images of the given texture * at the given level. */ unsigned r300_texture_get_stride(struct r300_screen* screen, struct r300_texture* tex, unsigned level) { unsigned tile_width, width; if (tex->stride_override) return tex->stride_override; /* Check the level. */ if (level > tex->tex.last_level) { SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n", __FUNCTION__, level, tex->tex.last_level); return 0; } width = u_minify(tex->tex.width0, level); if (!util_format_is_compressed(tex->tex.format)) { tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH, tex->mip_macrotile[level]); width = align(width, tile_width); return util_format_get_stride(tex->tex.format, width); } else { return align(util_format_get_stride(tex->tex.format, width), 32); } }
/** * 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); } }
void r300_texture_reinterpret_format(struct pipe_screen *screen, struct pipe_texture *tex, enum pipe_format new_format) { struct r300_screen *r300screen = r300_screen(screen); SCREEN_DBG(r300screen, DBG_TEX, "r300: Reinterpreting format: %s -> %s\n", util_format_name(tex->format), util_format_name(new_format)); tex->format = new_format; r300_setup_texture_state(r300_screen(screen), (struct r300_texture*)tex); }
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"); } }
/** * 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; }
static void r300_setup_texture_state(struct r300_screen* screen, struct r300_texture* tex) { struct r300_texture_format_state* state = &tex->state; struct pipe_texture *pt = &tex->tex; unsigned i; boolean is_r500 = screen->caps->is_r500; /* Set sampler state. */ state->format0 = R300_TX_WIDTH((pt->width0 - 1) & 0x7ff) | R300_TX_HEIGHT((pt->height0 - 1) & 0x7ff); if (tex->is_npot) { /* rectangles love this */ state->format0 |= R300_TX_PITCH_EN; state->format2 = (tex->pitch[0] - 1) & 0x1fff; } else { /* power of two textures (3D, mipmaps, and no pitch) */ state->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth0) & 0xf); } state->format1 = r300_translate_texformat(pt->format); if (pt->target == PIPE_TEXTURE_CUBE) { state->format1 |= R300_TX_FORMAT_CUBIC_MAP; } if (pt->target == PIPE_TEXTURE_3D) { state->format1 |= R300_TX_FORMAT_3D; } /* large textures on r500 */ if (is_r500) { if (pt->width0 > 2048) { state->format2 |= R500_TXWIDTH_BIT11; } if (pt->height0 > 2048) { state->format2 |= R500_TXHEIGHT_BIT11; } } SCREEN_DBG(screen, DBG_TEX, "r300: Set texture state (%dx%d, %d levels)\n", pt->width0, pt->height0, pt->last_level); /* Set framebuffer state. */ if (util_format_is_depth_or_stencil(tex->tex.format)) { for (i = 0; i <= tex->tex.last_level; i++) { tex->fb_state.depthpitch[i] = tex->pitch[i] | R300_DEPTHMACROTILE(tex->mip_macrotile[i]) | R300_DEPTHMICROTILE(tex->microtile); } tex->fb_state.zb_format = r300_translate_zsformat(tex->tex.format); } else { for (i = 0; i <= tex->tex.last_level; i++) { tex->fb_state.colorpitch[i] = tex->pitch[i] | r300_translate_colorformat(tex->tex.format) | R300_COLOR_TILE(tex->mip_macrotile[i]) | R300_COLOR_MICROTILE(tex->microtile); } tex->fb_state.us_out_fmt = r300_translate_out_fmt(tex->tex.format); } }