1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2006 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16bf215546Sopenharmony_ci * of the Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci/* 28bf215546Sopenharmony_ci * Authors: 29bf215546Sopenharmony_ci * Keith Whitwell <keithw@vmware.com> 30bf215546Sopenharmony_ci * Michel Dänzer <daenzer@vmware.com> 31bf215546Sopenharmony_ci */ 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#include "pipe/p_context.h" 34bf215546Sopenharmony_ci#include "pipe/p_defines.h" 35bf215546Sopenharmony_ci#include "pipe/p_state.h" 36bf215546Sopenharmony_ci#include "util/format/u_format.h" 37bf215546Sopenharmony_ci#include "util/u_inlines.h" 38bf215546Sopenharmony_ci#include "util/u_math.h" 39bf215546Sopenharmony_ci#include "util/u_memory.h" 40bf215546Sopenharmony_ci#include "util/u_rect.h" 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci#include "i915_context.h" 43bf215546Sopenharmony_ci#include "i915_debug.h" 44bf215546Sopenharmony_ci#include "i915_resource.h" 45bf215546Sopenharmony_ci#include "i915_screen.h" 46bf215546Sopenharmony_ci#include "i915_winsys.h" 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci#define DEBUG_TEXTURES 0 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci/* 51bf215546Sopenharmony_ci * Helper function and arrays 52bf215546Sopenharmony_ci */ 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci/** 55bf215546Sopenharmony_ci * Initial offset for Cube map. 56bf215546Sopenharmony_ci */ 57bf215546Sopenharmony_cistatic const int initial_offsets[6][2] = { 58bf215546Sopenharmony_ci [PIPE_TEX_FACE_POS_X] = {0, 0}, [PIPE_TEX_FACE_POS_Y] = {1, 0}, 59bf215546Sopenharmony_ci [PIPE_TEX_FACE_POS_Z] = {1, 1}, [PIPE_TEX_FACE_NEG_X] = {0, 2}, 60bf215546Sopenharmony_ci [PIPE_TEX_FACE_NEG_Y] = {1, 2}, [PIPE_TEX_FACE_NEG_Z] = {1, 3}, 61bf215546Sopenharmony_ci}; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci/** 64bf215546Sopenharmony_ci * Step offsets for Cube map. 65bf215546Sopenharmony_ci */ 66bf215546Sopenharmony_cistatic const int step_offsets[6][2] = { 67bf215546Sopenharmony_ci [PIPE_TEX_FACE_POS_X] = {0, 2}, [PIPE_TEX_FACE_POS_Y] = {-1, 2}, 68bf215546Sopenharmony_ci [PIPE_TEX_FACE_POS_Z] = {-1, 1}, [PIPE_TEX_FACE_NEG_X] = {0, 2}, 69bf215546Sopenharmony_ci [PIPE_TEX_FACE_NEG_Y] = {-1, 2}, [PIPE_TEX_FACE_NEG_Z] = {-1, 1}, 70bf215546Sopenharmony_ci}; 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci/** 73bf215546Sopenharmony_ci * For compressed level 2 74bf215546Sopenharmony_ci */ 75bf215546Sopenharmony_cistatic const int bottom_offsets[6] = { 76bf215546Sopenharmony_ci [PIPE_TEX_FACE_POS_X] = 16 + 0 * 8, [PIPE_TEX_FACE_POS_Y] = 16 + 1 * 8, 77bf215546Sopenharmony_ci [PIPE_TEX_FACE_POS_Z] = 16 + 2 * 8, [PIPE_TEX_FACE_NEG_X] = 16 + 3 * 8, 78bf215546Sopenharmony_ci [PIPE_TEX_FACE_NEG_Y] = 16 + 4 * 8, [PIPE_TEX_FACE_NEG_Z] = 16 + 5 * 8, 79bf215546Sopenharmony_ci}; 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_cistatic inline unsigned 82bf215546Sopenharmony_cialign_nblocksx(enum pipe_format format, unsigned width, unsigned align_to) 83bf215546Sopenharmony_ci{ 84bf215546Sopenharmony_ci return align(util_format_get_nblocksx(format, width), align_to); 85bf215546Sopenharmony_ci} 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_cistatic inline unsigned 88bf215546Sopenharmony_cialign_nblocksy(enum pipe_format format, unsigned width, unsigned align_to) 89bf215546Sopenharmony_ci{ 90bf215546Sopenharmony_ci return align(util_format_get_nblocksy(format, width), align_to); 91bf215546Sopenharmony_ci} 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_cistatic inline unsigned 94bf215546Sopenharmony_ciget_pot_stride(enum pipe_format format, unsigned width) 95bf215546Sopenharmony_ci{ 96bf215546Sopenharmony_ci return util_next_power_of_two(util_format_get_stride(format, width)); 97bf215546Sopenharmony_ci} 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_cistatic inline const char * 100bf215546Sopenharmony_ciget_tiling_string(enum i915_winsys_buffer_tile tile) 101bf215546Sopenharmony_ci{ 102bf215546Sopenharmony_ci switch (tile) { 103bf215546Sopenharmony_ci case I915_TILE_NONE: 104bf215546Sopenharmony_ci return "none"; 105bf215546Sopenharmony_ci case I915_TILE_X: 106bf215546Sopenharmony_ci return "x"; 107bf215546Sopenharmony_ci case I915_TILE_Y: 108bf215546Sopenharmony_ci return "y"; 109bf215546Sopenharmony_ci default: 110bf215546Sopenharmony_ci assert(false); 111bf215546Sopenharmony_ci return "?"; 112bf215546Sopenharmony_ci } 113bf215546Sopenharmony_ci} 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci/* 116bf215546Sopenharmony_ci * More advanced helper funcs 117bf215546Sopenharmony_ci */ 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_cistatic void 120bf215546Sopenharmony_cii915_texture_set_level_info(struct i915_texture *tex, unsigned level, 121bf215546Sopenharmony_ci unsigned nr_images) 122bf215546Sopenharmony_ci{ 123bf215546Sopenharmony_ci assert(level < ARRAY_SIZE(tex->nr_images)); 124bf215546Sopenharmony_ci assert(nr_images); 125bf215546Sopenharmony_ci assert(!tex->image_offset[level]); 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci tex->nr_images[level] = nr_images; 128bf215546Sopenharmony_ci tex->image_offset[level] = MALLOC(nr_images * sizeof(struct offset_pair)); 129bf215546Sopenharmony_ci tex->image_offset[level][0].nblocksx = 0; 130bf215546Sopenharmony_ci tex->image_offset[level][0].nblocksy = 0; 131bf215546Sopenharmony_ci} 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ciunsigned 134bf215546Sopenharmony_cii915_texture_offset(const struct i915_texture *tex, unsigned level, 135bf215546Sopenharmony_ci unsigned layer) 136bf215546Sopenharmony_ci{ 137bf215546Sopenharmony_ci unsigned x, y; 138bf215546Sopenharmony_ci x = tex->image_offset[level][layer].nblocksx * 139bf215546Sopenharmony_ci util_format_get_blocksize(tex->b.format); 140bf215546Sopenharmony_ci y = tex->image_offset[level][layer].nblocksy; 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci return y * tex->stride + x; 143bf215546Sopenharmony_ci} 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_cistatic void 146bf215546Sopenharmony_cii915_texture_set_image_offset(struct i915_texture *tex, unsigned level, 147bf215546Sopenharmony_ci unsigned img, unsigned nblocksx, 148bf215546Sopenharmony_ci unsigned nblocksy) 149bf215546Sopenharmony_ci{ 150bf215546Sopenharmony_ci /* for the first image and level make sure offset is zero */ 151bf215546Sopenharmony_ci assert(!(img == 0 && level == 0) || (nblocksx == 0 && nblocksy == 0)); 152bf215546Sopenharmony_ci assert(img < tex->nr_images[level]); 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci tex->image_offset[level][img].nblocksx = nblocksx; 155bf215546Sopenharmony_ci tex->image_offset[level][img].nblocksy = nblocksy; 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci#if DEBUG_TEXTURES 158bf215546Sopenharmony_ci debug_printf("%s: %p level %u, img %u (%u, %u)\n", __FUNCTION__, tex, level, 159bf215546Sopenharmony_ci img, x, y); 160bf215546Sopenharmony_ci#endif 161bf215546Sopenharmony_ci} 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_cistatic enum i915_winsys_buffer_tile 164bf215546Sopenharmony_cii915_texture_tiling(struct i915_screen *is, struct i915_texture *tex) 165bf215546Sopenharmony_ci{ 166bf215546Sopenharmony_ci if (!is->debug.tiling) 167bf215546Sopenharmony_ci return I915_TILE_NONE; 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci if (tex->b.target == PIPE_TEXTURE_1D) 170bf215546Sopenharmony_ci return I915_TILE_NONE; 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci if (util_format_is_compressed(tex->b.format)) 173bf215546Sopenharmony_ci return I915_TILE_X; 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci if (is->debug.use_blitter) 176bf215546Sopenharmony_ci return I915_TILE_X; 177bf215546Sopenharmony_ci else 178bf215546Sopenharmony_ci return I915_TILE_Y; 179bf215546Sopenharmony_ci} 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci/* 182bf215546Sopenharmony_ci * Shared layout functions 183bf215546Sopenharmony_ci */ 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci/** 186bf215546Sopenharmony_ci * Special case to deal with scanout textures. 187bf215546Sopenharmony_ci */ 188bf215546Sopenharmony_cistatic bool 189bf215546Sopenharmony_cii9x5_scanout_layout(struct i915_texture *tex) 190bf215546Sopenharmony_ci{ 191bf215546Sopenharmony_ci struct pipe_resource *pt = &tex->b; 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci if (pt->last_level > 0 || util_format_get_blocksize(pt->format) != 4) 194bf215546Sopenharmony_ci return false; 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci if (pt->width0 >= 240) { 197bf215546Sopenharmony_ci tex->stride = align(util_format_get_stride(pt->format, pt->width0), 64); 198bf215546Sopenharmony_ci tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8); 199bf215546Sopenharmony_ci tex->tiling = I915_TILE_X; 200bf215546Sopenharmony_ci /* special case for cursors */ 201bf215546Sopenharmony_ci } else if (pt->width0 == 64 && pt->height0 == 64) { 202bf215546Sopenharmony_ci tex->stride = get_pot_stride(pt->format, pt->width0); 203bf215546Sopenharmony_ci tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8); 204bf215546Sopenharmony_ci } else { 205bf215546Sopenharmony_ci return false; 206bf215546Sopenharmony_ci } 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci i915_texture_set_level_info(tex, 0, 1); 209bf215546Sopenharmony_ci i915_texture_set_image_offset(tex, 0, 0, 0, 0); 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci#if DEBUG_TEXTURE 213bf215546Sopenharmony_ci debug_printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__, 214bf215546Sopenharmony_ci pt->width0, pt->height0, util_format_get_blocksize(pt->format), 215bf215546Sopenharmony_ci tex->stride, tex->total_nblocksy, 216bf215546Sopenharmony_ci tex->stride * tex->total_nblocksy); 217bf215546Sopenharmony_ci#endif 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci return true; 220bf215546Sopenharmony_ci} 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci/** 223bf215546Sopenharmony_ci * Special case to deal with shared textures. 224bf215546Sopenharmony_ci */ 225bf215546Sopenharmony_cistatic bool 226bf215546Sopenharmony_cii9x5_display_target_layout(struct i915_texture *tex) 227bf215546Sopenharmony_ci{ 228bf215546Sopenharmony_ci struct pipe_resource *pt = &tex->b; 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci if (pt->last_level > 0 || util_format_get_blocksize(pt->format) != 4) 231bf215546Sopenharmony_ci return false; 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci /* fallback to normal textures for small textures */ 234bf215546Sopenharmony_ci if (pt->width0 < 240) 235bf215546Sopenharmony_ci return false; 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci i915_texture_set_level_info(tex, 0, 1); 238bf215546Sopenharmony_ci i915_texture_set_image_offset(tex, 0, 0, 0, 0); 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci tex->stride = align(util_format_get_stride(pt->format, pt->width0), 64); 241bf215546Sopenharmony_ci tex->total_nblocksy = align_nblocksy(pt->format, pt->height0, 8); 242bf215546Sopenharmony_ci tex->tiling = I915_TILE_X; 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci#if DEBUG_TEXTURE 245bf215546Sopenharmony_ci debug_printf("%s size: %d,%d,%d offset %d,%d (0x%x)\n", __FUNCTION__, 246bf215546Sopenharmony_ci pt->width0, pt->height0, util_format_get_blocksize(pt->format), 247bf215546Sopenharmony_ci tex->stride, tex->total_nblocksy, 248bf215546Sopenharmony_ci tex->stride * tex->total_nblocksy); 249bf215546Sopenharmony_ci#endif 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci return true; 252bf215546Sopenharmony_ci} 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci/** 255bf215546Sopenharmony_ci * Helper function for special layouts 256bf215546Sopenharmony_ci */ 257bf215546Sopenharmony_cistatic bool 258bf215546Sopenharmony_cii9x5_special_layout(struct i915_texture *tex) 259bf215546Sopenharmony_ci{ 260bf215546Sopenharmony_ci struct pipe_resource *pt = &tex->b; 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci /* Scanouts needs special care */ 263bf215546Sopenharmony_ci if (pt->bind & PIPE_BIND_SCANOUT) 264bf215546Sopenharmony_ci if (i9x5_scanout_layout(tex)) 265bf215546Sopenharmony_ci return true; 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci /* Shared buffers needs to be compatible with X servers 268bf215546Sopenharmony_ci * 269bf215546Sopenharmony_ci * XXX: need a better name than shared for this if it is to be part 270bf215546Sopenharmony_ci * of core gallium, and probably move the flag to resource.flags, 271bf215546Sopenharmony_ci * rather than bindings. 272bf215546Sopenharmony_ci */ 273bf215546Sopenharmony_ci if (pt->bind & (PIPE_BIND_SHARED | PIPE_BIND_DISPLAY_TARGET)) 274bf215546Sopenharmony_ci if (i9x5_display_target_layout(tex)) 275bf215546Sopenharmony_ci return true; 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ci return false; 278bf215546Sopenharmony_ci} 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_ci/** 281bf215546Sopenharmony_ci * Cube layout used on i915 and for non-compressed textures on i945. 282bf215546Sopenharmony_ci * 283bf215546Sopenharmony_ci * Hardware layout looks like: 284bf215546Sopenharmony_ci * 285bf215546Sopenharmony_ci * +-------+-------+ 286bf215546Sopenharmony_ci * | | | 287bf215546Sopenharmony_ci * | | | 288bf215546Sopenharmony_ci * | | | 289bf215546Sopenharmony_ci * | +x | +y | 290bf215546Sopenharmony_ci * | | | 291bf215546Sopenharmony_ci * | | | 292bf215546Sopenharmony_ci * | | | 293bf215546Sopenharmony_ci * | | | 294bf215546Sopenharmony_ci * +---+---+-------+ 295bf215546Sopenharmony_ci * | | | | 296bf215546Sopenharmony_ci * | +x| +y| | 297bf215546Sopenharmony_ci * | | | | 298bf215546Sopenharmony_ci * | | | | 299bf215546Sopenharmony_ci * +-+-+---+ +z | 300bf215546Sopenharmony_ci * | | | | | 301bf215546Sopenharmony_ci * +-+-+ +z| | 302bf215546Sopenharmony_ci * | | | | 303bf215546Sopenharmony_ci * +-+-+---+-------+ 304bf215546Sopenharmony_ci * | | | 305bf215546Sopenharmony_ci * | | | 306bf215546Sopenharmony_ci * | | | 307bf215546Sopenharmony_ci * | -x | -y | 308bf215546Sopenharmony_ci * | | | 309bf215546Sopenharmony_ci * | | | 310bf215546Sopenharmony_ci * | | | 311bf215546Sopenharmony_ci * | | | 312bf215546Sopenharmony_ci * +---+---+-------+ 313bf215546Sopenharmony_ci * | | | | 314bf215546Sopenharmony_ci * | -x| -y| | 315bf215546Sopenharmony_ci * | | | | 316bf215546Sopenharmony_ci * | | | | 317bf215546Sopenharmony_ci * +-+-+---+ -z | 318bf215546Sopenharmony_ci * | | | | | 319bf215546Sopenharmony_ci * +-+-+ -z| | 320bf215546Sopenharmony_ci * | | | | 321bf215546Sopenharmony_ci * +-+---+-------+ 322bf215546Sopenharmony_ci * 323bf215546Sopenharmony_ci */ 324bf215546Sopenharmony_cistatic void 325bf215546Sopenharmony_cii9x5_texture_layout_cube(struct i915_texture *tex) 326bf215546Sopenharmony_ci{ 327bf215546Sopenharmony_ci struct pipe_resource *pt = &tex->b; 328bf215546Sopenharmony_ci unsigned width = util_next_power_of_two(pt->width0); 329bf215546Sopenharmony_ci const unsigned nblocks = util_format_get_nblocksx(pt->format, width); 330bf215546Sopenharmony_ci unsigned level; 331bf215546Sopenharmony_ci unsigned face; 332bf215546Sopenharmony_ci 333bf215546Sopenharmony_ci assert(pt->width0 == pt->height0); /* cubemap images are square */ 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_ci /* double pitch for cube layouts */ 336bf215546Sopenharmony_ci tex->stride = align(nblocks * util_format_get_blocksize(pt->format) * 2, 4); 337bf215546Sopenharmony_ci tex->total_nblocksy = nblocks * 4; 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_ci for (level = 0; level <= pt->last_level; level++) 340bf215546Sopenharmony_ci i915_texture_set_level_info(tex, level, 6); 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci for (face = 0; face < 6; face++) { 343bf215546Sopenharmony_ci unsigned x = initial_offsets[face][0] * nblocks; 344bf215546Sopenharmony_ci unsigned y = initial_offsets[face][1] * nblocks; 345bf215546Sopenharmony_ci unsigned d = nblocks; 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci for (level = 0; level <= pt->last_level; level++) { 348bf215546Sopenharmony_ci i915_texture_set_image_offset(tex, level, face, x, y); 349bf215546Sopenharmony_ci d >>= 1; 350bf215546Sopenharmony_ci x += step_offsets[face][0] * d; 351bf215546Sopenharmony_ci y += step_offsets[face][1] * d; 352bf215546Sopenharmony_ci } 353bf215546Sopenharmony_ci } 354bf215546Sopenharmony_ci} 355bf215546Sopenharmony_ci 356bf215546Sopenharmony_ci/* 357bf215546Sopenharmony_ci * i915 layout functions 358bf215546Sopenharmony_ci */ 359bf215546Sopenharmony_ci 360bf215546Sopenharmony_cistatic void 361bf215546Sopenharmony_cii915_texture_layout_2d(struct i915_texture *tex) 362bf215546Sopenharmony_ci{ 363bf215546Sopenharmony_ci struct pipe_resource *pt = &tex->b; 364bf215546Sopenharmony_ci unsigned level; 365bf215546Sopenharmony_ci unsigned width = util_next_power_of_two(pt->width0); 366bf215546Sopenharmony_ci unsigned height = util_next_power_of_two(pt->height0); 367bf215546Sopenharmony_ci unsigned nblocksy = util_format_get_nblocksy(pt->format, width); 368bf215546Sopenharmony_ci unsigned align_y = 2; 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci if (util_format_is_compressed(pt->format)) 371bf215546Sopenharmony_ci align_y = 1; 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_ci tex->stride = align(util_format_get_stride(pt->format, width), 4); 374bf215546Sopenharmony_ci tex->total_nblocksy = 0; 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci for (level = 0; level <= pt->last_level; level++) { 377bf215546Sopenharmony_ci i915_texture_set_level_info(tex, level, 1); 378bf215546Sopenharmony_ci i915_texture_set_image_offset(tex, level, 0, 0, tex->total_nblocksy); 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci tex->total_nblocksy += nblocksy; 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci width = u_minify(width, 1); 383bf215546Sopenharmony_ci height = u_minify(height, 1); 384bf215546Sopenharmony_ci nblocksy = align_nblocksy(pt->format, height, align_y); 385bf215546Sopenharmony_ci } 386bf215546Sopenharmony_ci} 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_cistatic void 389bf215546Sopenharmony_cii915_texture_layout_3d(struct i915_texture *tex) 390bf215546Sopenharmony_ci{ 391bf215546Sopenharmony_ci struct pipe_resource *pt = &tex->b; 392bf215546Sopenharmony_ci unsigned level; 393bf215546Sopenharmony_ci 394bf215546Sopenharmony_ci unsigned width = util_next_power_of_two(pt->width0); 395bf215546Sopenharmony_ci unsigned height = util_next_power_of_two(pt->height0); 396bf215546Sopenharmony_ci unsigned depth = util_next_power_of_two(pt->depth0); 397bf215546Sopenharmony_ci unsigned nblocksy = util_format_get_nblocksy(pt->format, height); 398bf215546Sopenharmony_ci unsigned stack_nblocksy = 0; 399bf215546Sopenharmony_ci 400bf215546Sopenharmony_ci /* Calculate the size of a single slice. 401bf215546Sopenharmony_ci */ 402bf215546Sopenharmony_ci tex->stride = align(util_format_get_stride(pt->format, width), 4); 403bf215546Sopenharmony_ci 404bf215546Sopenharmony_ci /* XXX: hardware expects/requires 9 levels at minimum. 405bf215546Sopenharmony_ci */ 406bf215546Sopenharmony_ci for (level = 0; level <= MAX2(8, pt->last_level); level++) { 407bf215546Sopenharmony_ci i915_texture_set_level_info(tex, level, depth); 408bf215546Sopenharmony_ci 409bf215546Sopenharmony_ci stack_nblocksy += MAX2(2, nblocksy); 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci width = u_minify(width, 1); 412bf215546Sopenharmony_ci height = u_minify(height, 1); 413bf215546Sopenharmony_ci nblocksy = util_format_get_nblocksy(pt->format, height); 414bf215546Sopenharmony_ci } 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci /* Fixup depth image_offsets: 417bf215546Sopenharmony_ci */ 418bf215546Sopenharmony_ci for (level = 0; level <= pt->last_level; level++) { 419bf215546Sopenharmony_ci unsigned i; 420bf215546Sopenharmony_ci for (i = 0; i < depth; i++) 421bf215546Sopenharmony_ci i915_texture_set_image_offset(tex, level, i, 0, i * stack_nblocksy); 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci depth = u_minify(depth, 1); 424bf215546Sopenharmony_ci } 425bf215546Sopenharmony_ci 426bf215546Sopenharmony_ci /* Multiply slice size by texture depth for total size. It's 427bf215546Sopenharmony_ci * remarkable how wasteful of memory the i915 texture layouts 428bf215546Sopenharmony_ci * are. They are largely fixed in the i945. 429bf215546Sopenharmony_ci */ 430bf215546Sopenharmony_ci tex->total_nblocksy = stack_nblocksy * util_next_power_of_two(pt->depth0); 431bf215546Sopenharmony_ci} 432bf215546Sopenharmony_ci 433bf215546Sopenharmony_cistatic bool 434bf215546Sopenharmony_cii915_texture_layout(struct i915_texture *tex) 435bf215546Sopenharmony_ci{ 436bf215546Sopenharmony_ci switch (tex->b.target) { 437bf215546Sopenharmony_ci case PIPE_TEXTURE_1D: 438bf215546Sopenharmony_ci case PIPE_TEXTURE_2D: 439bf215546Sopenharmony_ci case PIPE_TEXTURE_RECT: 440bf215546Sopenharmony_ci if (!i9x5_special_layout(tex)) 441bf215546Sopenharmony_ci i915_texture_layout_2d(tex); 442bf215546Sopenharmony_ci break; 443bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: 444bf215546Sopenharmony_ci i915_texture_layout_3d(tex); 445bf215546Sopenharmony_ci break; 446bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 447bf215546Sopenharmony_ci i9x5_texture_layout_cube(tex); 448bf215546Sopenharmony_ci break; 449bf215546Sopenharmony_ci default: 450bf215546Sopenharmony_ci assert(0); 451bf215546Sopenharmony_ci return false; 452bf215546Sopenharmony_ci } 453bf215546Sopenharmony_ci 454bf215546Sopenharmony_ci return true; 455bf215546Sopenharmony_ci} 456bf215546Sopenharmony_ci 457bf215546Sopenharmony_ci/* 458bf215546Sopenharmony_ci * i945 layout functions 459bf215546Sopenharmony_ci */ 460bf215546Sopenharmony_ci 461bf215546Sopenharmony_cistatic void 462bf215546Sopenharmony_cii945_texture_layout_2d(struct i915_texture *tex) 463bf215546Sopenharmony_ci{ 464bf215546Sopenharmony_ci struct pipe_resource *pt = &tex->b; 465bf215546Sopenharmony_ci int align_x = 4, align_y = 2; 466bf215546Sopenharmony_ci unsigned level; 467bf215546Sopenharmony_ci unsigned x = 0; 468bf215546Sopenharmony_ci unsigned y = 0; 469bf215546Sopenharmony_ci unsigned width = util_next_power_of_two(pt->width0); 470bf215546Sopenharmony_ci unsigned height = util_next_power_of_two(pt->height0); 471bf215546Sopenharmony_ci unsigned nblocksx = util_format_get_nblocksx(pt->format, width); 472bf215546Sopenharmony_ci unsigned nblocksy = util_format_get_nblocksy(pt->format, height); 473bf215546Sopenharmony_ci 474bf215546Sopenharmony_ci if (util_format_is_compressed(pt->format)) { 475bf215546Sopenharmony_ci align_x = 1; 476bf215546Sopenharmony_ci align_y = 1; 477bf215546Sopenharmony_ci } 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_ci tex->stride = align(util_format_get_stride(pt->format, width), 4); 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci /* May need to adjust pitch to accommodate the placement of 482bf215546Sopenharmony_ci * the 2nd mipmap level. This occurs when the alignment 483bf215546Sopenharmony_ci * constraints of mipmap placement push the right edge of the 484bf215546Sopenharmony_ci * 2nd mipmap level out past the width of its parent. 485bf215546Sopenharmony_ci */ 486bf215546Sopenharmony_ci if (pt->last_level > 0) { 487bf215546Sopenharmony_ci unsigned mip1_nblocksx = 488bf215546Sopenharmony_ci align_nblocksx(pt->format, u_minify(width, 1), align_x) + 489bf215546Sopenharmony_ci util_format_get_nblocksx(pt->format, u_minify(width, 2)); 490bf215546Sopenharmony_ci 491bf215546Sopenharmony_ci if (mip1_nblocksx > nblocksx) 492bf215546Sopenharmony_ci tex->stride = mip1_nblocksx * util_format_get_blocksize(pt->format); 493bf215546Sopenharmony_ci } 494bf215546Sopenharmony_ci 495bf215546Sopenharmony_ci /* Pitch must be a whole number of dwords 496bf215546Sopenharmony_ci */ 497bf215546Sopenharmony_ci tex->stride = align(tex->stride, 64); 498bf215546Sopenharmony_ci tex->total_nblocksy = 0; 499bf215546Sopenharmony_ci 500bf215546Sopenharmony_ci for (level = 0; level <= pt->last_level; level++) { 501bf215546Sopenharmony_ci i915_texture_set_level_info(tex, level, 1); 502bf215546Sopenharmony_ci i915_texture_set_image_offset(tex, level, 0, x, y); 503bf215546Sopenharmony_ci 504bf215546Sopenharmony_ci /* Because the images are packed better, the final offset 505bf215546Sopenharmony_ci * might not be the maximal one: 506bf215546Sopenharmony_ci */ 507bf215546Sopenharmony_ci tex->total_nblocksy = MAX2(tex->total_nblocksy, y + nblocksy); 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci /* Layout_below: step right after second mipmap level. 510bf215546Sopenharmony_ci */ 511bf215546Sopenharmony_ci if (level == 1) { 512bf215546Sopenharmony_ci x += nblocksx; 513bf215546Sopenharmony_ci } else { 514bf215546Sopenharmony_ci y += nblocksy; 515bf215546Sopenharmony_ci } 516bf215546Sopenharmony_ci 517bf215546Sopenharmony_ci width = u_minify(width, 1); 518bf215546Sopenharmony_ci height = u_minify(height, 1); 519bf215546Sopenharmony_ci nblocksx = align_nblocksx(pt->format, width, align_x); 520bf215546Sopenharmony_ci nblocksy = align_nblocksy(pt->format, height, align_y); 521bf215546Sopenharmony_ci } 522bf215546Sopenharmony_ci} 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_cistatic void 525bf215546Sopenharmony_cii945_texture_layout_3d(struct i915_texture *tex) 526bf215546Sopenharmony_ci{ 527bf215546Sopenharmony_ci struct pipe_resource *pt = &tex->b; 528bf215546Sopenharmony_ci unsigned width = util_next_power_of_two(pt->width0); 529bf215546Sopenharmony_ci unsigned height = util_next_power_of_two(pt->height0); 530bf215546Sopenharmony_ci unsigned depth = util_next_power_of_two(pt->depth0); 531bf215546Sopenharmony_ci unsigned nblocksy = util_format_get_nblocksy(pt->format, height); 532bf215546Sopenharmony_ci unsigned pack_x_pitch, pack_x_nr; 533bf215546Sopenharmony_ci unsigned pack_y_pitch; 534bf215546Sopenharmony_ci unsigned level; 535bf215546Sopenharmony_ci 536bf215546Sopenharmony_ci tex->stride = align(util_format_get_stride(pt->format, width), 4); 537bf215546Sopenharmony_ci tex->total_nblocksy = 0; 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ci pack_y_pitch = MAX2(nblocksy, 2); 540bf215546Sopenharmony_ci pack_x_pitch = tex->stride / util_format_get_blocksize(pt->format); 541bf215546Sopenharmony_ci pack_x_nr = 1; 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_ci for (level = 0; level <= pt->last_level; level++) { 544bf215546Sopenharmony_ci int x = 0; 545bf215546Sopenharmony_ci int y = 0; 546bf215546Sopenharmony_ci unsigned q, j; 547bf215546Sopenharmony_ci 548bf215546Sopenharmony_ci i915_texture_set_level_info(tex, level, depth); 549bf215546Sopenharmony_ci 550bf215546Sopenharmony_ci for (q = 0; q < depth;) { 551bf215546Sopenharmony_ci for (j = 0; j < pack_x_nr && q < depth; j++, q++) { 552bf215546Sopenharmony_ci i915_texture_set_image_offset(tex, level, q, x, 553bf215546Sopenharmony_ci y + tex->total_nblocksy); 554bf215546Sopenharmony_ci x += pack_x_pitch; 555bf215546Sopenharmony_ci } 556bf215546Sopenharmony_ci 557bf215546Sopenharmony_ci x = 0; 558bf215546Sopenharmony_ci y += pack_y_pitch; 559bf215546Sopenharmony_ci } 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci tex->total_nblocksy += y; 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_ci if (pack_x_pitch > 4) { 564bf215546Sopenharmony_ci pack_x_pitch >>= 1; 565bf215546Sopenharmony_ci pack_x_nr <<= 1; 566bf215546Sopenharmony_ci assert(pack_x_pitch * pack_x_nr * 567bf215546Sopenharmony_ci util_format_get_blocksize(pt->format) <= 568bf215546Sopenharmony_ci tex->stride); 569bf215546Sopenharmony_ci } 570bf215546Sopenharmony_ci 571bf215546Sopenharmony_ci if (pack_y_pitch > 2) { 572bf215546Sopenharmony_ci pack_y_pitch >>= 1; 573bf215546Sopenharmony_ci } 574bf215546Sopenharmony_ci 575bf215546Sopenharmony_ci width = u_minify(width, 1); 576bf215546Sopenharmony_ci height = u_minify(height, 1); 577bf215546Sopenharmony_ci depth = u_minify(depth, 1); 578bf215546Sopenharmony_ci nblocksy = util_format_get_nblocksy(pt->format, height); 579bf215546Sopenharmony_ci } 580bf215546Sopenharmony_ci} 581bf215546Sopenharmony_ci 582bf215546Sopenharmony_ci/** 583bf215546Sopenharmony_ci * Compressed cube texture map layout for i945 and later. 584bf215546Sopenharmony_ci * 585bf215546Sopenharmony_ci * The hardware layout looks like the 830-915 layout, except for the small 586bf215546Sopenharmony_ci * sizes. A zoomed in view of the layout for 945 is: 587bf215546Sopenharmony_ci * 588bf215546Sopenharmony_ci * +-------+-------+ 589bf215546Sopenharmony_ci * | 8x8 | 8x8 | 590bf215546Sopenharmony_ci * | | | 591bf215546Sopenharmony_ci * | | | 592bf215546Sopenharmony_ci * | +x | +y | 593bf215546Sopenharmony_ci * | | | 594bf215546Sopenharmony_ci * | | | 595bf215546Sopenharmony_ci * | | | 596bf215546Sopenharmony_ci * | | | 597bf215546Sopenharmony_ci * +---+---+-------+ 598bf215546Sopenharmony_ci * |4x4| | 8x8 | 599bf215546Sopenharmony_ci * | +x| | | 600bf215546Sopenharmony_ci * | | | | 601bf215546Sopenharmony_ci * | | | | 602bf215546Sopenharmony_ci * +---+ | +z | 603bf215546Sopenharmony_ci * |4x4| | | 604bf215546Sopenharmony_ci * | +y| | | 605bf215546Sopenharmony_ci * | | | | 606bf215546Sopenharmony_ci * +---+ +-------+ 607bf215546Sopenharmony_ci * 608bf215546Sopenharmony_ci * ... 609bf215546Sopenharmony_ci * 610bf215546Sopenharmony_ci * +-------+-------+ 611bf215546Sopenharmony_ci * | 8x8 | 8x8 | 612bf215546Sopenharmony_ci * | | | 613bf215546Sopenharmony_ci * | | | 614bf215546Sopenharmony_ci * | -x | -y | 615bf215546Sopenharmony_ci * | | | 616bf215546Sopenharmony_ci * | | | 617bf215546Sopenharmony_ci * | | | 618bf215546Sopenharmony_ci * | | | 619bf215546Sopenharmony_ci * +---+---+-------+ 620bf215546Sopenharmony_ci * |4x4| | 8x8 | 621bf215546Sopenharmony_ci * | -x| | | 622bf215546Sopenharmony_ci * | | | | 623bf215546Sopenharmony_ci * | | | | 624bf215546Sopenharmony_ci * +---+ | -z | 625bf215546Sopenharmony_ci * |4x4| | | 626bf215546Sopenharmony_ci * | -y| | | 627bf215546Sopenharmony_ci * | | | | 628bf215546Sopenharmony_ci * +---+ +---+---+---+---+---+---+---+---+---+ 629bf215546Sopenharmony_ci * |4x4| |4x4| |2x2| |2x2| |2x2| |2x2| 630bf215546Sopenharmony_ci * | +z| | -z| | +x| | +y| | +z| | -x| ... 631bf215546Sopenharmony_ci * | | | | | | | | | | | | 632bf215546Sopenharmony_ci * +---+ +---+ +---+ +---+ +---+ +---+ 633bf215546Sopenharmony_ci * 634bf215546Sopenharmony_ci * The bottom row continues with the remaining 2x2 then the 1x1 mip contents 635bf215546Sopenharmony_ci * in order, with each of them aligned to a 8x8 block boundary. Thus, for 636bf215546Sopenharmony_ci * 32x32 cube maps and smaller, the bottom row layout is going to dictate the 637bf215546Sopenharmony_ci * pitch of the tree. For a tree with 4x4 images, the pitch is at least 638bf215546Sopenharmony_ci * 14 * 8 = 112 texels, for 2x2 it is at least 12 * 8 texels, and for 1x1 639bf215546Sopenharmony_ci * it is 6 * 8 texels. 640bf215546Sopenharmony_ci */ 641bf215546Sopenharmony_cistatic void 642bf215546Sopenharmony_cii945_texture_layout_cube(struct i915_texture *tex) 643bf215546Sopenharmony_ci{ 644bf215546Sopenharmony_ci struct pipe_resource *pt = &tex->b; 645bf215546Sopenharmony_ci unsigned width = util_next_power_of_two(pt->width0); 646bf215546Sopenharmony_ci const unsigned nblocks = util_format_get_nblocksx(pt->format, width); 647bf215546Sopenharmony_ci const unsigned dim = width; 648bf215546Sopenharmony_ci unsigned level; 649bf215546Sopenharmony_ci unsigned face; 650bf215546Sopenharmony_ci 651bf215546Sopenharmony_ci assert(pt->width0 == pt->height0); /* cubemap images are square */ 652bf215546Sopenharmony_ci assert(util_format_is_compressed(pt->format)); /* compressed only */ 653bf215546Sopenharmony_ci 654bf215546Sopenharmony_ci /* 655bf215546Sopenharmony_ci * Depending on the size of the largest images, pitch can be 656bf215546Sopenharmony_ci * determined either by the old-style packing of cubemap faces, 657bf215546Sopenharmony_ci * or the final row of 4x4, 2x2 and 1x1 faces below this. 658bf215546Sopenharmony_ci * 659bf215546Sopenharmony_ci * 64 * 2 / 4 = 32 660bf215546Sopenharmony_ci * 14 * 2 = 28 661bf215546Sopenharmony_ci */ 662bf215546Sopenharmony_ci if (width >= 64) 663bf215546Sopenharmony_ci tex->stride = nblocks * 2 * util_format_get_blocksize(pt->format); 664bf215546Sopenharmony_ci else 665bf215546Sopenharmony_ci tex->stride = 14 * 2 * util_format_get_blocksize(pt->format); 666bf215546Sopenharmony_ci 667bf215546Sopenharmony_ci /* 668bf215546Sopenharmony_ci * Something similary apply for height as well. 669bf215546Sopenharmony_ci */ 670bf215546Sopenharmony_ci if (width >= 4) 671bf215546Sopenharmony_ci tex->total_nblocksy = nblocks * 4 + 1; 672bf215546Sopenharmony_ci else 673bf215546Sopenharmony_ci tex->total_nblocksy = 1; 674bf215546Sopenharmony_ci 675bf215546Sopenharmony_ci /* Set all the levels to effectively occupy the whole rectangular region */ 676bf215546Sopenharmony_ci for (level = 0; level <= pt->last_level; level++) 677bf215546Sopenharmony_ci i915_texture_set_level_info(tex, level, 6); 678bf215546Sopenharmony_ci 679bf215546Sopenharmony_ci for (face = 0; face < 6; face++) { 680bf215546Sopenharmony_ci /* all calculations in pixels */ 681bf215546Sopenharmony_ci unsigned total_height = tex->total_nblocksy * 4; 682bf215546Sopenharmony_ci unsigned x = initial_offsets[face][0] * dim; 683bf215546Sopenharmony_ci unsigned y = initial_offsets[face][1] * dim; 684bf215546Sopenharmony_ci unsigned d = dim; 685bf215546Sopenharmony_ci 686bf215546Sopenharmony_ci if (dim == 4 && face >= 4) { 687bf215546Sopenharmony_ci x = (face - 4) * 8; 688bf215546Sopenharmony_ci y = tex->total_nblocksy * 4 - 4; /* 4 = 1 block */ 689bf215546Sopenharmony_ci } else if (dim < 4 && (face > 0)) { 690bf215546Sopenharmony_ci x = face * 8; 691bf215546Sopenharmony_ci y = total_height - 4; 692bf215546Sopenharmony_ci } 693bf215546Sopenharmony_ci 694bf215546Sopenharmony_ci for (level = 0; level <= pt->last_level; level++) { 695bf215546Sopenharmony_ci i915_texture_set_image_offset(tex, level, face, 696bf215546Sopenharmony_ci util_format_get_nblocksx(pt->format, x), 697bf215546Sopenharmony_ci util_format_get_nblocksy(pt->format, y)); 698bf215546Sopenharmony_ci 699bf215546Sopenharmony_ci d >>= 1; 700bf215546Sopenharmony_ci 701bf215546Sopenharmony_ci switch (d) { 702bf215546Sopenharmony_ci case 4: 703bf215546Sopenharmony_ci switch (face) { 704bf215546Sopenharmony_ci case PIPE_TEX_FACE_POS_X: 705bf215546Sopenharmony_ci case PIPE_TEX_FACE_NEG_X: 706bf215546Sopenharmony_ci x += step_offsets[face][0] * d; 707bf215546Sopenharmony_ci y += step_offsets[face][1] * d; 708bf215546Sopenharmony_ci break; 709bf215546Sopenharmony_ci case PIPE_TEX_FACE_POS_Y: 710bf215546Sopenharmony_ci case PIPE_TEX_FACE_NEG_Y: 711bf215546Sopenharmony_ci y += 12; 712bf215546Sopenharmony_ci x -= 8; 713bf215546Sopenharmony_ci break; 714bf215546Sopenharmony_ci case PIPE_TEX_FACE_POS_Z: 715bf215546Sopenharmony_ci case PIPE_TEX_FACE_NEG_Z: 716bf215546Sopenharmony_ci y = total_height - 4; 717bf215546Sopenharmony_ci x = (face - 4) * 8; 718bf215546Sopenharmony_ci break; 719bf215546Sopenharmony_ci } 720bf215546Sopenharmony_ci break; 721bf215546Sopenharmony_ci case 2: 722bf215546Sopenharmony_ci y = total_height - 4; 723bf215546Sopenharmony_ci x = bottom_offsets[face]; 724bf215546Sopenharmony_ci break; 725bf215546Sopenharmony_ci case 1: 726bf215546Sopenharmony_ci x += 48; 727bf215546Sopenharmony_ci break; 728bf215546Sopenharmony_ci default: 729bf215546Sopenharmony_ci x += step_offsets[face][0] * d; 730bf215546Sopenharmony_ci y += step_offsets[face][1] * d; 731bf215546Sopenharmony_ci break; 732bf215546Sopenharmony_ci } 733bf215546Sopenharmony_ci } 734bf215546Sopenharmony_ci } 735bf215546Sopenharmony_ci} 736bf215546Sopenharmony_ci 737bf215546Sopenharmony_cistatic bool 738bf215546Sopenharmony_cii945_texture_layout(struct i915_texture *tex) 739bf215546Sopenharmony_ci{ 740bf215546Sopenharmony_ci switch (tex->b.target) { 741bf215546Sopenharmony_ci case PIPE_TEXTURE_1D: 742bf215546Sopenharmony_ci case PIPE_TEXTURE_2D: 743bf215546Sopenharmony_ci case PIPE_TEXTURE_RECT: 744bf215546Sopenharmony_ci if (!i9x5_special_layout(tex)) 745bf215546Sopenharmony_ci i945_texture_layout_2d(tex); 746bf215546Sopenharmony_ci break; 747bf215546Sopenharmony_ci case PIPE_TEXTURE_3D: 748bf215546Sopenharmony_ci i945_texture_layout_3d(tex); 749bf215546Sopenharmony_ci break; 750bf215546Sopenharmony_ci case PIPE_TEXTURE_CUBE: 751bf215546Sopenharmony_ci if (!util_format_is_compressed(tex->b.format)) 752bf215546Sopenharmony_ci i9x5_texture_layout_cube(tex); 753bf215546Sopenharmony_ci else 754bf215546Sopenharmony_ci i945_texture_layout_cube(tex); 755bf215546Sopenharmony_ci break; 756bf215546Sopenharmony_ci default: 757bf215546Sopenharmony_ci assert(0); 758bf215546Sopenharmony_ci return false; 759bf215546Sopenharmony_ci } 760bf215546Sopenharmony_ci 761bf215546Sopenharmony_ci return true; 762bf215546Sopenharmony_ci} 763bf215546Sopenharmony_ci 764bf215546Sopenharmony_ci/* 765bf215546Sopenharmony_ci * Screen texture functions 766bf215546Sopenharmony_ci */ 767bf215546Sopenharmony_ci 768bf215546Sopenharmony_cibool 769bf215546Sopenharmony_cii915_resource_get_handle(struct pipe_screen *screen, 770bf215546Sopenharmony_ci struct pipe_context *context, 771bf215546Sopenharmony_ci struct pipe_resource *texture, 772bf215546Sopenharmony_ci struct winsys_handle *whandle, unsigned usage) 773bf215546Sopenharmony_ci{ 774bf215546Sopenharmony_ci if (texture->target == PIPE_BUFFER) 775bf215546Sopenharmony_ci return false; 776bf215546Sopenharmony_ci 777bf215546Sopenharmony_ci struct i915_screen *is = i915_screen(screen); 778bf215546Sopenharmony_ci struct i915_texture *tex = i915_texture(texture); 779bf215546Sopenharmony_ci struct i915_winsys *iws = is->iws; 780bf215546Sopenharmony_ci 781bf215546Sopenharmony_ci return iws->buffer_get_handle(iws, tex->buffer, whandle, tex->stride); 782bf215546Sopenharmony_ci} 783bf215546Sopenharmony_ci 784bf215546Sopenharmony_civoid * 785bf215546Sopenharmony_cii915_texture_transfer_map(struct pipe_context *pipe, 786bf215546Sopenharmony_ci struct pipe_resource *resource, unsigned level, 787bf215546Sopenharmony_ci unsigned usage, const struct pipe_box *box, 788bf215546Sopenharmony_ci struct pipe_transfer **ptransfer) 789bf215546Sopenharmony_ci{ 790bf215546Sopenharmony_ci struct i915_context *i915 = i915_context(pipe); 791bf215546Sopenharmony_ci struct i915_texture *tex = i915_texture(resource); 792bf215546Sopenharmony_ci struct i915_transfer *transfer = slab_alloc_st(&i915->texture_transfer_pool); 793bf215546Sopenharmony_ci bool use_staging_texture = false; 794bf215546Sopenharmony_ci struct i915_winsys *iws = i915_screen(pipe->screen)->iws; 795bf215546Sopenharmony_ci enum pipe_format format = resource->format; 796bf215546Sopenharmony_ci unsigned offset; 797bf215546Sopenharmony_ci char *map; 798bf215546Sopenharmony_ci 799bf215546Sopenharmony_ci if (!transfer) 800bf215546Sopenharmony_ci return NULL; 801bf215546Sopenharmony_ci 802bf215546Sopenharmony_ci transfer->b.resource = resource; 803bf215546Sopenharmony_ci transfer->b.level = level; 804bf215546Sopenharmony_ci transfer->b.usage = usage; 805bf215546Sopenharmony_ci transfer->b.box = *box; 806bf215546Sopenharmony_ci transfer->b.stride = tex->stride; 807bf215546Sopenharmony_ci transfer->staging_texture = NULL; 808bf215546Sopenharmony_ci /* XXX: handle depth textures everyhwere*/ 809bf215546Sopenharmony_ci transfer->b.layer_stride = 0; 810bf215546Sopenharmony_ci 811bf215546Sopenharmony_ci /* if we use staging transfers, only support textures we can render to, 812bf215546Sopenharmony_ci * because we need that for u_blitter */ 813bf215546Sopenharmony_ci if (i915->blitter && 814bf215546Sopenharmony_ci util_blitter_is_copy_supported(i915->blitter, resource, resource) && 815bf215546Sopenharmony_ci (usage & PIPE_MAP_WRITE) && 816bf215546Sopenharmony_ci !(usage & 817bf215546Sopenharmony_ci (PIPE_MAP_READ | PIPE_MAP_DONTBLOCK | PIPE_MAP_UNSYNCHRONIZED))) 818bf215546Sopenharmony_ci use_staging_texture = true; 819bf215546Sopenharmony_ci 820bf215546Sopenharmony_ci use_staging_texture = false; 821bf215546Sopenharmony_ci 822bf215546Sopenharmony_ci if (use_staging_texture) { 823bf215546Sopenharmony_ci /* 824bf215546Sopenharmony_ci * Allocate the untiled staging texture. 825bf215546Sopenharmony_ci * If the alloc fails, transfer->staging_texture is NULL and we fallback 826bf215546Sopenharmony_ci * to a map() 827bf215546Sopenharmony_ci */ 828bf215546Sopenharmony_ci transfer->staging_texture = 829bf215546Sopenharmony_ci i915_texture_create(pipe->screen, resource, true); 830bf215546Sopenharmony_ci } 831bf215546Sopenharmony_ci 832bf215546Sopenharmony_ci if (resource->target != PIPE_TEXTURE_3D && 833bf215546Sopenharmony_ci resource->target != PIPE_TEXTURE_CUBE) { 834bf215546Sopenharmony_ci assert(box->z == 0); 835bf215546Sopenharmony_ci assert(box->depth == 1); 836bf215546Sopenharmony_ci } 837bf215546Sopenharmony_ci 838bf215546Sopenharmony_ci if (transfer->staging_texture) { 839bf215546Sopenharmony_ci tex = i915_texture(transfer->staging_texture); 840bf215546Sopenharmony_ci } else { 841bf215546Sopenharmony_ci /* TODO this is a sledgehammer */ 842bf215546Sopenharmony_ci tex = i915_texture(resource); 843bf215546Sopenharmony_ci pipe->flush(pipe, NULL, 0); 844bf215546Sopenharmony_ci } 845bf215546Sopenharmony_ci 846bf215546Sopenharmony_ci offset = i915_texture_offset(tex, transfer->b.level, box->z); 847bf215546Sopenharmony_ci 848bf215546Sopenharmony_ci map = iws->buffer_map(iws, tex->buffer, 849bf215546Sopenharmony_ci (transfer->b.usage & PIPE_MAP_WRITE) ? true : false); 850bf215546Sopenharmony_ci if (!map) { 851bf215546Sopenharmony_ci pipe_resource_reference(&transfer->staging_texture, NULL); 852bf215546Sopenharmony_ci FREE(transfer); 853bf215546Sopenharmony_ci return NULL; 854bf215546Sopenharmony_ci } 855bf215546Sopenharmony_ci 856bf215546Sopenharmony_ci *ptransfer = &transfer->b; 857bf215546Sopenharmony_ci 858bf215546Sopenharmony_ci return map + offset + 859bf215546Sopenharmony_ci box->y / util_format_get_blockheight(format) * transfer->b.stride + 860bf215546Sopenharmony_ci box->x / util_format_get_blockwidth(format) * 861bf215546Sopenharmony_ci util_format_get_blocksize(format); 862bf215546Sopenharmony_ci} 863bf215546Sopenharmony_ci 864bf215546Sopenharmony_civoid 865bf215546Sopenharmony_cii915_texture_transfer_unmap(struct pipe_context *pipe, 866bf215546Sopenharmony_ci struct pipe_transfer *transfer) 867bf215546Sopenharmony_ci{ 868bf215546Sopenharmony_ci struct i915_context *i915 = i915_context(pipe); 869bf215546Sopenharmony_ci struct i915_transfer *itransfer = (struct i915_transfer *)transfer; 870bf215546Sopenharmony_ci struct i915_texture *tex = i915_texture(itransfer->b.resource); 871bf215546Sopenharmony_ci struct i915_winsys *iws = i915_screen(tex->b.screen)->iws; 872bf215546Sopenharmony_ci 873bf215546Sopenharmony_ci if (itransfer->staging_texture) 874bf215546Sopenharmony_ci tex = i915_texture(itransfer->staging_texture); 875bf215546Sopenharmony_ci 876bf215546Sopenharmony_ci iws->buffer_unmap(iws, tex->buffer); 877bf215546Sopenharmony_ci 878bf215546Sopenharmony_ci if ((itransfer->staging_texture) && (transfer->usage & PIPE_MAP_WRITE)) { 879bf215546Sopenharmony_ci struct pipe_box sbox; 880bf215546Sopenharmony_ci 881bf215546Sopenharmony_ci u_box_origin_2d(itransfer->b.box.width, itransfer->b.box.height, &sbox); 882bf215546Sopenharmony_ci pipe->resource_copy_region(pipe, itransfer->b.resource, 883bf215546Sopenharmony_ci itransfer->b.level, itransfer->b.box.x, 884bf215546Sopenharmony_ci itransfer->b.box.y, itransfer->b.box.z, 885bf215546Sopenharmony_ci itransfer->staging_texture, 0, &sbox); 886bf215546Sopenharmony_ci pipe->flush(pipe, NULL, 0); 887bf215546Sopenharmony_ci pipe_resource_reference(&itransfer->staging_texture, NULL); 888bf215546Sopenharmony_ci } 889bf215546Sopenharmony_ci 890bf215546Sopenharmony_ci slab_free_st(&i915->texture_transfer_pool, itransfer); 891bf215546Sopenharmony_ci} 892bf215546Sopenharmony_ci 893bf215546Sopenharmony_civoid 894bf215546Sopenharmony_cii915_texture_subdata(struct pipe_context *pipe, struct pipe_resource *resource, 895bf215546Sopenharmony_ci unsigned level, unsigned usage, const struct pipe_box *box, 896bf215546Sopenharmony_ci const void *data, unsigned stride, unsigned layer_stride) 897bf215546Sopenharmony_ci{ 898bf215546Sopenharmony_ci /* i915's cube and 3D maps are not laid out such that one could use a 899bf215546Sopenharmony_ci * layer_stride to get from one layer to the next, so we have to walk the 900bf215546Sopenharmony_ci * layers individually. 901bf215546Sopenharmony_ci */ 902bf215546Sopenharmony_ci struct pipe_box layer_box = *box; 903bf215546Sopenharmony_ci layer_box.depth = 1; 904bf215546Sopenharmony_ci for (layer_box.z = box->z; layer_box.z < box->z + box->depth; 905bf215546Sopenharmony_ci layer_box.z++) { 906bf215546Sopenharmony_ci u_default_texture_subdata(pipe, resource, level, usage, &layer_box, data, 907bf215546Sopenharmony_ci stride, layer_stride); 908bf215546Sopenharmony_ci data += layer_stride; 909bf215546Sopenharmony_ci } 910bf215546Sopenharmony_ci} 911bf215546Sopenharmony_ci 912bf215546Sopenharmony_cistruct pipe_resource * 913bf215546Sopenharmony_cii915_texture_create(struct pipe_screen *screen, 914bf215546Sopenharmony_ci const struct pipe_resource *template, bool force_untiled) 915bf215546Sopenharmony_ci{ 916bf215546Sopenharmony_ci struct i915_screen *is = i915_screen(screen); 917bf215546Sopenharmony_ci struct i915_winsys *iws = is->iws; 918bf215546Sopenharmony_ci struct i915_texture *tex = CALLOC_STRUCT(i915_texture); 919bf215546Sopenharmony_ci unsigned buf_usage = 0; 920bf215546Sopenharmony_ci 921bf215546Sopenharmony_ci if (!tex) 922bf215546Sopenharmony_ci return NULL; 923bf215546Sopenharmony_ci 924bf215546Sopenharmony_ci tex->b = *template; 925bf215546Sopenharmony_ci pipe_reference_init(&tex->b.reference, 1); 926bf215546Sopenharmony_ci tex->b.screen = screen; 927bf215546Sopenharmony_ci 928bf215546Sopenharmony_ci if ((force_untiled) || (template->usage == PIPE_USAGE_STREAM)) 929bf215546Sopenharmony_ci tex->tiling = I915_TILE_NONE; 930bf215546Sopenharmony_ci else 931bf215546Sopenharmony_ci tex->tiling = i915_texture_tiling(is, tex); 932bf215546Sopenharmony_ci 933bf215546Sopenharmony_ci if (is->is_i945) { 934bf215546Sopenharmony_ci if (!i945_texture_layout(tex)) 935bf215546Sopenharmony_ci goto fail; 936bf215546Sopenharmony_ci } else { 937bf215546Sopenharmony_ci if (!i915_texture_layout(tex)) 938bf215546Sopenharmony_ci goto fail; 939bf215546Sopenharmony_ci } 940bf215546Sopenharmony_ci 941bf215546Sopenharmony_ci /* for scanouts and cursors, cursors arn't scanouts */ 942bf215546Sopenharmony_ci 943bf215546Sopenharmony_ci /* XXX: use a custom flag for cursors, don't rely on magically 944bf215546Sopenharmony_ci * guessing that this is Xorg asking for a cursor 945bf215546Sopenharmony_ci */ 946bf215546Sopenharmony_ci if ((template->bind & PIPE_BIND_SCANOUT) && template->width0 != 64) 947bf215546Sopenharmony_ci buf_usage = I915_NEW_SCANOUT; 948bf215546Sopenharmony_ci else 949bf215546Sopenharmony_ci buf_usage = I915_NEW_TEXTURE; 950bf215546Sopenharmony_ci 951bf215546Sopenharmony_ci tex->buffer = iws->buffer_create_tiled( 952bf215546Sopenharmony_ci iws, &tex->stride, tex->total_nblocksy, &tex->tiling, buf_usage); 953bf215546Sopenharmony_ci if (!tex->buffer) 954bf215546Sopenharmony_ci goto fail; 955bf215546Sopenharmony_ci 956bf215546Sopenharmony_ci I915_DBG(DBG_TEXTURE, "%s: %p stride %u, blocks (%u, %u) tiling %s\n", 957bf215546Sopenharmony_ci __func__, tex, tex->stride, 958bf215546Sopenharmony_ci tex->stride / util_format_get_blocksize(tex->b.format), 959bf215546Sopenharmony_ci tex->total_nblocksy, get_tiling_string(tex->tiling)); 960bf215546Sopenharmony_ci 961bf215546Sopenharmony_ci return &tex->b; 962bf215546Sopenharmony_ci 963bf215546Sopenharmony_cifail: 964bf215546Sopenharmony_ci FREE(tex); 965bf215546Sopenharmony_ci return NULL; 966bf215546Sopenharmony_ci} 967bf215546Sopenharmony_ci 968bf215546Sopenharmony_cistruct pipe_resource * 969bf215546Sopenharmony_cii915_texture_from_handle(struct pipe_screen *screen, 970bf215546Sopenharmony_ci const struct pipe_resource *template, 971bf215546Sopenharmony_ci struct winsys_handle *whandle) 972bf215546Sopenharmony_ci{ 973bf215546Sopenharmony_ci struct i915_screen *is = i915_screen(screen); 974bf215546Sopenharmony_ci struct i915_texture *tex; 975bf215546Sopenharmony_ci struct i915_winsys *iws = is->iws; 976bf215546Sopenharmony_ci struct i915_winsys_buffer *buffer; 977bf215546Sopenharmony_ci unsigned stride; 978bf215546Sopenharmony_ci enum i915_winsys_buffer_tile tiling; 979bf215546Sopenharmony_ci 980bf215546Sopenharmony_ci assert(screen); 981bf215546Sopenharmony_ci 982bf215546Sopenharmony_ci buffer = iws->buffer_from_handle(iws, whandle, template->height0, &tiling, 983bf215546Sopenharmony_ci &stride); 984bf215546Sopenharmony_ci 985bf215546Sopenharmony_ci /* Only supports one type */ 986bf215546Sopenharmony_ci if ((template->target != PIPE_TEXTURE_2D && 987bf215546Sopenharmony_ci template->target != PIPE_TEXTURE_RECT) || 988bf215546Sopenharmony_ci template->last_level != 0 || template->depth0 != 1) { 989bf215546Sopenharmony_ci return NULL; 990bf215546Sopenharmony_ci } 991bf215546Sopenharmony_ci 992bf215546Sopenharmony_ci tex = CALLOC_STRUCT(i915_texture); 993bf215546Sopenharmony_ci if (!tex) 994bf215546Sopenharmony_ci return NULL; 995bf215546Sopenharmony_ci 996bf215546Sopenharmony_ci tex->b = *template; 997bf215546Sopenharmony_ci pipe_reference_init(&tex->b.reference, 1); 998bf215546Sopenharmony_ci tex->b.screen = screen; 999bf215546Sopenharmony_ci 1000bf215546Sopenharmony_ci tex->stride = stride; 1001bf215546Sopenharmony_ci tex->tiling = tiling; 1002bf215546Sopenharmony_ci tex->total_nblocksy = align_nblocksy(tex->b.format, tex->b.height0, 8); 1003bf215546Sopenharmony_ci 1004bf215546Sopenharmony_ci i915_texture_set_level_info(tex, 0, 1); 1005bf215546Sopenharmony_ci i915_texture_set_image_offset(tex, 0, 0, 0, 0); 1006bf215546Sopenharmony_ci 1007bf215546Sopenharmony_ci tex->buffer = buffer; 1008bf215546Sopenharmony_ci 1009bf215546Sopenharmony_ci I915_DBG(DBG_TEXTURE, "%s: %p stride %u, blocks (%u, %u) tiling %s\n", 1010bf215546Sopenharmony_ci __func__, tex, tex->stride, 1011bf215546Sopenharmony_ci tex->stride / util_format_get_blocksize(tex->b.format), 1012bf215546Sopenharmony_ci tex->total_nblocksy, get_tiling_string(tex->tiling)); 1013bf215546Sopenharmony_ci 1014bf215546Sopenharmony_ci return &tex->b; 1015bf215546Sopenharmony_ci} 1016