1/* 2 * Copyright 2008 Ben Skeggs 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23#include "nv50/nv50_context.h" 24#include "nv50/nv50_resource.h" 25#include "nv50/g80_texture.xml.h" 26#include "nv50/g80_defs.xml.h" 27 28#include "util/u_format.h" 29 30static inline uint32_t 31nv50_tic_swizzle(const struct nv50_format *fmt, unsigned swz, bool tex_int) 32{ 33 switch (swz) { 34 case PIPE_SWIZZLE_X : return fmt->tic.src_x; 35 case PIPE_SWIZZLE_Y: return fmt->tic.src_y; 36 case PIPE_SWIZZLE_Z : return fmt->tic.src_z; 37 case PIPE_SWIZZLE_W: return fmt->tic.src_w; 38 case PIPE_SWIZZLE_1: 39 return tex_int ? G80_TIC_SOURCE_ONE_INT : G80_TIC_SOURCE_ONE_FLOAT; 40 case PIPE_SWIZZLE_0: 41 default: 42 return G80_TIC_SOURCE_ZERO; 43 } 44} 45 46struct pipe_sampler_view * 47nv50_create_sampler_view(struct pipe_context *pipe, 48 struct pipe_resource *res, 49 const struct pipe_sampler_view *templ) 50{ 51 uint32_t flags = 0; 52 53 if (templ->target == PIPE_TEXTURE_RECT || templ->target == PIPE_BUFFER) 54 flags |= NV50_TEXVIEW_SCALED_COORDS; 55 56 return nv50_create_texture_view(pipe, res, templ, flags, templ->target); 57} 58 59struct pipe_sampler_view * 60nv50_create_texture_view(struct pipe_context *pipe, 61 struct pipe_resource *texture, 62 const struct pipe_sampler_view *templ, 63 uint32_t flags, 64 enum pipe_texture_target target) 65{ 66 const uint32_t class_3d = nouveau_context(pipe)->screen->class_3d; 67 const struct util_format_description *desc; 68 const struct nv50_format *fmt; 69 uint64_t addr; 70 uint32_t *tic; 71 uint32_t swz[4]; 72 uint32_t depth; 73 struct nv50_tic_entry *view; 74 struct nv50_miptree *mt = nv50_miptree(texture); 75 bool tex_int; 76 77 view = MALLOC_STRUCT(nv50_tic_entry); 78 if (!view) 79 return NULL; 80 81 view->pipe = *templ; 82 view->pipe.reference.count = 1; 83 view->pipe.texture = NULL; 84 view->pipe.context = pipe; 85 86 view->id = -1; 87 88 pipe_resource_reference(&view->pipe.texture, texture); 89 90 tic = &view->tic[0]; 91 92 desc = util_format_description(view->pipe.format); 93 94 /* TIC[0] */ 95 96 fmt = &nv50_format_table[view->pipe.format]; 97 98 tex_int = util_format_is_pure_integer(view->pipe.format); 99 100 swz[0] = nv50_tic_swizzle(fmt, view->pipe.swizzle_r, tex_int); 101 swz[1] = nv50_tic_swizzle(fmt, view->pipe.swizzle_g, tex_int); 102 swz[2] = nv50_tic_swizzle(fmt, view->pipe.swizzle_b, tex_int); 103 swz[3] = nv50_tic_swizzle(fmt, view->pipe.swizzle_a, tex_int); 104 tic[0] = (fmt->tic.format << G80_TIC_0_COMPONENTS_SIZES__SHIFT) | 105 (fmt->tic.type_r << G80_TIC_0_R_DATA_TYPE__SHIFT) | 106 (fmt->tic.type_g << G80_TIC_0_G_DATA_TYPE__SHIFT) | 107 (fmt->tic.type_b << G80_TIC_0_B_DATA_TYPE__SHIFT) | 108 (fmt->tic.type_a << G80_TIC_0_A_DATA_TYPE__SHIFT) | 109 (swz[0] << G80_TIC_0_X_SOURCE__SHIFT) | 110 (swz[1] << G80_TIC_0_Y_SOURCE__SHIFT) | 111 (swz[2] << G80_TIC_0_Z_SOURCE__SHIFT) | 112 (swz[3] << G80_TIC_0_W_SOURCE__SHIFT); 113 114 addr = mt->base.address; 115 116 depth = MAX2(mt->base.base.array_size, mt->base.base.depth0); 117 118 if (mt->base.base.array_size > 1) { 119 /* there doesn't seem to be a base layer field in TIC */ 120 addr += view->pipe.u.tex.first_layer * mt->layer_stride; 121 depth = view->pipe.u.tex.last_layer - view->pipe.u.tex.first_layer + 1; 122 } 123 124 tic[2] = 0x10001000 | G80_TIC_2_BORDER_SOURCE_COLOR; 125 126 if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) 127 tic[2] |= G80_TIC_2_SRGB_CONVERSION; 128 129 if (!(flags & NV50_TEXVIEW_SCALED_COORDS)) 130 tic[2] |= G80_TIC_2_NORMALIZED_COORDS; 131 132 if (unlikely(!nouveau_bo_memtype(nv04_resource(texture)->bo))) { 133 if (target == PIPE_BUFFER) { 134 addr += view->pipe.u.buf.offset; 135 tic[2] |= G80_TIC_2_LAYOUT_PITCH | G80_TIC_2_TEXTURE_TYPE_ONE_D_BUFFER; 136 tic[3] = 0; 137 tic[4] = /* width */ 138 view->pipe.u.buf.size / (desc->block.bits / 8); 139 tic[5] = 0; 140 } else { 141 tic[2] |= G80_TIC_2_LAYOUT_PITCH | G80_TIC_2_TEXTURE_TYPE_TWO_D_NO_MIPMAP; 142 tic[3] = mt->level[0].pitch; 143 tic[4] = mt->base.base.width0; 144 tic[5] = (1 << 16) | (mt->base.base.height0); 145 } 146 tic[6] = 147 tic[7] = 0; 148 tic[1] = addr; 149 tic[2] |= addr >> 32; 150 return &view->pipe; 151 } 152 153 tic[1] = addr; 154 tic[2] |= (addr >> 32) & 0xff; 155 156 tic[2] |= 157 ((mt->level[0].tile_mode & 0x0f0) << (22 - 4)) | 158 ((mt->level[0].tile_mode & 0xf00) << (25 - 8)); 159 160 switch (target) { 161 case PIPE_TEXTURE_1D: 162 tic[2] |= G80_TIC_2_TEXTURE_TYPE_ONE_D; 163 break; 164 case PIPE_TEXTURE_2D: 165 tic[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D; 166 break; 167 case PIPE_TEXTURE_RECT: 168 tic[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D_NO_MIPMAP; 169 break; 170 case PIPE_TEXTURE_3D: 171 tic[2] |= G80_TIC_2_TEXTURE_TYPE_THREE_D; 172 break; 173 case PIPE_TEXTURE_CUBE: 174 depth /= 6; 175 tic[2] |= G80_TIC_2_TEXTURE_TYPE_CUBEMAP; 176 break; 177 case PIPE_TEXTURE_1D_ARRAY: 178 tic[2] |= G80_TIC_2_TEXTURE_TYPE_ONE_D_ARRAY; 179 break; 180 case PIPE_TEXTURE_2D_ARRAY: 181 tic[2] |= G80_TIC_2_TEXTURE_TYPE_TWO_D_ARRAY; 182 break; 183 case PIPE_TEXTURE_CUBE_ARRAY: 184 depth /= 6; 185 tic[2] |= G80_TIC_2_TEXTURE_TYPE_CUBE_ARRAY; 186 break; 187 case PIPE_BUFFER: 188 assert(0); /* should be linear and handled above ! */ 189 tic[2] |= G80_TIC_2_TEXTURE_TYPE_ONE_D_BUFFER | G80_TIC_2_LAYOUT_PITCH; 190 break; 191 default: 192 unreachable("unexpected/invalid texture target"); 193 } 194 195 tic[3] = (flags & NV50_TEXVIEW_FILTER_MSAA8) ? 0x20000000 : 0x00300000; 196 197 tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x); 198 199 tic[5] = (mt->base.base.height0 << mt->ms_y) & 0xffff; 200 tic[5] |= depth << 16; 201 if (class_3d > NV50_3D_CLASS) 202 tic[5] |= mt->base.base.last_level << G80_TIC_5_MAP_MIP_LEVEL__SHIFT; 203 else 204 tic[5] |= view->pipe.u.tex.last_level << G80_TIC_5_MAP_MIP_LEVEL__SHIFT; 205 206 tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000; /* sampling points */ 207 208 if (class_3d > NV50_3D_CLASS) 209 tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level; 210 else 211 tic[7] = 0; 212 213 if (unlikely(!(tic[2] & G80_TIC_2_NORMALIZED_COORDS))) 214 if (mt->base.base.last_level) 215 tic[5] &= ~G80_TIC_5_MAP_MIP_LEVEL__MASK; 216 217 return &view->pipe; 218} 219 220static void 221nv50_update_tic(struct nv50_context *nv50, struct nv50_tic_entry *tic, 222 struct nv04_resource *res) 223{ 224 uint64_t address = res->address; 225 if (res->base.target != PIPE_BUFFER) 226 return; 227 address += tic->pipe.u.buf.offset; 228 if (tic->tic[1] == (uint32_t)address && 229 (tic->tic[2] & 0xff) == address >> 32) 230 return; 231 232 nv50_screen_tic_unlock(nv50->screen, tic); 233 tic->id = -1; 234 tic->tic[1] = address; 235 tic->tic[2] &= 0xffffff00; 236 tic->tic[2] |= address >> 32; 237} 238 239static bool 240nv50_validate_tic(struct nv50_context *nv50, int s) 241{ 242 struct nouveau_pushbuf *push = nv50->base.pushbuf; 243 struct nouveau_bo *txc = nv50->screen->txc; 244 unsigned i; 245 bool need_flush = false; 246 247 assert(nv50->num_textures[s] <= PIPE_MAX_SAMPLERS); 248 for (i = 0; i < nv50->num_textures[s]; ++i) { 249 struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]); 250 struct nv04_resource *res; 251 252 if (!tic) { 253 BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1); 254 PUSH_DATA (push, (i << 1) | 0); 255 continue; 256 } 257 res = &nv50_miptree(tic->pipe.texture)->base; 258 nv50_update_tic(nv50, tic, res); 259 260 if (tic->id < 0) { 261 tic->id = nv50_screen_tic_alloc(nv50->screen, tic); 262 263 BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2); 264 PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM); 265 PUSH_DATA (push, 1); 266 BEGIN_NV04(push, NV50_2D(DST_PITCH), 5); 267 PUSH_DATA (push, 262144); 268 PUSH_DATA (push, 65536); 269 PUSH_DATA (push, 1); 270 PUSH_DATAh(push, txc->offset); 271 PUSH_DATA (push, txc->offset); 272 BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2); 273 PUSH_DATA (push, 0); 274 PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM); 275 BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10); 276 PUSH_DATA (push, 32); 277 PUSH_DATA (push, 1); 278 PUSH_DATA (push, 0); 279 PUSH_DATA (push, 1); 280 PUSH_DATA (push, 0); 281 PUSH_DATA (push, 1); 282 PUSH_DATA (push, 0); 283 PUSH_DATA (push, tic->id * 32); 284 PUSH_DATA (push, 0); 285 PUSH_DATA (push, 0); 286 BEGIN_NI04(push, NV50_2D(SIFC_DATA), 8); 287 PUSH_DATAp(push, &tic->tic[0], 8); 288 289 need_flush = true; 290 } else 291 if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) { 292 BEGIN_NV04(push, NV50_3D(TEX_CACHE_CTL), 1); 293 PUSH_DATA (push, 0x20); 294 } 295 296 nv50->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32); 297 298 res->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING; 299 res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; 300 301 BCTX_REFN(nv50->bufctx_3d, 3D_TEXTURES, res, RD); 302 303 BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1); 304 PUSH_DATA (push, (tic->id << 9) | (i << 1) | 1); 305 } 306 for (; i < nv50->state.num_textures[s]; ++i) { 307 BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1); 308 PUSH_DATA (push, (i << 1) | 0); 309 } 310 if (nv50->num_textures[s]) { 311 BEGIN_NV04(push, NV50_3D(CB_ADDR), 1); 312 PUSH_DATA (push, ((NV50_CB_AUX_TEX_MS_OFFSET + 16 * s * 2 * 4) << (8 - 2)) | NV50_CB_AUX); 313 BEGIN_NI04(push, NV50_3D(CB_DATA(0)), nv50->num_textures[s] * 2); 314 for (i = 0; i < nv50->num_textures[s]; i++) { 315 struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]); 316 struct nv50_miptree *res; 317 318 if (!tic) { 319 PUSH_DATA (push, 0); 320 PUSH_DATA (push, 0); 321 continue; 322 } 323 res = nv50_miptree(tic->pipe.texture); 324 PUSH_DATA (push, res->ms_x); 325 PUSH_DATA (push, res->ms_y); 326 } 327 } 328 nv50->state.num_textures[s] = nv50->num_textures[s]; 329 330 return need_flush; 331} 332 333void nv50_validate_textures(struct nv50_context *nv50) 334{ 335 bool need_flush; 336 337 need_flush = nv50_validate_tic(nv50, 0); 338 need_flush |= nv50_validate_tic(nv50, 1); 339 need_flush |= nv50_validate_tic(nv50, 2); 340 341 if (need_flush) { 342 BEGIN_NV04(nv50->base.pushbuf, NV50_3D(TIC_FLUSH), 1); 343 PUSH_DATA (nv50->base.pushbuf, 0); 344 } 345} 346 347static bool 348nv50_validate_tsc(struct nv50_context *nv50, int s) 349{ 350 struct nouveau_pushbuf *push = nv50->base.pushbuf; 351 unsigned i; 352 bool need_flush = false; 353 354 assert(nv50->num_samplers[s] <= PIPE_MAX_SAMPLERS); 355 for (i = 0; i < nv50->num_samplers[s]; ++i) { 356 struct nv50_tsc_entry *tsc = nv50_tsc_entry(nv50->samplers[s][i]); 357 358 if (!tsc) { 359 BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1); 360 PUSH_DATA (push, (i << 4) | 0); 361 continue; 362 } 363 nv50->seamless_cube_map = tsc->seamless_cube_map; 364 if (tsc->id < 0) { 365 tsc->id = nv50_screen_tsc_alloc(nv50->screen, tsc); 366 367 nv50_sifc_linear_u8(&nv50->base, nv50->screen->txc, 368 65536 + tsc->id * 32, 369 NOUVEAU_BO_VRAM, 32, tsc->tsc); 370 need_flush = true; 371 } 372 nv50->screen->tsc.lock[tsc->id / 32] |= 1 << (tsc->id % 32); 373 374 BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1); 375 PUSH_DATA (push, (tsc->id << 12) | (i << 4) | 1); 376 } 377 for (; i < nv50->state.num_samplers[s]; ++i) { 378 BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1); 379 PUSH_DATA (push, (i << 4) | 0); 380 } 381 nv50->state.num_samplers[s] = nv50->num_samplers[s]; 382 383 // TXF, in unlinked tsc mode, will always use sampler 0. So we have to 384 // ensure that it remains bound. Its contents don't matter, all samplers we 385 // ever create have the SRGB_CONVERSION bit set, so as long as the first 386 // entry is initialized, we're good to go. This is the only bit that has 387 // any effect on what TXF does. 388 if (!nv50->samplers[s][0]) { 389 BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1); 390 PUSH_DATA (push, 1); 391 } 392 393 return need_flush; 394} 395 396void nv50_validate_samplers(struct nv50_context *nv50) 397{ 398 bool need_flush; 399 400 need_flush = nv50_validate_tsc(nv50, 0); 401 need_flush |= nv50_validate_tsc(nv50, 1); 402 need_flush |= nv50_validate_tsc(nv50, 2); 403 404 if (need_flush) { 405 BEGIN_NV04(nv50->base.pushbuf, NV50_3D(TSC_FLUSH), 1); 406 PUSH_DATA (nv50->base.pushbuf, 0); 407 } 408} 409 410/* There can be up to 4 different MS levels (1, 2, 4, 8). To simplify the 411 * shader logic, allow each one to take up 8 offsets. 412 */ 413#define COMBINE(x, y) x, y 414#define DUMMY 0, 0 415static const uint32_t msaa_sample_xy_offsets[] = { 416 /* MS1 */ 417 COMBINE(0, 0), 418 DUMMY, 419 DUMMY, 420 DUMMY, 421 DUMMY, 422 DUMMY, 423 DUMMY, 424 DUMMY, 425 426 /* MS2 */ 427 COMBINE(0, 0), 428 COMBINE(1, 0), 429 DUMMY, 430 DUMMY, 431 DUMMY, 432 DUMMY, 433 DUMMY, 434 DUMMY, 435 436 /* MS4 */ 437 COMBINE(0, 0), 438 COMBINE(1, 0), 439 COMBINE(0, 1), 440 COMBINE(1, 1), 441 DUMMY, 442 DUMMY, 443 DUMMY, 444 DUMMY, 445 446 /* MS8 */ 447 COMBINE(0, 0), 448 COMBINE(1, 0), 449 COMBINE(0, 1), 450 COMBINE(1, 1), 451 COMBINE(2, 0), 452 COMBINE(3, 0), 453 COMBINE(2, 1), 454 COMBINE(3, 1), 455}; 456 457void nv50_upload_ms_info(struct nouveau_pushbuf *push) 458{ 459 BEGIN_NV04(push, NV50_3D(CB_ADDR), 1); 460 PUSH_DATA (push, (NV50_CB_AUX_MS_OFFSET << (8 - 2)) | NV50_CB_AUX); 461 BEGIN_NI04(push, NV50_3D(CB_DATA(0)), ARRAY_SIZE(msaa_sample_xy_offsets)); 462 PUSH_DATAp(push, msaa_sample_xy_offsets, ARRAY_SIZE(msaa_sample_xy_offsets)); 463} 464 465void nv50_upload_tsc0(struct nv50_context *nv50) 466{ 467 struct nouveau_pushbuf *push = nv50->base.pushbuf; 468 u32 data[8] = { G80_TSC_0_SRGB_CONVERSION }; 469 nv50_sifc_linear_u8(&nv50->base, nv50->screen->txc, 470 65536 /* + tsc->id * 32 */, 471 NOUVEAU_BO_VRAM, 32, data); 472 BEGIN_NV04(push, NV50_3D(TSC_FLUSH), 1); 473 PUSH_DATA (push, 0); 474} 475