1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2008 Ben Skeggs 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 12bf215546Sopenharmony_ci * all copies or substantial portions of the Software. 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 21bf215546Sopenharmony_ci */ 22bf215546Sopenharmony_ci 23bf215546Sopenharmony_ci#include "pipe/p_state.h" 24bf215546Sopenharmony_ci#include "pipe/p_defines.h" 25bf215546Sopenharmony_ci#include "util/u_inlines.h" 26bf215546Sopenharmony_ci#include "util/format/u_format.h" 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#include "nv50/nv50_context.h" 29bf215546Sopenharmony_ci#include "nv50/nv50_resource.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ciuint32_t 32bf215546Sopenharmony_cinv50_tex_choose_tile_dims_helper(unsigned nx, unsigned ny, unsigned nz, 33bf215546Sopenharmony_ci bool is_3d) 34bf215546Sopenharmony_ci{ 35bf215546Sopenharmony_ci uint32_t tile_mode = 0x000; 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci if (ny > 64) tile_mode = 0x040; /* height 128 tiles */ 38bf215546Sopenharmony_ci else 39bf215546Sopenharmony_ci if (ny > 32) tile_mode = 0x030; /* height 64 tiles */ 40bf215546Sopenharmony_ci else 41bf215546Sopenharmony_ci if (ny > 16) tile_mode = 0x020; /* height 32 tiles */ 42bf215546Sopenharmony_ci else 43bf215546Sopenharmony_ci if (ny > 8) tile_mode = 0x010; /* height 16 tiles */ 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci if (!is_3d) 46bf215546Sopenharmony_ci return tile_mode; 47bf215546Sopenharmony_ci else 48bf215546Sopenharmony_ci if (tile_mode > 0x020) 49bf215546Sopenharmony_ci tile_mode = 0x020; 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci if (nz > 16 && tile_mode < 0x020) 52bf215546Sopenharmony_ci return tile_mode | 0x500; /* depth 32 tiles */ 53bf215546Sopenharmony_ci if (nz > 8) return tile_mode | 0x400; /* depth 16 tiles */ 54bf215546Sopenharmony_ci if (nz > 4) return tile_mode | 0x300; /* depth 8 tiles */ 55bf215546Sopenharmony_ci if (nz > 2) return tile_mode | 0x200; /* depth 4 tiles */ 56bf215546Sopenharmony_ci if (nz > 1) return tile_mode | 0x100; /* depth 2 tiles */ 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci return tile_mode; 59bf215546Sopenharmony_ci} 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_cistatic uint32_t 62bf215546Sopenharmony_cinv50_tex_choose_tile_dims(unsigned nx, unsigned ny, unsigned nz, bool is_3d) 63bf215546Sopenharmony_ci{ 64bf215546Sopenharmony_ci return nv50_tex_choose_tile_dims_helper(nx, ny * 2, nz, is_3d); 65bf215546Sopenharmony_ci} 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_cistatic uint32_t 68bf215546Sopenharmony_cinv50_mt_choose_storage_type(struct nv50_miptree *mt, bool compressed) 69bf215546Sopenharmony_ci{ 70bf215546Sopenharmony_ci const unsigned ms = util_logbase2(mt->base.base.nr_samples); 71bf215546Sopenharmony_ci uint32_t tile_flags; 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci if (unlikely(mt->base.base.flags & NOUVEAU_RESOURCE_FLAG_LINEAR)) 74bf215546Sopenharmony_ci return 0; 75bf215546Sopenharmony_ci if (unlikely(mt->base.base.bind & PIPE_BIND_CURSOR)) 76bf215546Sopenharmony_ci return 0; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci switch (mt->base.base.format) { 79bf215546Sopenharmony_ci case PIPE_FORMAT_Z16_UNORM: 80bf215546Sopenharmony_ci tile_flags = 0x6c + ms; 81bf215546Sopenharmony_ci break; 82bf215546Sopenharmony_ci case PIPE_FORMAT_X8Z24_UNORM: 83bf215546Sopenharmony_ci case PIPE_FORMAT_S8X24_UINT: 84bf215546Sopenharmony_ci case PIPE_FORMAT_S8_UINT_Z24_UNORM: 85bf215546Sopenharmony_ci tile_flags = 0x18 + ms; 86bf215546Sopenharmony_ci break; 87bf215546Sopenharmony_ci case PIPE_FORMAT_X24S8_UINT: 88bf215546Sopenharmony_ci case PIPE_FORMAT_Z24X8_UNORM: 89bf215546Sopenharmony_ci case PIPE_FORMAT_Z24_UNORM_S8_UINT: 90bf215546Sopenharmony_ci tile_flags = 0x128 + ms; 91bf215546Sopenharmony_ci break; 92bf215546Sopenharmony_ci case PIPE_FORMAT_Z32_FLOAT: 93bf215546Sopenharmony_ci tile_flags = 0x40 + ms; 94bf215546Sopenharmony_ci break; 95bf215546Sopenharmony_ci case PIPE_FORMAT_X32_S8X24_UINT: 96bf215546Sopenharmony_ci case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT: 97bf215546Sopenharmony_ci tile_flags = 0x60 + ms; 98bf215546Sopenharmony_ci break; 99bf215546Sopenharmony_ci default: 100bf215546Sopenharmony_ci /* Most color formats don't work with compression. */ 101bf215546Sopenharmony_ci compressed = false; 102bf215546Sopenharmony_ci FALLTHROUGH; 103bf215546Sopenharmony_ci case PIPE_FORMAT_R8G8B8A8_UNORM: 104bf215546Sopenharmony_ci case PIPE_FORMAT_R8G8B8A8_SRGB: 105bf215546Sopenharmony_ci case PIPE_FORMAT_R8G8B8X8_UNORM: 106bf215546Sopenharmony_ci case PIPE_FORMAT_R8G8B8X8_SRGB: 107bf215546Sopenharmony_ci case PIPE_FORMAT_B8G8R8A8_UNORM: 108bf215546Sopenharmony_ci case PIPE_FORMAT_B8G8R8A8_SRGB: 109bf215546Sopenharmony_ci case PIPE_FORMAT_B8G8R8X8_UNORM: 110bf215546Sopenharmony_ci case PIPE_FORMAT_B8G8R8X8_SRGB: 111bf215546Sopenharmony_ci case PIPE_FORMAT_R10G10B10A2_UNORM: 112bf215546Sopenharmony_ci case PIPE_FORMAT_B10G10R10A2_UNORM: 113bf215546Sopenharmony_ci case PIPE_FORMAT_R16G16B16A16_FLOAT: 114bf215546Sopenharmony_ci case PIPE_FORMAT_R16G16B16X16_FLOAT: 115bf215546Sopenharmony_ci case PIPE_FORMAT_R11G11B10_FLOAT: 116bf215546Sopenharmony_ci switch (util_format_get_blocksizebits(mt->base.base.format)) { 117bf215546Sopenharmony_ci case 128: 118bf215546Sopenharmony_ci assert(ms < 3); 119bf215546Sopenharmony_ci tile_flags = 0x74; 120bf215546Sopenharmony_ci break; 121bf215546Sopenharmony_ci case 64: 122bf215546Sopenharmony_ci switch (ms) { 123bf215546Sopenharmony_ci case 2: tile_flags = 0xfc; break; 124bf215546Sopenharmony_ci case 3: tile_flags = 0xfd; break; 125bf215546Sopenharmony_ci default: 126bf215546Sopenharmony_ci tile_flags = 0x70; 127bf215546Sopenharmony_ci break; 128bf215546Sopenharmony_ci } 129bf215546Sopenharmony_ci break; 130bf215546Sopenharmony_ci case 32: 131bf215546Sopenharmony_ci if (mt->base.base.bind & PIPE_BIND_SCANOUT) { 132bf215546Sopenharmony_ci assert(ms == 0); 133bf215546Sopenharmony_ci tile_flags = 0x7a; 134bf215546Sopenharmony_ci } else { 135bf215546Sopenharmony_ci switch (ms) { 136bf215546Sopenharmony_ci case 2: tile_flags = 0xf8; break; 137bf215546Sopenharmony_ci case 3: tile_flags = 0xf9; break; 138bf215546Sopenharmony_ci default: 139bf215546Sopenharmony_ci tile_flags = 0x70; 140bf215546Sopenharmony_ci break; 141bf215546Sopenharmony_ci } 142bf215546Sopenharmony_ci } 143bf215546Sopenharmony_ci break; 144bf215546Sopenharmony_ci case 16: 145bf215546Sopenharmony_ci case 8: 146bf215546Sopenharmony_ci tile_flags = 0x70; 147bf215546Sopenharmony_ci break; 148bf215546Sopenharmony_ci default: 149bf215546Sopenharmony_ci return 0; 150bf215546Sopenharmony_ci } 151bf215546Sopenharmony_ci if (mt->base.base.bind & PIPE_BIND_CURSOR) 152bf215546Sopenharmony_ci tile_flags = 0; 153bf215546Sopenharmony_ci } 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci if (!compressed) 156bf215546Sopenharmony_ci tile_flags &= ~0x180; 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci return tile_flags; 159bf215546Sopenharmony_ci} 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_civoid 162bf215546Sopenharmony_cinv50_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt) 163bf215546Sopenharmony_ci{ 164bf215546Sopenharmony_ci struct nv50_miptree *mt = nv50_miptree(pt); 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci if (mt->base.fence && mt->base.fence->state < NOUVEAU_FENCE_STATE_FLUSHED) 167bf215546Sopenharmony_ci nouveau_fence_work(mt->base.fence, nouveau_fence_unref_bo, mt->base.bo); 168bf215546Sopenharmony_ci else 169bf215546Sopenharmony_ci nouveau_bo_ref(NULL, &mt->base.bo); 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci nouveau_fence_ref(NULL, &mt->base.fence); 172bf215546Sopenharmony_ci nouveau_fence_ref(NULL, &mt->base.fence_wr); 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci NOUVEAU_DRV_STAT(nouveau_screen(pscreen), tex_obj_current_count, -1); 175bf215546Sopenharmony_ci NOUVEAU_DRV_STAT(nouveau_screen(pscreen), tex_obj_current_bytes, 176bf215546Sopenharmony_ci -(uint64_t)mt->total_size); 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci FREE(mt); 179bf215546Sopenharmony_ci} 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_cibool 182bf215546Sopenharmony_cinv50_miptree_get_handle(struct pipe_screen *pscreen, 183bf215546Sopenharmony_ci struct pipe_context *context, 184bf215546Sopenharmony_ci struct pipe_resource *pt, 185bf215546Sopenharmony_ci struct winsys_handle *whandle, 186bf215546Sopenharmony_ci unsigned usage) 187bf215546Sopenharmony_ci{ 188bf215546Sopenharmony_ci if (pt->target == PIPE_BUFFER) 189bf215546Sopenharmony_ci return false; 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci struct nv50_miptree *mt = nv50_miptree(pt); 192bf215546Sopenharmony_ci unsigned stride; 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci if (!mt || !mt->base.bo) 195bf215546Sopenharmony_ci return false; 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci stride = mt->level[0].pitch; 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci return nouveau_screen_bo_get_handle(pscreen, 200bf215546Sopenharmony_ci mt->base.bo, 201bf215546Sopenharmony_ci stride, 202bf215546Sopenharmony_ci whandle); 203bf215546Sopenharmony_ci} 204bf215546Sopenharmony_ci 205bf215546Sopenharmony_cistatic inline bool 206bf215546Sopenharmony_cinv50_miptree_init_ms_mode(struct nv50_miptree *mt) 207bf215546Sopenharmony_ci{ 208bf215546Sopenharmony_ci switch (mt->base.base.nr_samples) { 209bf215546Sopenharmony_ci case 8: 210bf215546Sopenharmony_ci mt->ms_mode = NV50_3D_MULTISAMPLE_MODE_MS8; 211bf215546Sopenharmony_ci mt->ms_x = 2; 212bf215546Sopenharmony_ci mt->ms_y = 1; 213bf215546Sopenharmony_ci break; 214bf215546Sopenharmony_ci case 4: 215bf215546Sopenharmony_ci mt->ms_mode = NV50_3D_MULTISAMPLE_MODE_MS4; 216bf215546Sopenharmony_ci mt->ms_x = 1; 217bf215546Sopenharmony_ci mt->ms_y = 1; 218bf215546Sopenharmony_ci break; 219bf215546Sopenharmony_ci case 2: 220bf215546Sopenharmony_ci mt->ms_mode = NV50_3D_MULTISAMPLE_MODE_MS2; 221bf215546Sopenharmony_ci mt->ms_x = 1; 222bf215546Sopenharmony_ci break; 223bf215546Sopenharmony_ci case 1: 224bf215546Sopenharmony_ci case 0: 225bf215546Sopenharmony_ci mt->ms_mode = NV50_3D_MULTISAMPLE_MODE_MS1; 226bf215546Sopenharmony_ci break; 227bf215546Sopenharmony_ci default: 228bf215546Sopenharmony_ci NOUVEAU_ERR("invalid nr_samples: %u\n", mt->base.base.nr_samples); 229bf215546Sopenharmony_ci return false; 230bf215546Sopenharmony_ci } 231bf215546Sopenharmony_ci return true; 232bf215546Sopenharmony_ci} 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_cibool 235bf215546Sopenharmony_cinv50_miptree_init_layout_linear(struct nv50_miptree *mt, unsigned pitch_align) 236bf215546Sopenharmony_ci{ 237bf215546Sopenharmony_ci struct pipe_resource *pt = &mt->base.base; 238bf215546Sopenharmony_ci const unsigned blocksize = util_format_get_blocksize(pt->format); 239bf215546Sopenharmony_ci unsigned h = pt->height0; 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci if (util_format_is_depth_or_stencil(pt->format)) 242bf215546Sopenharmony_ci return false; 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci if ((pt->last_level > 0) || (pt->depth0 > 1) || (pt->array_size > 1)) 245bf215546Sopenharmony_ci return false; 246bf215546Sopenharmony_ci if (mt->ms_x | mt->ms_y) 247bf215546Sopenharmony_ci return false; 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci mt->level[0].pitch = align(pt->width0 * blocksize, pitch_align); 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci /* Account for very generous prefetch (allocate size as if tiled). */ 252bf215546Sopenharmony_ci h = MAX2(h, 8); 253bf215546Sopenharmony_ci h = util_next_power_of_two(h); 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci mt->total_size = mt->level[0].pitch * h; 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci return true; 258bf215546Sopenharmony_ci} 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_cistatic void 261bf215546Sopenharmony_cinv50_miptree_init_layout_video(struct nv50_miptree *mt) 262bf215546Sopenharmony_ci{ 263bf215546Sopenharmony_ci const struct pipe_resource *pt = &mt->base.base; 264bf215546Sopenharmony_ci const unsigned blocksize = util_format_get_blocksize(pt->format); 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci assert(pt->last_level == 0); 267bf215546Sopenharmony_ci assert(mt->ms_x == 0 && mt->ms_y == 0); 268bf215546Sopenharmony_ci assert(!util_format_is_compressed(pt->format)); 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci mt->layout_3d = pt->target == PIPE_TEXTURE_3D; 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci mt->level[0].tile_mode = 0x20; 273bf215546Sopenharmony_ci mt->level[0].pitch = align(pt->width0 * blocksize, 64); 274bf215546Sopenharmony_ci mt->total_size = align(pt->height0, 16) * mt->level[0].pitch * (mt->layout_3d ? pt->depth0 : 1); 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci if (pt->array_size > 1) { 277bf215546Sopenharmony_ci mt->layer_stride = align(mt->total_size, NV50_TILE_SIZE(0x20)); 278bf215546Sopenharmony_ci mt->total_size = mt->layer_stride * pt->array_size; 279bf215546Sopenharmony_ci } 280bf215546Sopenharmony_ci} 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_cistatic void 283bf215546Sopenharmony_cinv50_miptree_init_layout_tiled(struct nv50_miptree *mt) 284bf215546Sopenharmony_ci{ 285bf215546Sopenharmony_ci struct pipe_resource *pt = &mt->base.base; 286bf215546Sopenharmony_ci unsigned w, h, d, l; 287bf215546Sopenharmony_ci const unsigned blocksize = util_format_get_blocksize(pt->format); 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci mt->layout_3d = pt->target == PIPE_TEXTURE_3D; 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci w = pt->width0 << mt->ms_x; 292bf215546Sopenharmony_ci h = pt->height0 << mt->ms_y; 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci /* For 3D textures, a mipmap is spanned by all the layers, for array 295bf215546Sopenharmony_ci * textures and cube maps, each layer contains its own mipmaps. 296bf215546Sopenharmony_ci */ 297bf215546Sopenharmony_ci d = mt->layout_3d ? pt->depth0 : 1; 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci for (l = 0; l <= pt->last_level; ++l) { 300bf215546Sopenharmony_ci struct nv50_miptree_level *lvl = &mt->level[l]; 301bf215546Sopenharmony_ci unsigned tsx, tsy, tsz; 302bf215546Sopenharmony_ci unsigned nbx = util_format_get_nblocksx(pt->format, w); 303bf215546Sopenharmony_ci unsigned nby = util_format_get_nblocksy(pt->format, h); 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci lvl->offset = mt->total_size; 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci lvl->tile_mode = nv50_tex_choose_tile_dims(nbx, nby, d, mt->layout_3d); 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci tsx = NV50_TILE_SIZE_X(lvl->tile_mode); /* x is tile row pitch in bytes */ 310bf215546Sopenharmony_ci tsy = NV50_TILE_SIZE_Y(lvl->tile_mode); 311bf215546Sopenharmony_ci tsz = NV50_TILE_SIZE_Z(lvl->tile_mode); 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci lvl->pitch = align(nbx * blocksize, tsx); 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci mt->total_size += lvl->pitch * align(nby, tsy) * align(d, tsz); 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci w = u_minify(w, 1); 318bf215546Sopenharmony_ci h = u_minify(h, 1); 319bf215546Sopenharmony_ci d = u_minify(d, 1); 320bf215546Sopenharmony_ci } 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_ci if (pt->array_size > 1) { 323bf215546Sopenharmony_ci mt->layer_stride = align(mt->total_size, 324bf215546Sopenharmony_ci NV50_TILE_SIZE(mt->level[0].tile_mode)); 325bf215546Sopenharmony_ci mt->total_size = mt->layer_stride * pt->array_size; 326bf215546Sopenharmony_ci } 327bf215546Sopenharmony_ci} 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_cistruct pipe_resource * 330bf215546Sopenharmony_cinv50_miptree_create(struct pipe_screen *pscreen, 331bf215546Sopenharmony_ci const struct pipe_resource *templ) 332bf215546Sopenharmony_ci{ 333bf215546Sopenharmony_ci struct nouveau_device *dev = nouveau_screen(pscreen)->device; 334bf215546Sopenharmony_ci struct nouveau_drm *drm = nouveau_screen(pscreen)->drm; 335bf215546Sopenharmony_ci struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree); 336bf215546Sopenharmony_ci struct pipe_resource *pt = &mt->base.base; 337bf215546Sopenharmony_ci bool compressed = drm->version >= 0x01000101; 338bf215546Sopenharmony_ci int ret; 339bf215546Sopenharmony_ci union nouveau_bo_config bo_config; 340bf215546Sopenharmony_ci uint32_t bo_flags; 341bf215546Sopenharmony_ci unsigned pitch_align; 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci if (!mt) 344bf215546Sopenharmony_ci return NULL; 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_ci *pt = *templ; 347bf215546Sopenharmony_ci pipe_reference_init(&pt->reference, 1); 348bf215546Sopenharmony_ci pt->screen = pscreen; 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci if (pt->bind & PIPE_BIND_LINEAR) 351bf215546Sopenharmony_ci pt->flags |= NOUVEAU_RESOURCE_FLAG_LINEAR; 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_ci bo_config.nv50.memtype = nv50_mt_choose_storage_type(mt, compressed); 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci if (!nv50_miptree_init_ms_mode(mt)) { 356bf215546Sopenharmony_ci FREE(mt); 357bf215546Sopenharmony_ci return NULL; 358bf215546Sopenharmony_ci } 359bf215546Sopenharmony_ci 360bf215546Sopenharmony_ci if (unlikely(pt->flags & NV50_RESOURCE_FLAG_VIDEO)) { 361bf215546Sopenharmony_ci nv50_miptree_init_layout_video(mt); 362bf215546Sopenharmony_ci if (pt->flags & NV50_RESOURCE_FLAG_NOALLOC) { 363bf215546Sopenharmony_ci /* BO allocation done by client */ 364bf215546Sopenharmony_ci return pt; 365bf215546Sopenharmony_ci } 366bf215546Sopenharmony_ci } else 367bf215546Sopenharmony_ci if (bo_config.nv50.memtype != 0) { 368bf215546Sopenharmony_ci nv50_miptree_init_layout_tiled(mt); 369bf215546Sopenharmony_ci } else { 370bf215546Sopenharmony_ci if (pt->usage & PIPE_BIND_CURSOR) 371bf215546Sopenharmony_ci pitch_align = 1; 372bf215546Sopenharmony_ci else if (pt->usage & PIPE_BIND_SCANOUT) 373bf215546Sopenharmony_ci pitch_align = 256; 374bf215546Sopenharmony_ci else 375bf215546Sopenharmony_ci pitch_align = 64; 376bf215546Sopenharmony_ci if (!nv50_miptree_init_layout_linear(mt, pitch_align)) { 377bf215546Sopenharmony_ci FREE(mt); 378bf215546Sopenharmony_ci return NULL; 379bf215546Sopenharmony_ci } 380bf215546Sopenharmony_ci } 381bf215546Sopenharmony_ci bo_config.nv50.tile_mode = mt->level[0].tile_mode; 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci if (!bo_config.nv50.memtype && (pt->bind & PIPE_BIND_SHARED)) 384bf215546Sopenharmony_ci mt->base.domain = NOUVEAU_BO_GART; 385bf215546Sopenharmony_ci else 386bf215546Sopenharmony_ci mt->base.domain = NV_VRAM_DOMAIN(nouveau_screen(pscreen)); 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci bo_flags = mt->base.domain | NOUVEAU_BO_NOSNOOP; 389bf215546Sopenharmony_ci if (mt->base.base.bind & (PIPE_BIND_CURSOR | PIPE_BIND_DISPLAY_TARGET)) 390bf215546Sopenharmony_ci bo_flags |= NOUVEAU_BO_CONTIG; 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci ret = nouveau_bo_new(dev, bo_flags, 4096, mt->total_size, &bo_config, 393bf215546Sopenharmony_ci &mt->base.bo); 394bf215546Sopenharmony_ci if (ret) { 395bf215546Sopenharmony_ci FREE(mt); 396bf215546Sopenharmony_ci return NULL; 397bf215546Sopenharmony_ci } 398bf215546Sopenharmony_ci mt->base.address = mt->base.bo->offset; 399bf215546Sopenharmony_ci 400bf215546Sopenharmony_ci return pt; 401bf215546Sopenharmony_ci} 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_cistruct pipe_resource * 404bf215546Sopenharmony_cinv50_miptree_from_handle(struct pipe_screen *pscreen, 405bf215546Sopenharmony_ci const struct pipe_resource *templ, 406bf215546Sopenharmony_ci struct winsys_handle *whandle) 407bf215546Sopenharmony_ci{ 408bf215546Sopenharmony_ci struct nv50_miptree *mt; 409bf215546Sopenharmony_ci unsigned stride; 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci /* only supports 2D, non-mipmapped textures for the moment */ 412bf215546Sopenharmony_ci if ((templ->target != PIPE_TEXTURE_2D && 413bf215546Sopenharmony_ci templ->target != PIPE_TEXTURE_RECT) || 414bf215546Sopenharmony_ci templ->last_level != 0 || 415bf215546Sopenharmony_ci templ->depth0 != 1 || 416bf215546Sopenharmony_ci templ->array_size > 1) 417bf215546Sopenharmony_ci return NULL; 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_ci mt = CALLOC_STRUCT(nv50_miptree); 420bf215546Sopenharmony_ci if (!mt) 421bf215546Sopenharmony_ci return NULL; 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci mt->base.bo = nouveau_screen_bo_from_handle(pscreen, whandle, &stride); 424bf215546Sopenharmony_ci if (mt->base.bo == NULL) { 425bf215546Sopenharmony_ci FREE(mt); 426bf215546Sopenharmony_ci return NULL; 427bf215546Sopenharmony_ci } 428bf215546Sopenharmony_ci mt->base.domain = mt->base.bo->flags & NOUVEAU_BO_APER; 429bf215546Sopenharmony_ci mt->base.address = mt->base.bo->offset; 430bf215546Sopenharmony_ci 431bf215546Sopenharmony_ci mt->base.base = *templ; 432bf215546Sopenharmony_ci pipe_reference_init(&mt->base.base.reference, 1); 433bf215546Sopenharmony_ci mt->base.base.screen = pscreen; 434bf215546Sopenharmony_ci mt->level[0].pitch = stride; 435bf215546Sopenharmony_ci mt->level[0].offset = 0; 436bf215546Sopenharmony_ci mt->level[0].tile_mode = mt->base.bo->config.nv50.tile_mode; 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_ci NOUVEAU_DRV_STAT(nouveau_screen(pscreen), tex_obj_current_count, 1); 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_ci /* no need to adjust bo reference count */ 441bf215546Sopenharmony_ci return &mt->base.base; 442bf215546Sopenharmony_ci} 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci/* Offset of zslice @z from start of level @l. */ 446bf215546Sopenharmony_ciinline unsigned 447bf215546Sopenharmony_cinv50_mt_zslice_offset(const struct nv50_miptree *mt, unsigned l, unsigned z) 448bf215546Sopenharmony_ci{ 449bf215546Sopenharmony_ci const struct pipe_resource *pt = &mt->base.base; 450bf215546Sopenharmony_ci 451bf215546Sopenharmony_ci unsigned tds = NV50_TILE_SHIFT_Z(mt->level[l].tile_mode); 452bf215546Sopenharmony_ci unsigned ths = NV50_TILE_SHIFT_Y(mt->level[l].tile_mode); 453bf215546Sopenharmony_ci 454bf215546Sopenharmony_ci unsigned nby = util_format_get_nblocksy(pt->format, 455bf215546Sopenharmony_ci u_minify(pt->height0, l)); 456bf215546Sopenharmony_ci 457bf215546Sopenharmony_ci /* to next 2D tile slice within a 3D tile */ 458bf215546Sopenharmony_ci unsigned stride_2d = NV50_TILE_SIZE_2D(mt->level[l].tile_mode); 459bf215546Sopenharmony_ci 460bf215546Sopenharmony_ci /* to slice in the next (in z direction) 3D tile */ 461bf215546Sopenharmony_ci unsigned stride_3d = (align(nby, (1 << ths)) * mt->level[l].pitch) << tds; 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_ci return (z & ((1 << tds) - 1)) * stride_2d + (z >> tds) * stride_3d; 464bf215546Sopenharmony_ci} 465bf215546Sopenharmony_ci 466bf215546Sopenharmony_ci/* Surface functions. 467bf215546Sopenharmony_ci */ 468bf215546Sopenharmony_ci 469bf215546Sopenharmony_cistruct nv50_surface * 470bf215546Sopenharmony_cinv50_surface_from_miptree(struct nv50_miptree *mt, 471bf215546Sopenharmony_ci const struct pipe_surface *templ) 472bf215546Sopenharmony_ci{ 473bf215546Sopenharmony_ci struct pipe_surface *ps; 474bf215546Sopenharmony_ci struct nv50_surface *ns = CALLOC_STRUCT(nv50_surface); 475bf215546Sopenharmony_ci if (!ns) 476bf215546Sopenharmony_ci return NULL; 477bf215546Sopenharmony_ci ps = &ns->base; 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_ci pipe_reference_init(&ps->reference, 1); 480bf215546Sopenharmony_ci pipe_resource_reference(&ps->texture, &mt->base.base); 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci ps->format = templ->format; 483bf215546Sopenharmony_ci ps->writable = templ->writable; 484bf215546Sopenharmony_ci ps->u.tex.level = templ->u.tex.level; 485bf215546Sopenharmony_ci ps->u.tex.first_layer = templ->u.tex.first_layer; 486bf215546Sopenharmony_ci ps->u.tex.last_layer = templ->u.tex.last_layer; 487bf215546Sopenharmony_ci 488bf215546Sopenharmony_ci ns->width = u_minify(mt->base.base.width0, ps->u.tex.level); 489bf215546Sopenharmony_ci ns->height = u_minify(mt->base.base.height0, ps->u.tex.level); 490bf215546Sopenharmony_ci ns->depth = ps->u.tex.last_layer - ps->u.tex.first_layer + 1; 491bf215546Sopenharmony_ci ns->offset = mt->level[templ->u.tex.level].offset; 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_ci /* comment says there are going to be removed, but they're used by the st */ 494bf215546Sopenharmony_ci ps->width = ns->width; 495bf215546Sopenharmony_ci ps->height = ns->height; 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci ns->width <<= mt->ms_x; 498bf215546Sopenharmony_ci ns->height <<= mt->ms_y; 499bf215546Sopenharmony_ci 500bf215546Sopenharmony_ci return ns; 501bf215546Sopenharmony_ci} 502bf215546Sopenharmony_ci 503bf215546Sopenharmony_cistruct pipe_surface * 504bf215546Sopenharmony_cinv50_miptree_surface_new(struct pipe_context *pipe, 505bf215546Sopenharmony_ci struct pipe_resource *pt, 506bf215546Sopenharmony_ci const struct pipe_surface *templ) 507bf215546Sopenharmony_ci{ 508bf215546Sopenharmony_ci struct nv50_miptree *mt = nv50_miptree(pt); 509bf215546Sopenharmony_ci struct nv50_surface *ns = nv50_surface_from_miptree(mt, templ); 510bf215546Sopenharmony_ci if (!ns) 511bf215546Sopenharmony_ci return NULL; 512bf215546Sopenharmony_ci ns->base.context = pipe; 513bf215546Sopenharmony_ci 514bf215546Sopenharmony_ci if (ns->base.u.tex.first_layer) { 515bf215546Sopenharmony_ci const unsigned l = ns->base.u.tex.level; 516bf215546Sopenharmony_ci const unsigned z = ns->base.u.tex.first_layer; 517bf215546Sopenharmony_ci 518bf215546Sopenharmony_ci if (mt->layout_3d) { 519bf215546Sopenharmony_ci ns->offset += nv50_mt_zslice_offset(mt, l, z); 520bf215546Sopenharmony_ci 521bf215546Sopenharmony_ci /* TODO: switch to depth 1 tiles; but actually this shouldn't happen */ 522bf215546Sopenharmony_ci if (ns->depth > 1 && 523bf215546Sopenharmony_ci (z & (NV50_TILE_SIZE_Z(mt->level[l].tile_mode) - 1))) 524bf215546Sopenharmony_ci NOUVEAU_ERR("Creating unsupported 3D surface !\n"); 525bf215546Sopenharmony_ci } else { 526bf215546Sopenharmony_ci ns->offset += mt->layer_stride * z; 527bf215546Sopenharmony_ci } 528bf215546Sopenharmony_ci } 529bf215546Sopenharmony_ci 530bf215546Sopenharmony_ci return &ns->base; 531bf215546Sopenharmony_ci} 532