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 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 */ 22 23 #include "nv50_context.h" 24 #include "nv50_resource.h" 25 #include "nv50_texture.xml.h" 26 #include "nv50_defs.xml.h" 27 28 #include "util/u_format.h" 29 30 #define NV50_TIC_0_SWIZZLE__MASK \ 31 (NV50_TIC_0_MAPA__MASK | NV50_TIC_0_MAPB__MASK | \ 32 NV50_TIC_0_MAPG__MASK | NV50_TIC_0_MAPR__MASK) 33 34 static INLINE uint32_t 35 nv50_tic_swizzle(uint32_t tc, unsigned swz, boolean tex_int) 36 { 37 switch (swz) { 38 case PIPE_SWIZZLE_RED: 39 return (tc & NV50_TIC_0_MAPR__MASK) >> NV50_TIC_0_MAPR__SHIFT; 40 case PIPE_SWIZZLE_GREEN: 41 return (tc & NV50_TIC_0_MAPG__MASK) >> NV50_TIC_0_MAPG__SHIFT; 42 case PIPE_SWIZZLE_BLUE: 43 return (tc & NV50_TIC_0_MAPB__MASK) >> NV50_TIC_0_MAPB__SHIFT; 44 case PIPE_SWIZZLE_ALPHA: 45 return (tc & NV50_TIC_0_MAPA__MASK) >> NV50_TIC_0_MAPA__SHIFT; 46 case PIPE_SWIZZLE_ONE: 47 return tex_int ? NV50_TIC_MAP_ONE_INT : NV50_TIC_MAP_ONE_FLOAT; 48 case PIPE_SWIZZLE_ZERO: 49 default: 50 return NV50_TIC_MAP_ZERO; 51 } 52 } 53 54 static void 55 nv50_init_tic_entry_linear(uint32_t *tic, struct pipe_resource *res) 56 { 57 if (res->target == PIPE_BUFFER) { 58 tic[2] |= NV50_TIC_2_LINEAR | NV50_TIC_2_TARGET_BUFFER; 59 tic[4] = res->width0; 60 } else { 61 struct nv50_miptree *mt = nv50_miptree(res); 62 63 tic[2] |= NV50_TIC_2_LINEAR | NV50_TIC_2_TARGET_RECT; 64 if (res->target != PIPE_TEXTURE_RECT) 65 tic[2] |= NV50_TIC_2_NORMALIZED_COORDS; 66 tic[3] = mt->level[0].pitch; 67 tic[4] = res->width0; 68 tic[5] = (1 << 16) | res->height0; 69 } 70 } 71 72 struct pipe_sampler_view * 73 nv50_create_sampler_view(struct pipe_context *pipe, 74 struct pipe_resource *texture, 75 const struct pipe_sampler_view *templ) 76 { 77 const struct util_format_description *desc; 78 uint64_t addr; 79 uint32_t *tic; 80 uint32_t swz[4]; 81 uint32_t depth; 82 struct nv50_tic_entry *view; 83 struct nv50_miptree *mt = nv50_miptree(texture); 84 boolean tex_int; 85 86 view = MALLOC_STRUCT(nv50_tic_entry); 87 if (!view) 88 return NULL; 89 90 view->pipe = *templ; 91 view->pipe.reference.count = 1; 92 view->pipe.texture = NULL; 93 view->pipe.context = pipe; 94 95 view->id = -1; 96 97 pipe_resource_reference(&view->pipe.texture, texture); 98 99 tic = &view->tic[0]; 100 101 desc = util_format_description(view->pipe.format); 102 103 /* TIC[0] */ 104 105 tic[0] = nv50_format_table[view->pipe.format].tic; 106 107 tex_int = util_format_is_pure_integer(view->pipe.format); 108 109 swz[0] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_r, tex_int); 110 swz[1] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_g, tex_int); 111 swz[2] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_b, tex_int); 112 swz[3] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_a, tex_int); 113 tic[0] = (tic[0] & ~NV50_TIC_0_SWIZZLE__MASK) | 114 (swz[0] << NV50_TIC_0_MAPR__SHIFT) | 115 (swz[1] << NV50_TIC_0_MAPG__SHIFT) | 116 (swz[2] << NV50_TIC_0_MAPB__SHIFT) | 117 (swz[3] << NV50_TIC_0_MAPA__SHIFT); 118 119 addr = mt->base.address; 120 121 if (mt->base.base.target == PIPE_TEXTURE_1D_ARRAY || 122 mt->base.base.target == PIPE_TEXTURE_2D_ARRAY) { 123 addr += view->pipe.u.tex.first_layer * mt->layer_stride; 124 depth = view->pipe.u.tex.last_layer - view->pipe.u.tex.first_layer + 1; 125 } else { 126 depth = mt->base.base.depth0; 127 } 128 129 tic[1] = addr; 130 tic[2] = (addr >> 32) & 0xff; 131 132 tic[2] |= 0x10001000 | NV50_TIC_2_NO_BORDER; 133 134 if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) 135 tic[2] |= NV50_TIC_2_COLORSPACE_SRGB; 136 137 if (unlikely(!nouveau_bo_memtype(nv04_resource(texture)->bo))) { 138 nv50_init_tic_entry_linear(tic, texture); 139 return &view->pipe; 140 } 141 142 if (mt->base.base.target != PIPE_TEXTURE_RECT) 143 tic[2] |= NV50_TIC_2_NORMALIZED_COORDS; 144 145 tic[2] |= 146 ((mt->level[0].tile_mode & 0x0f0) << (22 - 4)) | 147 ((mt->level[0].tile_mode & 0xf00) << (25 - 8)); 148 149 switch (mt->base.base.target) { 150 case PIPE_TEXTURE_1D: 151 tic[2] |= NV50_TIC_2_TARGET_1D; 152 break; 153 case PIPE_TEXTURE_2D: 154 tic[2] |= NV50_TIC_2_TARGET_2D; 155 break; 156 case PIPE_TEXTURE_RECT: 157 tic[2] |= NV50_TIC_2_TARGET_RECT; 158 break; 159 case PIPE_TEXTURE_3D: 160 tic[2] |= NV50_TIC_2_TARGET_3D; 161 break; 162 case PIPE_TEXTURE_CUBE: 163 depth /= 6; 164 if (depth > 1) 165 tic[2] |= NV50_TIC_2_TARGET_CUBE_ARRAY; 166 else 167 tic[2] |= NV50_TIC_2_TARGET_CUBE; 168 break; 169 case PIPE_TEXTURE_1D_ARRAY: 170 tic[2] |= NV50_TIC_2_TARGET_1D_ARRAY; 171 break; 172 case PIPE_TEXTURE_2D_ARRAY: 173 tic[2] |= NV50_TIC_2_TARGET_2D_ARRAY; 174 break; 175 case PIPE_BUFFER: 176 assert(0); /* should be linear and handled above ! */ 177 tic[2] |= NV50_TIC_2_TARGET_BUFFER | NV50_TIC_2_LINEAR; 178 break; 179 default: 180 NOUVEAU_ERR("invalid texture target: %d\n", mt->base.base.target); 181 return FALSE; 182 } 183 184 tic[3] = 0x00300000; 185 186 tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x); 187 188 tic[5] = (mt->base.base.height0 << mt->ms_y) & 0xffff; 189 tic[5] |= depth << 16; 190 tic[5] |= mt->base.base.last_level << 28; 191 192 tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000; /* sampling points */ 193 194 tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level; 195 196 return &view->pipe; 197 } 198 199 static boolean 200 nv50_validate_tic(struct nv50_context *nv50, int s) 201 { 202 struct nouveau_pushbuf *push = nv50->base.pushbuf; 203 struct nouveau_bo *txc = nv50->screen->txc; 204 unsigned i; 205 boolean need_flush = FALSE; 206 207 for (i = 0; i < nv50->num_textures[s]; ++i) { 208 struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]); 209 struct nv04_resource *res; 210 211 if (!tic) { 212 BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1); 213 PUSH_DATA (push, (i << 1) | 0); 214 continue; 215 } 216 res = &nv50_miptree(tic->pipe.texture)->base; 217 218 if (tic->id < 0) { 219 tic->id = nv50_screen_tic_alloc(nv50->screen, tic); 220 221 BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2); 222 PUSH_DATA (push, NV50_SURFACE_FORMAT_R8_UNORM); 223 PUSH_DATA (push, 1); 224 BEGIN_NV04(push, NV50_2D(DST_PITCH), 5); 225 PUSH_DATA (push, 262144); 226 PUSH_DATA (push, 65536); 227 PUSH_DATA (push, 1); 228 PUSH_DATAh(push, txc->offset); 229 PUSH_DATA (push, txc->offset); 230 BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2); 231 PUSH_DATA (push, 0); 232 PUSH_DATA (push, NV50_SURFACE_FORMAT_R8_UNORM); 233 BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10); 234 PUSH_DATA (push, 32); 235 PUSH_DATA (push, 1); 236 PUSH_DATA (push, 0); 237 PUSH_DATA (push, 1); 238 PUSH_DATA (push, 0); 239 PUSH_DATA (push, 1); 240 PUSH_DATA (push, 0); 241 PUSH_DATA (push, tic->id * 32); 242 PUSH_DATA (push, 0); 243 PUSH_DATA (push, 0); 244 BEGIN_NI04(push, NV50_2D(SIFC_DATA), 8); 245 PUSH_DATAp(push, &tic->tic[0], 8); 246 247 need_flush = TRUE; 248 } else 249 if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) { 250 BEGIN_NV04(push, NV50_3D(TEX_CACHE_CTL), 1); 251 PUSH_DATA (push, 0x20); 252 } 253 254 nv50->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32); 255 256 res->status &= NOUVEAU_BUFFER_STATUS_GPU_WRITING; 257 res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; 258 259 BCTX_REFN(nv50->bufctx_3d, TEXTURES, res, RD); 260 261 BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1); 262 PUSH_DATA (push, (tic->id << 9) | (i << 1) | 1); 263 } 264 for (; i < nv50->state.num_textures[s]; ++i) { 265 BEGIN_NV04(push, NV50_3D(BIND_TIC(s)), 1); 266 PUSH_DATA (push, (i << 1) | 0); 267 } 268 nv50->state.num_textures[s] = nv50->num_textures[s]; 269 270 return need_flush; 271 } 272 273 void nv50_validate_textures(struct nv50_context *nv50) 274 { 275 boolean need_flush; 276 277 need_flush = nv50_validate_tic(nv50, 0); 278 need_flush |= nv50_validate_tic(nv50, 2); 279 280 if (need_flush) { 281 BEGIN_NV04(nv50->base.pushbuf, NV50_3D(TIC_FLUSH), 1); 282 PUSH_DATA (nv50->base.pushbuf, 0); 283 } 284 } 285 286 static boolean 287 nv50_validate_tsc(struct nv50_context *nv50, int s) 288 { 289 struct nouveau_pushbuf *push = nv50->base.pushbuf; 290 unsigned i; 291 boolean need_flush = FALSE; 292 293 for (i = 0; i < nv50->num_samplers[s]; ++i) { 294 struct nv50_tsc_entry *tsc = nv50_tsc_entry(nv50->samplers[s][i]); 295 296 if (!tsc) { 297 BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1); 298 PUSH_DATA (push, (i << 4) | 0); 299 continue; 300 } 301 if (tsc->id < 0) { 302 tsc->id = nv50_screen_tsc_alloc(nv50->screen, tsc); 303 304 nv50_sifc_linear_u8(&nv50->base, nv50->screen->txc, 305 65536 + tsc->id * 32, 306 NOUVEAU_BO_VRAM, 32, tsc->tsc); 307 need_flush = TRUE; 308 } 309 nv50->screen->tsc.lock[tsc->id / 32] |= 1 << (tsc->id % 32); 310 311 BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1); 312 PUSH_DATA (push, (tsc->id << 12) | (i << 4) | 1); 313 } 314 for (; i < nv50->state.num_samplers[s]; ++i) { 315 BEGIN_NV04(push, NV50_3D(BIND_TSC(s)), 1); 316 PUSH_DATA (push, (i << 4) | 0); 317 } 318 nv50->state.num_samplers[s] = nv50->num_samplers[s]; 319 320 return need_flush; 321 } 322 323 void nv50_validate_samplers(struct nv50_context *nv50) 324 { 325 boolean need_flush; 326 327 need_flush = nv50_validate_tsc(nv50, 0); 328 need_flush |= nv50_validate_tsc(nv50, 2); 329 330 if (need_flush) { 331 BEGIN_NV04(nv50->base.pushbuf, NV50_3D(TSC_FLUSH), 1); 332 PUSH_DATA (nv50->base.pushbuf, 0); 333 } 334 } 335