1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com> 3bf215546Sopenharmony_ci * Copyright 2010 Marek Olšák <maraeo@gmail.com> 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 8bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 9bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 10bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 11bf215546Sopenharmony_ci * 12bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 13bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 14bf215546Sopenharmony_ci * Software. 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "r300_texture_desc.h" 25bf215546Sopenharmony_ci#include "r300_context.h" 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "util/format/u_format.h" 28bf215546Sopenharmony_ci#include <inttypes.h> 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci/* Returns the number of pixels that the texture should be aligned to 31bf215546Sopenharmony_ci * in the given dimension. */ 32bf215546Sopenharmony_ciunsigned r300_get_pixel_alignment(enum pipe_format format, 33bf215546Sopenharmony_ci unsigned num_samples, 34bf215546Sopenharmony_ci enum radeon_bo_layout microtile, 35bf215546Sopenharmony_ci enum radeon_bo_layout macrotile, 36bf215546Sopenharmony_ci enum r300_dim dim, boolean is_rs690) 37bf215546Sopenharmony_ci{ 38bf215546Sopenharmony_ci static const unsigned table[2][5][3][2] = 39bf215546Sopenharmony_ci { 40bf215546Sopenharmony_ci { 41bf215546Sopenharmony_ci /* Macro: linear linear linear 42bf215546Sopenharmony_ci Micro: linear tiled square-tiled */ 43bf215546Sopenharmony_ci {{ 32, 1}, { 8, 4}, { 0, 0}}, /* 8 bits per pixel */ 44bf215546Sopenharmony_ci {{ 16, 1}, { 8, 2}, { 4, 4}}, /* 16 bits per pixel */ 45bf215546Sopenharmony_ci {{ 8, 1}, { 4, 2}, { 0, 0}}, /* 32 bits per pixel */ 46bf215546Sopenharmony_ci {{ 4, 1}, { 2, 2}, { 0, 0}}, /* 64 bits per pixel */ 47bf215546Sopenharmony_ci {{ 2, 1}, { 0, 0}, { 0, 0}} /* 128 bits per pixel */ 48bf215546Sopenharmony_ci }, 49bf215546Sopenharmony_ci { 50bf215546Sopenharmony_ci /* Macro: tiled tiled tiled 51bf215546Sopenharmony_ci Micro: linear tiled square-tiled */ 52bf215546Sopenharmony_ci {{256, 8}, {64, 32}, { 0, 0}}, /* 8 bits per pixel */ 53bf215546Sopenharmony_ci {{128, 8}, {64, 16}, {32, 32}}, /* 16 bits per pixel */ 54bf215546Sopenharmony_ci {{ 64, 8}, {32, 16}, { 0, 0}}, /* 32 bits per pixel */ 55bf215546Sopenharmony_ci {{ 32, 8}, {16, 16}, { 0, 0}}, /* 64 bits per pixel */ 56bf215546Sopenharmony_ci {{ 16, 8}, { 0, 0}, { 0, 0}} /* 128 bits per pixel */ 57bf215546Sopenharmony_ci } 58bf215546Sopenharmony_ci }; 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_ci unsigned tile = 0; 61bf215546Sopenharmony_ci unsigned pixsize = util_format_get_blocksize(format); 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci assert(macrotile <= RADEON_LAYOUT_TILED); 64bf215546Sopenharmony_ci assert(microtile <= RADEON_LAYOUT_SQUARETILED); 65bf215546Sopenharmony_ci assert(pixsize <= 16); 66bf215546Sopenharmony_ci assert(dim <= DIM_HEIGHT); 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_ci tile = table[macrotile][util_logbase2(pixsize)][microtile][dim]; 69bf215546Sopenharmony_ci if (macrotile == 0 && is_rs690 && dim == DIM_WIDTH) { 70bf215546Sopenharmony_ci int align; 71bf215546Sopenharmony_ci int h_tile; 72bf215546Sopenharmony_ci h_tile = table[macrotile][util_logbase2(pixsize)][microtile][DIM_HEIGHT]; 73bf215546Sopenharmony_ci align = 64 / (pixsize * h_tile); 74bf215546Sopenharmony_ci if (tile < align) 75bf215546Sopenharmony_ci tile = align; 76bf215546Sopenharmony_ci } 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci assert(tile); 79bf215546Sopenharmony_ci return tile; 80bf215546Sopenharmony_ci} 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci/* Return true if macrotiling should be enabled on the miplevel. */ 83bf215546Sopenharmony_cistatic boolean r300_texture_macro_switch(struct r300_resource *tex, 84bf215546Sopenharmony_ci unsigned level, 85bf215546Sopenharmony_ci boolean rv350_mode, 86bf215546Sopenharmony_ci enum r300_dim dim) 87bf215546Sopenharmony_ci{ 88bf215546Sopenharmony_ci unsigned tile, texdim; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci if (tex->b.nr_samples > 1) { 91bf215546Sopenharmony_ci return TRUE; 92bf215546Sopenharmony_ci } 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci tile = r300_get_pixel_alignment(tex->b.format, tex->b.nr_samples, 95bf215546Sopenharmony_ci tex->tex.microtile, RADEON_LAYOUT_TILED, dim, 0); 96bf215546Sopenharmony_ci if (dim == DIM_WIDTH) { 97bf215546Sopenharmony_ci texdim = u_minify(tex->tex.width0, level); 98bf215546Sopenharmony_ci } else { 99bf215546Sopenharmony_ci texdim = u_minify(tex->tex.height0, level); 100bf215546Sopenharmony_ci } 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci /* See TX_FILTER1_n.MACRO_SWITCH. */ 103bf215546Sopenharmony_ci if (rv350_mode) { 104bf215546Sopenharmony_ci return texdim >= tile; 105bf215546Sopenharmony_ci } else { 106bf215546Sopenharmony_ci return texdim > tile; 107bf215546Sopenharmony_ci } 108bf215546Sopenharmony_ci} 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci/** 111bf215546Sopenharmony_ci * Return the stride, in bytes, of the texture image of the given texture 112bf215546Sopenharmony_ci * at the given level. 113bf215546Sopenharmony_ci */ 114bf215546Sopenharmony_cistatic unsigned r300_texture_get_stride(struct r300_screen *screen, 115bf215546Sopenharmony_ci struct r300_resource *tex, 116bf215546Sopenharmony_ci unsigned level) 117bf215546Sopenharmony_ci{ 118bf215546Sopenharmony_ci unsigned tile_width, width, stride; 119bf215546Sopenharmony_ci boolean is_rs690 = (screen->caps.family == CHIP_RS600 || 120bf215546Sopenharmony_ci screen->caps.family == CHIP_RS690 || 121bf215546Sopenharmony_ci screen->caps.family == CHIP_RS740); 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci if (tex->tex.stride_in_bytes_override) 124bf215546Sopenharmony_ci return tex->tex.stride_in_bytes_override; 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci /* Check the level. */ 127bf215546Sopenharmony_ci if (level > tex->b.last_level) { 128bf215546Sopenharmony_ci SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n", 129bf215546Sopenharmony_ci __FUNCTION__, level, tex->b.last_level); 130bf215546Sopenharmony_ci return 0; 131bf215546Sopenharmony_ci } 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci width = u_minify(tex->tex.width0, level); 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci if (util_format_is_plain(tex->b.format)) { 136bf215546Sopenharmony_ci tile_width = r300_get_pixel_alignment(tex->b.format, 137bf215546Sopenharmony_ci tex->b.nr_samples, 138bf215546Sopenharmony_ci tex->tex.microtile, 139bf215546Sopenharmony_ci tex->tex.macrotile[level], 140bf215546Sopenharmony_ci DIM_WIDTH, is_rs690); 141bf215546Sopenharmony_ci width = align(width, tile_width); 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci stride = util_format_get_stride(tex->b.format, width); 144bf215546Sopenharmony_ci /* The alignment to 32 bytes is sort of implied by the layout... */ 145bf215546Sopenharmony_ci return stride; 146bf215546Sopenharmony_ci } else { 147bf215546Sopenharmony_ci return align(util_format_get_stride(tex->b.format, width), is_rs690 ? 64 : 32); 148bf215546Sopenharmony_ci } 149bf215546Sopenharmony_ci} 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_cistatic unsigned r300_texture_get_nblocksy(struct r300_resource *tex, 152bf215546Sopenharmony_ci unsigned level, 153bf215546Sopenharmony_ci boolean *out_aligned_for_cbzb) 154bf215546Sopenharmony_ci{ 155bf215546Sopenharmony_ci unsigned height, tile_height; 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci height = u_minify(tex->tex.height0, level); 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci /* Mipmapped and 3D textures must have their height aligned to POT. */ 160bf215546Sopenharmony_ci if ((tex->b.target != PIPE_TEXTURE_1D && 161bf215546Sopenharmony_ci tex->b.target != PIPE_TEXTURE_2D && 162bf215546Sopenharmony_ci tex->b.target != PIPE_TEXTURE_RECT) || 163bf215546Sopenharmony_ci tex->b.last_level != 0) { 164bf215546Sopenharmony_ci height = util_next_power_of_two(height); 165bf215546Sopenharmony_ci } 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci if (util_format_is_plain(tex->b.format)) { 168bf215546Sopenharmony_ci tile_height = r300_get_pixel_alignment(tex->b.format, 169bf215546Sopenharmony_ci tex->b.nr_samples, 170bf215546Sopenharmony_ci tex->tex.microtile, 171bf215546Sopenharmony_ci tex->tex.macrotile[level], 172bf215546Sopenharmony_ci DIM_HEIGHT, 0); 173bf215546Sopenharmony_ci height = align(height, tile_height); 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci /* See if the CBZB clear can be used on the buffer, 176bf215546Sopenharmony_ci * taking the texture size into account. */ 177bf215546Sopenharmony_ci if (out_aligned_for_cbzb) { 178bf215546Sopenharmony_ci if (tex->tex.macrotile[level]) { 179bf215546Sopenharmony_ci /* When clearing, the layer (width*height) is horizontally split 180bf215546Sopenharmony_ci * into two, and the upper and lower halves are cleared by the CB 181bf215546Sopenharmony_ci * and ZB units, respectively. Therefore, the number of macrotiles 182bf215546Sopenharmony_ci * in the Y direction must be even. */ 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci /* Align the height so that there is an even number of macrotiles. 185bf215546Sopenharmony_ci * Do so for 3 or more macrotiles in the Y direction. */ 186bf215546Sopenharmony_ci if (level == 0 && tex->b.last_level == 0 && 187bf215546Sopenharmony_ci (tex->b.target == PIPE_TEXTURE_1D || 188bf215546Sopenharmony_ci tex->b.target == PIPE_TEXTURE_2D || 189bf215546Sopenharmony_ci tex->b.target == PIPE_TEXTURE_RECT) && 190bf215546Sopenharmony_ci height >= tile_height * 3) { 191bf215546Sopenharmony_ci height = align(height, tile_height * 2); 192bf215546Sopenharmony_ci } 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci *out_aligned_for_cbzb = height % (tile_height * 2) == 0; 195bf215546Sopenharmony_ci } else { 196bf215546Sopenharmony_ci *out_aligned_for_cbzb = FALSE; 197bf215546Sopenharmony_ci } 198bf215546Sopenharmony_ci } 199bf215546Sopenharmony_ci } 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci return util_format_get_nblocksy(tex->b.format, height); 202bf215546Sopenharmony_ci} 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci/* Get a width in pixels from a stride in bytes. */ 205bf215546Sopenharmony_ciunsigned r300_stride_to_width(enum pipe_format format, 206bf215546Sopenharmony_ci unsigned stride_in_bytes) 207bf215546Sopenharmony_ci{ 208bf215546Sopenharmony_ci return (stride_in_bytes / util_format_get_blocksize(format)) * 209bf215546Sopenharmony_ci util_format_get_blockwidth(format); 210bf215546Sopenharmony_ci} 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_cistatic void r300_setup_miptree(struct r300_screen *screen, 213bf215546Sopenharmony_ci struct r300_resource *tex, 214bf215546Sopenharmony_ci boolean align_for_cbzb) 215bf215546Sopenharmony_ci{ 216bf215546Sopenharmony_ci struct pipe_resource *base = &tex->b; 217bf215546Sopenharmony_ci unsigned stride, size, layer_size, nblocksy, i; 218bf215546Sopenharmony_ci boolean rv350_mode = screen->caps.family >= CHIP_R350; 219bf215546Sopenharmony_ci boolean aligned_for_cbzb; 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci tex->tex.size_in_bytes = 0; 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci SCREEN_DBG(screen, DBG_TEXALLOC, 224bf215546Sopenharmony_ci "r300: Making miptree for texture, format %s\n", 225bf215546Sopenharmony_ci util_format_short_name(base->format)); 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci for (i = 0; i <= base->last_level; i++) { 228bf215546Sopenharmony_ci /* Let's see if this miplevel can be macrotiled. */ 229bf215546Sopenharmony_ci tex->tex.macrotile[i] = 230bf215546Sopenharmony_ci (tex->tex.macrotile[0] == RADEON_LAYOUT_TILED && 231bf215546Sopenharmony_ci r300_texture_macro_switch(tex, i, rv350_mode, DIM_WIDTH) && 232bf215546Sopenharmony_ci r300_texture_macro_switch(tex, i, rv350_mode, DIM_HEIGHT)) ? 233bf215546Sopenharmony_ci RADEON_LAYOUT_TILED : RADEON_LAYOUT_LINEAR; 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci stride = r300_texture_get_stride(screen, tex, i); 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci /* Compute the number of blocks in Y, see if the CBZB clear can be 238bf215546Sopenharmony_ci * used on the texture. */ 239bf215546Sopenharmony_ci aligned_for_cbzb = FALSE; 240bf215546Sopenharmony_ci if (align_for_cbzb && tex->tex.cbzb_allowed[i]) 241bf215546Sopenharmony_ci nblocksy = r300_texture_get_nblocksy(tex, i, &aligned_for_cbzb); 242bf215546Sopenharmony_ci else 243bf215546Sopenharmony_ci nblocksy = r300_texture_get_nblocksy(tex, i, NULL); 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci layer_size = stride * nblocksy; 246bf215546Sopenharmony_ci 247bf215546Sopenharmony_ci if (base->nr_samples > 1) { 248bf215546Sopenharmony_ci layer_size *= base->nr_samples; 249bf215546Sopenharmony_ci } 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci if (base->target == PIPE_TEXTURE_CUBE) 252bf215546Sopenharmony_ci size = layer_size * 6; 253bf215546Sopenharmony_ci else 254bf215546Sopenharmony_ci size = layer_size * u_minify(tex->tex.depth0, i); 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci tex->tex.offset_in_bytes[i] = tex->tex.size_in_bytes; 257bf215546Sopenharmony_ci tex->tex.size_in_bytes = tex->tex.offset_in_bytes[i] + size; 258bf215546Sopenharmony_ci tex->tex.layer_size_in_bytes[i] = layer_size; 259bf215546Sopenharmony_ci tex->tex.stride_in_bytes[i] = stride; 260bf215546Sopenharmony_ci tex->tex.cbzb_allowed[i] = tex->tex.cbzb_allowed[i] && aligned_for_cbzb; 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Texture miptree: Level %d " 263bf215546Sopenharmony_ci "(%dx%dx%d px, pitch %d bytes) %d bytes total, macrotiled %s\n", 264bf215546Sopenharmony_ci i, u_minify(tex->tex.width0, i), u_minify(tex->tex.height0, i), 265bf215546Sopenharmony_ci u_minify(tex->tex.depth0, i), stride, tex->tex.size_in_bytes, 266bf215546Sopenharmony_ci tex->tex.macrotile[i] ? "TRUE" : "FALSE"); 267bf215546Sopenharmony_ci } 268bf215546Sopenharmony_ci} 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_cistatic void r300_setup_flags(struct r300_resource *tex) 271bf215546Sopenharmony_ci{ 272bf215546Sopenharmony_ci tex->tex.uses_stride_addressing = 273bf215546Sopenharmony_ci !util_is_power_of_two_or_zero(tex->b.width0) || 274bf215546Sopenharmony_ci (tex->tex.stride_in_bytes_override && 275bf215546Sopenharmony_ci r300_stride_to_width(tex->b.format, 276bf215546Sopenharmony_ci tex->tex.stride_in_bytes_override) != tex->b.width0); 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci tex->tex.is_npot = 279bf215546Sopenharmony_ci tex->tex.uses_stride_addressing || 280bf215546Sopenharmony_ci !util_is_power_of_two_or_zero(tex->b.height0) || 281bf215546Sopenharmony_ci !util_is_power_of_two_or_zero(tex->b.depth0); 282bf215546Sopenharmony_ci} 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_cistatic void r300_setup_cbzb_flags(struct r300_screen *rscreen, 285bf215546Sopenharmony_ci struct r300_resource *tex) 286bf215546Sopenharmony_ci{ 287bf215546Sopenharmony_ci unsigned i, bpp; 288bf215546Sopenharmony_ci boolean first_level_valid; 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_ci bpp = util_format_get_blocksizebits(tex->b.format); 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci /* 1) The texture must be point-sampled, 293bf215546Sopenharmony_ci * 2) The depth must be 16 or 32 bits. 294bf215546Sopenharmony_ci * 3) If the midpoint ZB offset is not aligned to 2048, it returns garbage 295bf215546Sopenharmony_ci * with certain texture sizes. Macrotiling ensures the alignment. */ 296bf215546Sopenharmony_ci first_level_valid = tex->b.nr_samples <= 1 && 297bf215546Sopenharmony_ci (bpp == 16 || bpp == 32) && 298bf215546Sopenharmony_ci tex->tex.macrotile[0]; 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_ci if (SCREEN_DBG_ON(rscreen, DBG_NO_CBZB)) 301bf215546Sopenharmony_ci first_level_valid = FALSE; 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci for (i = 0; i <= tex->b.last_level; i++) 304bf215546Sopenharmony_ci tex->tex.cbzb_allowed[i] = first_level_valid && tex->tex.macrotile[i]; 305bf215546Sopenharmony_ci} 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_cistatic unsigned r300_pixels_to_dwords(unsigned stride, 308bf215546Sopenharmony_ci unsigned height, 309bf215546Sopenharmony_ci unsigned xblock, unsigned yblock) 310bf215546Sopenharmony_ci{ 311bf215546Sopenharmony_ci return (util_align_npot(stride, xblock) * align(height, yblock)) / (xblock * yblock); 312bf215546Sopenharmony_ci} 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_cistatic void r300_setup_hyperz_properties(struct r300_screen *screen, 315bf215546Sopenharmony_ci struct r300_resource *tex) 316bf215546Sopenharmony_ci{ 317bf215546Sopenharmony_ci /* The tile size of 1 DWORD in ZMASK RAM is: 318bf215546Sopenharmony_ci * 319bf215546Sopenharmony_ci * GPU Pipes 4x4 mode 8x8 mode 320bf215546Sopenharmony_ci * ------------------------------------------ 321bf215546Sopenharmony_ci * R580 4P/1Z 32x32 64x64 322bf215546Sopenharmony_ci * RV570 3P/1Z 48x16 96x32 323bf215546Sopenharmony_ci * RV530 1P/2Z 32x16 64x32 324bf215546Sopenharmony_ci * 1P/1Z 16x16 32x32 325bf215546Sopenharmony_ci */ 326bf215546Sopenharmony_ci static unsigned zmask_blocks_x_per_dw[4] = {4, 8, 12, 8}; 327bf215546Sopenharmony_ci static unsigned zmask_blocks_y_per_dw[4] = {4, 4, 4, 8}; 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_ci /* In HIZ RAM, one dword is always 8x8 pixels (each byte is 4x4 pixels), 330bf215546Sopenharmony_ci * but the blocks have very weird ordering. 331bf215546Sopenharmony_ci * 332bf215546Sopenharmony_ci * With 2 pipes and an image of size 8xY, where Y >= 1, 333bf215546Sopenharmony_ci * clearing 4 dwords clears blocks like this: 334bf215546Sopenharmony_ci * 335bf215546Sopenharmony_ci * 01012323 336bf215546Sopenharmony_ci * 337bf215546Sopenharmony_ci * where numbers correspond to dword indices. The blocks are interleaved 338bf215546Sopenharmony_ci * in the X direction, so the alignment must be 4x1 blocks (32x8 pixels). 339bf215546Sopenharmony_ci * 340bf215546Sopenharmony_ci * With 4 pipes and an image of size 8xY, where Y >= 4, 341bf215546Sopenharmony_ci * clearing 8 dwords clears blocks like this: 342bf215546Sopenharmony_ci * 01012323 343bf215546Sopenharmony_ci * 45456767 344bf215546Sopenharmony_ci * 01012323 345bf215546Sopenharmony_ci * 45456767 346bf215546Sopenharmony_ci * where numbers correspond to dword indices. The blocks are interleaved 347bf215546Sopenharmony_ci * in both directions, so the alignment must be 4x4 blocks (32x32 pixels) 348bf215546Sopenharmony_ci */ 349bf215546Sopenharmony_ci static unsigned hiz_align_x[4] = {8, 32, 48, 32}; 350bf215546Sopenharmony_ci static unsigned hiz_align_y[4] = {8, 8, 8, 32}; 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_ci if (util_format_is_depth_or_stencil(tex->b.format) && 353bf215546Sopenharmony_ci util_format_get_blocksizebits(tex->b.format) == 32 && 354bf215546Sopenharmony_ci tex->tex.microtile) { 355bf215546Sopenharmony_ci unsigned i, pipes; 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ci if (screen->caps.family == CHIP_RV530) { 358bf215546Sopenharmony_ci pipes = screen->info.r300_num_z_pipes; 359bf215546Sopenharmony_ci } else { 360bf215546Sopenharmony_ci pipes = screen->info.r300_num_gb_pipes; 361bf215546Sopenharmony_ci } 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci for (i = 0; i <= tex->b.last_level; i++) { 364bf215546Sopenharmony_ci unsigned zcomp_numdw, zcompsize, hiz_numdw, stride, height; 365bf215546Sopenharmony_ci 366bf215546Sopenharmony_ci stride = r300_stride_to_width(tex->b.format, 367bf215546Sopenharmony_ci tex->tex.stride_in_bytes[i]); 368bf215546Sopenharmony_ci stride = align(stride, 16); 369bf215546Sopenharmony_ci height = u_minify(tex->b.height0, i); 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci /* The 8x8 compression mode needs macrotiling. */ 372bf215546Sopenharmony_ci zcompsize = screen->caps.z_compress == R300_ZCOMP_8X8 && 373bf215546Sopenharmony_ci tex->tex.macrotile[i] && 374bf215546Sopenharmony_ci tex->b.nr_samples <= 1 ? 8 : 4; 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci /* Get the ZMASK buffer size in dwords. */ 377bf215546Sopenharmony_ci zcomp_numdw = r300_pixels_to_dwords(stride, height, 378bf215546Sopenharmony_ci zmask_blocks_x_per_dw[pipes-1] * zcompsize, 379bf215546Sopenharmony_ci zmask_blocks_y_per_dw[pipes-1] * zcompsize); 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_ci /* Check whether we have enough ZMASK memory. */ 382bf215546Sopenharmony_ci if (util_format_get_blocksizebits(tex->b.format) == 32 && 383bf215546Sopenharmony_ci zcomp_numdw <= screen->caps.zmask_ram * pipes) { 384bf215546Sopenharmony_ci tex->tex.zmask_dwords[i] = zcomp_numdw; 385bf215546Sopenharmony_ci tex->tex.zcomp8x8[i] = zcompsize == 8; 386bf215546Sopenharmony_ci 387bf215546Sopenharmony_ci tex->tex.zmask_stride_in_pixels[i] = 388bf215546Sopenharmony_ci util_align_npot(stride, zmask_blocks_x_per_dw[pipes-1] * zcompsize); 389bf215546Sopenharmony_ci } else { 390bf215546Sopenharmony_ci tex->tex.zmask_dwords[i] = 0; 391bf215546Sopenharmony_ci tex->tex.zcomp8x8[i] = FALSE; 392bf215546Sopenharmony_ci tex->tex.zmask_stride_in_pixels[i] = 0; 393bf215546Sopenharmony_ci } 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_ci /* Now setup HIZ. */ 396bf215546Sopenharmony_ci stride = util_align_npot(stride, hiz_align_x[pipes-1]); 397bf215546Sopenharmony_ci height = align(height, hiz_align_y[pipes-1]); 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci /* Get the HIZ buffer size in dwords. */ 400bf215546Sopenharmony_ci hiz_numdw = (stride * height) / (8*8 * pipes); 401bf215546Sopenharmony_ci 402bf215546Sopenharmony_ci /* Check whether we have enough HIZ memory. */ 403bf215546Sopenharmony_ci if (hiz_numdw <= screen->caps.hiz_ram * pipes) { 404bf215546Sopenharmony_ci tex->tex.hiz_dwords[i] = hiz_numdw; 405bf215546Sopenharmony_ci tex->tex.hiz_stride_in_pixels[i] = stride; 406bf215546Sopenharmony_ci } else { 407bf215546Sopenharmony_ci tex->tex.hiz_dwords[i] = 0; 408bf215546Sopenharmony_ci tex->tex.hiz_stride_in_pixels[i] = 0; 409bf215546Sopenharmony_ci } 410bf215546Sopenharmony_ci } 411bf215546Sopenharmony_ci } 412bf215546Sopenharmony_ci} 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_cistatic void r300_setup_cmask_properties(struct r300_screen *screen, 415bf215546Sopenharmony_ci struct r300_resource *tex) 416bf215546Sopenharmony_ci{ 417bf215546Sopenharmony_ci static unsigned cmask_align_x[4] = {16, 32, 48, 32}; 418bf215546Sopenharmony_ci static unsigned cmask_align_y[4] = {16, 16, 16, 32}; 419bf215546Sopenharmony_ci unsigned pipes, stride, cmask_num_dw, cmask_max_size; 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_ci if (!screen->caps.has_cmask) { 422bf215546Sopenharmony_ci return; 423bf215546Sopenharmony_ci } 424bf215546Sopenharmony_ci 425bf215546Sopenharmony_ci /* We need an AA colorbuffer, no mipmaps. */ 426bf215546Sopenharmony_ci if (tex->b.nr_samples <= 1 || 427bf215546Sopenharmony_ci tex->b.last_level > 0 || 428bf215546Sopenharmony_ci util_format_is_depth_or_stencil(tex->b.format)) { 429bf215546Sopenharmony_ci return; 430bf215546Sopenharmony_ci } 431bf215546Sopenharmony_ci 432bf215546Sopenharmony_ci /* FP16 AA needs R500 and a fairly new DRM. */ 433bf215546Sopenharmony_ci if ((tex->b.format == PIPE_FORMAT_R16G16B16A16_FLOAT || 434bf215546Sopenharmony_ci tex->b.format == PIPE_FORMAT_R16G16B16X16_FLOAT) && 435bf215546Sopenharmony_ci !screen->caps.is_r500) { 436bf215546Sopenharmony_ci return; 437bf215546Sopenharmony_ci } 438bf215546Sopenharmony_ci 439bf215546Sopenharmony_ci if (SCREEN_DBG_ON(screen, DBG_NO_CMASK)) { 440bf215546Sopenharmony_ci return; 441bf215546Sopenharmony_ci } 442bf215546Sopenharmony_ci 443bf215546Sopenharmony_ci /* CMASK is part of raster pipes. The number of Z pipes doesn't matter. */ 444bf215546Sopenharmony_ci pipes = screen->info.r300_num_gb_pipes; 445bf215546Sopenharmony_ci 446bf215546Sopenharmony_ci /* The single-pipe cards have 5120 dwords of CMASK RAM, 447bf215546Sopenharmony_ci * the other cards have 4096 dwords of CMASK RAM per pipe. */ 448bf215546Sopenharmony_ci cmask_max_size = pipes == 1 ? 5120 : pipes * 4096; 449bf215546Sopenharmony_ci 450bf215546Sopenharmony_ci stride = r300_stride_to_width(tex->b.format, 451bf215546Sopenharmony_ci tex->tex.stride_in_bytes[0]); 452bf215546Sopenharmony_ci stride = align(stride, 16); 453bf215546Sopenharmony_ci 454bf215546Sopenharmony_ci /* Get the CMASK size in dwords. */ 455bf215546Sopenharmony_ci cmask_num_dw = r300_pixels_to_dwords(stride, tex->b.height0, 456bf215546Sopenharmony_ci cmask_align_x[pipes-1], 457bf215546Sopenharmony_ci cmask_align_y[pipes-1]); 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci /* Check the CMASK size against the CMASK memory limit. */ 460bf215546Sopenharmony_ci if (cmask_num_dw <= cmask_max_size) { 461bf215546Sopenharmony_ci tex->tex.cmask_dwords = cmask_num_dw; 462bf215546Sopenharmony_ci tex->tex.cmask_stride_in_pixels = 463bf215546Sopenharmony_ci util_align_npot(stride, cmask_align_x[pipes-1]); 464bf215546Sopenharmony_ci } 465bf215546Sopenharmony_ci} 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_cistatic void r300_setup_tiling(struct r300_screen *screen, 468bf215546Sopenharmony_ci struct r300_resource *tex) 469bf215546Sopenharmony_ci{ 470bf215546Sopenharmony_ci enum pipe_format format = tex->b.format; 471bf215546Sopenharmony_ci boolean rv350_mode = screen->caps.family >= CHIP_R350; 472bf215546Sopenharmony_ci boolean is_zb = util_format_is_depth_or_stencil(format); 473bf215546Sopenharmony_ci boolean dbg_no_tiling = SCREEN_DBG_ON(screen, DBG_NO_TILING); 474bf215546Sopenharmony_ci boolean force_microtiling = 475bf215546Sopenharmony_ci (tex->b.flags & R300_RESOURCE_FORCE_MICROTILING) != 0; 476bf215546Sopenharmony_ci 477bf215546Sopenharmony_ci if (tex->b.nr_samples > 1) { 478bf215546Sopenharmony_ci tex->tex.microtile = RADEON_LAYOUT_TILED; 479bf215546Sopenharmony_ci tex->tex.macrotile[0] = RADEON_LAYOUT_TILED; 480bf215546Sopenharmony_ci return; 481bf215546Sopenharmony_ci } 482bf215546Sopenharmony_ci 483bf215546Sopenharmony_ci tex->tex.microtile = RADEON_LAYOUT_LINEAR; 484bf215546Sopenharmony_ci tex->tex.macrotile[0] = RADEON_LAYOUT_LINEAR; 485bf215546Sopenharmony_ci 486bf215546Sopenharmony_ci if (tex->b.usage == PIPE_USAGE_STAGING) { 487bf215546Sopenharmony_ci return; 488bf215546Sopenharmony_ci } 489bf215546Sopenharmony_ci 490bf215546Sopenharmony_ci if (!util_format_is_plain(format)) { 491bf215546Sopenharmony_ci return; 492bf215546Sopenharmony_ci } 493bf215546Sopenharmony_ci 494bf215546Sopenharmony_ci /* If height == 1, disable microtiling except for zbuffer. */ 495bf215546Sopenharmony_ci if (!force_microtiling && !is_zb && 496bf215546Sopenharmony_ci (tex->b.height0 == 1 || dbg_no_tiling)) { 497bf215546Sopenharmony_ci return; 498bf215546Sopenharmony_ci } 499bf215546Sopenharmony_ci 500bf215546Sopenharmony_ci /* Set microtiling. */ 501bf215546Sopenharmony_ci switch (util_format_get_blocksize(format)) { 502bf215546Sopenharmony_ci case 1: 503bf215546Sopenharmony_ci case 4: 504bf215546Sopenharmony_ci case 8: 505bf215546Sopenharmony_ci tex->tex.microtile = RADEON_LAYOUT_TILED; 506bf215546Sopenharmony_ci break; 507bf215546Sopenharmony_ci 508bf215546Sopenharmony_ci case 2: 509bf215546Sopenharmony_ci tex->tex.microtile = RADEON_LAYOUT_SQUARETILED; 510bf215546Sopenharmony_ci break; 511bf215546Sopenharmony_ci } 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_ci if (dbg_no_tiling) { 514bf215546Sopenharmony_ci return; 515bf215546Sopenharmony_ci } 516bf215546Sopenharmony_ci 517bf215546Sopenharmony_ci /* Set macrotiling. */ 518bf215546Sopenharmony_ci if (r300_texture_macro_switch(tex, 0, rv350_mode, DIM_WIDTH) && 519bf215546Sopenharmony_ci r300_texture_macro_switch(tex, 0, rv350_mode, DIM_HEIGHT)) { 520bf215546Sopenharmony_ci tex->tex.macrotile[0] = RADEON_LAYOUT_TILED; 521bf215546Sopenharmony_ci } 522bf215546Sopenharmony_ci} 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_cistatic void r300_tex_print_info(struct r300_resource *tex, 525bf215546Sopenharmony_ci const char *func) 526bf215546Sopenharmony_ci{ 527bf215546Sopenharmony_ci fprintf(stderr, 528bf215546Sopenharmony_ci "r300: %s: Macro: %s, Micro: %s, Pitch: %i, Dim: %ix%ix%i, " 529bf215546Sopenharmony_ci "LastLevel: %i, Size: %i, Format: %s, Samples: %i\n", 530bf215546Sopenharmony_ci func, 531bf215546Sopenharmony_ci tex->tex.macrotile[0] ? "YES" : " NO", 532bf215546Sopenharmony_ci tex->tex.microtile ? "YES" : " NO", 533bf215546Sopenharmony_ci r300_stride_to_width(tex->b.format, tex->tex.stride_in_bytes[0]), 534bf215546Sopenharmony_ci tex->b.width0, tex->b.height0, tex->b.depth0, 535bf215546Sopenharmony_ci tex->b.last_level, tex->tex.size_in_bytes, 536bf215546Sopenharmony_ci util_format_short_name(tex->b.format), 537bf215546Sopenharmony_ci tex->b.nr_samples); 538bf215546Sopenharmony_ci} 539bf215546Sopenharmony_ci 540bf215546Sopenharmony_civoid r300_texture_desc_init(struct r300_screen *rscreen, 541bf215546Sopenharmony_ci struct r300_resource *tex, 542bf215546Sopenharmony_ci const struct pipe_resource *base) 543bf215546Sopenharmony_ci{ 544bf215546Sopenharmony_ci tex->b.target = base->target; 545bf215546Sopenharmony_ci tex->b.format = base->format; 546bf215546Sopenharmony_ci tex->b.width0 = base->width0; 547bf215546Sopenharmony_ci tex->b.height0 = base->height0; 548bf215546Sopenharmony_ci tex->b.depth0 = base->depth0; 549bf215546Sopenharmony_ci tex->b.array_size = base->array_size; 550bf215546Sopenharmony_ci tex->b.last_level = base->last_level; 551bf215546Sopenharmony_ci tex->b.nr_samples = base->nr_samples; 552bf215546Sopenharmony_ci tex->tex.width0 = base->width0; 553bf215546Sopenharmony_ci tex->tex.height0 = base->height0; 554bf215546Sopenharmony_ci tex->tex.depth0 = base->depth0; 555bf215546Sopenharmony_ci 556bf215546Sopenharmony_ci /* There is a CB memory addressing hardware bug that limits the width 557bf215546Sopenharmony_ci * of the MSAA buffer in some cases in R520. In order to get around it, 558bf215546Sopenharmony_ci * the following code lowers the sample count depending on the format and 559bf215546Sopenharmony_ci * the width. 560bf215546Sopenharmony_ci * 561bf215546Sopenharmony_ci * The only catch is that all MSAA colorbuffers and a zbuffer which are 562bf215546Sopenharmony_ci * supposed to be used together should always be bound together. Only 563bf215546Sopenharmony_ci * then the correct minimum sample count of all bound buffers is used 564bf215546Sopenharmony_ci * for rendering. */ 565bf215546Sopenharmony_ci if (rscreen->caps.is_r500) { 566bf215546Sopenharmony_ci /* FP16 6x MSAA buffers are limited to a width of 1360 pixels. */ 567bf215546Sopenharmony_ci if ((tex->b.format == PIPE_FORMAT_R16G16B16A16_FLOAT || 568bf215546Sopenharmony_ci tex->b.format == PIPE_FORMAT_R16G16B16X16_FLOAT) && 569bf215546Sopenharmony_ci tex->b.nr_samples == 6 && tex->b.width0 > 1360) { 570bf215546Sopenharmony_ci tex->b.nr_samples = 4; 571bf215546Sopenharmony_ci } 572bf215546Sopenharmony_ci 573bf215546Sopenharmony_ci /* FP16 4x MSAA buffers are limited to a width of 2048 pixels. */ 574bf215546Sopenharmony_ci if ((tex->b.format == PIPE_FORMAT_R16G16B16A16_FLOAT || 575bf215546Sopenharmony_ci tex->b.format == PIPE_FORMAT_R16G16B16X16_FLOAT) && 576bf215546Sopenharmony_ci tex->b.nr_samples == 4 && tex->b.width0 > 2048) { 577bf215546Sopenharmony_ci tex->b.nr_samples = 2; 578bf215546Sopenharmony_ci } 579bf215546Sopenharmony_ci } 580bf215546Sopenharmony_ci 581bf215546Sopenharmony_ci /* 32-bit 6x MSAA buffers are limited to a width of 2720 pixels. 582bf215546Sopenharmony_ci * This applies to all R300-R500 cards. */ 583bf215546Sopenharmony_ci if (util_format_get_blocksizebits(tex->b.format) == 32 && 584bf215546Sopenharmony_ci !util_format_is_depth_or_stencil(tex->b.format) && 585bf215546Sopenharmony_ci tex->b.nr_samples == 6 && tex->b.width0 > 2720) { 586bf215546Sopenharmony_ci tex->b.nr_samples = 4; 587bf215546Sopenharmony_ci } 588bf215546Sopenharmony_ci 589bf215546Sopenharmony_ci r300_setup_flags(tex); 590bf215546Sopenharmony_ci 591bf215546Sopenharmony_ci /* Align a 3D NPOT texture to POT. */ 592bf215546Sopenharmony_ci if (base->target == PIPE_TEXTURE_3D && tex->tex.is_npot) { 593bf215546Sopenharmony_ci tex->tex.width0 = util_next_power_of_two(tex->tex.width0); 594bf215546Sopenharmony_ci tex->tex.height0 = util_next_power_of_two(tex->tex.height0); 595bf215546Sopenharmony_ci tex->tex.depth0 = util_next_power_of_two(tex->tex.depth0); 596bf215546Sopenharmony_ci } 597bf215546Sopenharmony_ci 598bf215546Sopenharmony_ci /* Setup tiling. */ 599bf215546Sopenharmony_ci if (tex->tex.microtile == RADEON_LAYOUT_UNKNOWN) { 600bf215546Sopenharmony_ci r300_setup_tiling(rscreen, tex); 601bf215546Sopenharmony_ci } 602bf215546Sopenharmony_ci 603bf215546Sopenharmony_ci r300_setup_cbzb_flags(rscreen, tex); 604bf215546Sopenharmony_ci 605bf215546Sopenharmony_ci /* Setup the miptree description. */ 606bf215546Sopenharmony_ci r300_setup_miptree(rscreen, tex, TRUE); 607bf215546Sopenharmony_ci /* If the required buffer size is larger than the given max size, 608bf215546Sopenharmony_ci * try again without the alignment for the CBZB clear. */ 609bf215546Sopenharmony_ci if (tex->buf && tex->tex.size_in_bytes > tex->buf->size) { 610bf215546Sopenharmony_ci r300_setup_miptree(rscreen, tex, FALSE); 611bf215546Sopenharmony_ci 612bf215546Sopenharmony_ci /* Make sure the buffer we got is large enough. */ 613bf215546Sopenharmony_ci if (tex->tex.size_in_bytes > tex->buf->size) { 614bf215546Sopenharmony_ci fprintf(stderr, 615bf215546Sopenharmony_ci "r300: I got a pre-allocated buffer to use it as a texture " 616bf215546Sopenharmony_ci "storage, but the buffer is too small. I'll use the buffer " 617bf215546Sopenharmony_ci "anyway, because I can't crash here, but it's dangerous. " 618bf215546Sopenharmony_ci "This can be a DDX bug. Got: %"PRIu64"B, Need: %uB, Info:\n", 619bf215546Sopenharmony_ci tex->buf->size, tex->tex.size_in_bytes); 620bf215546Sopenharmony_ci r300_tex_print_info(tex, "texture_desc_init"); 621bf215546Sopenharmony_ci /* Oops, what now. Apps will break if we fail this, 622bf215546Sopenharmony_ci * so just pretend everything's okay. */ 623bf215546Sopenharmony_ci } 624bf215546Sopenharmony_ci } 625bf215546Sopenharmony_ci 626bf215546Sopenharmony_ci r300_setup_hyperz_properties(rscreen, tex); 627bf215546Sopenharmony_ci r300_setup_cmask_properties(rscreen, tex); 628bf215546Sopenharmony_ci 629bf215546Sopenharmony_ci if (SCREEN_DBG_ON(rscreen, DBG_TEX)) 630bf215546Sopenharmony_ci r300_tex_print_info(tex, "texture_desc_init"); 631bf215546Sopenharmony_ci} 632bf215546Sopenharmony_ci 633bf215546Sopenharmony_ciunsigned r300_texture_get_offset(struct r300_resource *tex, 634bf215546Sopenharmony_ci unsigned level, unsigned layer) 635bf215546Sopenharmony_ci{ 636bf215546Sopenharmony_ci unsigned offset = tex->tex.offset_in_bytes[level]; 637bf215546Sopenharmony_ci 638bf215546Sopenharmony_ci switch (tex->b.target) { 639bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: 640bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 641bf215546Sopenharmony_ci return offset + layer * tex->tex.layer_size_in_bytes[level]; 642bf215546Sopenharmony_ci 643bf215546Sopenharmony_ci default: 644bf215546Sopenharmony_ci assert(layer == 0); 645bf215546Sopenharmony_ci return offset; 646bf215546Sopenharmony_ci } 647bf215546Sopenharmony_ci} 648