nv50_tex.c revision 0a3f0ff2645d03d5f572cc26932595b8df400505
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 34static INLINE uint32_t 35nv50_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 54static void 55nv50_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 72struct pipe_sampler_view * 73nv50_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 uint32_t *tic; 79 uint32_t swz[4]; 80 uint32_t depth; 81 struct nv50_tic_entry *view; 82 struct nv50_miptree *mt = nv50_miptree(texture); 83 boolean tex_int; 84 85 view = MALLOC_STRUCT(nv50_tic_entry); 86 if (!view) 87 return NULL; 88 89 view->pipe = *templ; 90 view->pipe.reference.count = 1; 91 view->pipe.texture = NULL; 92 view->pipe.context = pipe; 93 94 view->id = -1; 95 96 pipe_resource_reference(&view->pipe.texture, texture); 97 98 tic = &view->tic[0]; 99 100 desc = util_format_description(view->pipe.format); 101 102 /* TIC[0] */ 103 104 tic[0] = nv50_format_table[view->pipe.format].tic; 105 106 tex_int = FALSE; /* XXX: integer textures */ 107 108 swz[0] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_r, tex_int); 109 swz[1] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_g, tex_int); 110 swz[2] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_b, tex_int); 111 swz[3] = nv50_tic_swizzle(tic[0], view->pipe.swizzle_a, tex_int); 112 tic[0] = (tic[0] & ~NV50_TIC_0_SWIZZLE__MASK) | 113 (swz[0] << NV50_TIC_0_MAPR__SHIFT) | 114 (swz[1] << NV50_TIC_0_MAPG__SHIFT) | 115 (swz[2] << NV50_TIC_0_MAPB__SHIFT) | 116 (swz[3] << NV50_TIC_0_MAPA__SHIFT); 117 118 tic[1] = /* mt->base.bo->offset; */ 0; 119 tic[2] = /* mt->base.bo->offset >> 32 */ 0; 120 121 tic[2] |= 0x10001000 | NV50_TIC_2_NO_BORDER; 122 123 if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) 124 tic[2] |= NV50_TIC_2_COLORSPACE_SRGB; 125 126 if (unlikely(!nouveau_bo_tile_layout(nv04_resource(texture)->bo))) { 127 nv50_init_tic_entry_linear(tic, texture); 128 return &view->pipe; 129 } 130 131 if (mt->base.base.target != PIPE_TEXTURE_RECT) 132 tic[2] |= NV50_TIC_2_NORMALIZED_COORDS; 133 134 tic[2] |= 135 ((mt->base.bo->tile_mode & 0x0f) << (22 - 0)) | 136 ((mt->base.bo->tile_mode & 0xf0) << (25 - 4)); 137 138 depth = MAX2(mt->base.base.array_size, mt->base.base.depth0); 139 140 if (mt->base.base.target == PIPE_TEXTURE_1D_ARRAY || 141 mt->base.base.target == PIPE_TEXTURE_2D_ARRAY) { 142 tic[1] = view->pipe.u.tex.first_layer * mt->layer_stride; 143 depth = view->pipe.u.tex.last_layer - view->pipe.u.tex.first_layer + 1; 144 } 145 146 switch (mt->base.base.target) { 147 case PIPE_TEXTURE_1D: 148 tic[2] |= NV50_TIC_2_TARGET_1D; 149 break; 150 case PIPE_TEXTURE_2D: 151 tic[2] |= NV50_TIC_2_TARGET_2D; 152 break; 153 case PIPE_TEXTURE_RECT: 154 tic[2] |= NV50_TIC_2_TARGET_RECT; 155 break; 156 case PIPE_TEXTURE_3D: 157 tic[2] |= NV50_TIC_2_TARGET_3D; 158 break; 159 case PIPE_TEXTURE_CUBE: 160 depth /= 6; 161 if (depth > 1) 162 tic[2] |= NV50_TIC_2_TARGET_CUBE_ARRAY; 163 else 164 tic[2] |= NV50_TIC_2_TARGET_CUBE; 165 break; 166 case PIPE_TEXTURE_1D_ARRAY: 167 tic[2] |= NV50_TIC_2_TARGET_1D_ARRAY; 168 break; 169 case PIPE_TEXTURE_2D_ARRAY: 170 tic[2] |= NV50_TIC_2_TARGET_2D_ARRAY; 171 break; 172 case PIPE_BUFFER: 173 assert(0); /* should be linear and handled above ! */ 174 tic[2] |= NV50_TIC_2_TARGET_BUFFER | NV50_TIC_2_LINEAR; 175 break; 176 default: 177 NOUVEAU_ERR("invalid texture target: %d\n", mt->base.base.target); 178 return FALSE; 179 } 180 181 tic[3] = 0x00300000; 182 183 tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x); 184 185 tic[5] = (mt->base.base.height0 << mt->ms_y) & 0xffff; 186 tic[5] |= depth << 16; 187 tic[5] |= mt->base.base.last_level << 28; 188 189 tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000; /* sampling points */ 190 191 tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level; 192 193 return &view->pipe; 194} 195 196static boolean 197nv50_validate_tic(struct nv50_context *nv50, int s) 198{ 199 struct nouveau_channel *chan = nv50->screen->base.channel; 200 struct nouveau_bo *txc = nv50->screen->txc; 201 unsigned i; 202 boolean need_flush = FALSE; 203 204 for (i = 0; i < nv50->num_textures[s]; ++i) { 205 struct nv50_tic_entry *tic = nv50_tic_entry(nv50->textures[s][i]); 206 struct nv04_resource *res; 207 208 if (!tic) { 209 BEGIN_RING(chan, RING_3D(BIND_TIC(s)), 1); 210 OUT_RING (chan, (i << 1) | 0); 211 continue; 212 } 213 res = &nv50_miptree(tic->pipe.texture)->base; 214 215 if (tic->id < 0) { 216 uint32_t offset = tic->tic[1]; 217 218 tic->id = nv50_screen_tic_alloc(nv50->screen, tic); 219 220 MARK_RING (chan, 24 + 8, 4); 221 BEGIN_RING(chan, RING_2D(DST_FORMAT), 2); 222 OUT_RING (chan, NV50_SURFACE_FORMAT_R8_UNORM); 223 OUT_RING (chan, 1); 224 BEGIN_RING(chan, RING_2D(DST_PITCH), 5); 225 OUT_RING (chan, 262144); 226 OUT_RING (chan, 65536); 227 OUT_RING (chan, 1); 228 OUT_RELOCh(chan, txc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); 229 OUT_RELOCl(chan, txc, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); 230 BEGIN_RING(chan, RING_2D(SIFC_BITMAP_ENABLE), 2); 231 OUT_RING (chan, 0); 232 OUT_RING (chan, NV50_SURFACE_FORMAT_R8_UNORM); 233 BEGIN_RING(chan, RING_2D(SIFC_WIDTH), 10); 234 OUT_RING (chan, 32); 235 OUT_RING (chan, 1); 236 OUT_RING (chan, 0); 237 OUT_RING (chan, 1); 238 OUT_RING (chan, 0); 239 OUT_RING (chan, 1); 240 OUT_RING (chan, 0); 241 OUT_RING (chan, tic->id * 32); 242 OUT_RING (chan, 0); 243 OUT_RING (chan, 0); 244 BEGIN_RING_NI(chan, RING_2D(SIFC_DATA), 8); 245 OUT_RING (chan, tic->tic[0]); 246 OUT_RELOCl(chan, res->bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); 247 OUT_RELOC (chan, res->bo, offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD | 248 NOUVEAU_BO_HIGH | NOUVEAU_BO_OR, tic->tic[2], tic->tic[2]); 249 OUT_RINGp (chan, &tic->tic[3], 5); 250 251 need_flush = TRUE; 252 } else 253 if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) { 254 BEGIN_RING(chan, RING_3D(TEX_CACHE_CTL), 1); 255 OUT_RING (chan, 0x20); //(tic->id << 4) | 1); 256 } 257 258 nv50->screen->tic.lock[tic->id / 32] |= 1 << (tic->id % 32); 259 260 res->status &= NOUVEAU_BUFFER_STATUS_GPU_WRITING; 261 res->status |= NOUVEAU_BUFFER_STATUS_GPU_READING; 262 263 nv50_bufctx_add_resident(nv50, NV50_BUFCTX_TEXTURES, res, 264 NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); 265 266 BEGIN_RING(chan, RING_3D(BIND_TIC(s)), 1); 267 OUT_RING (chan, (tic->id << 9) | (i << 1) | 1); 268 } 269 for (; i < nv50->state.num_textures[s]; ++i) { 270 BEGIN_RING(chan, RING_3D(BIND_TIC(s)), 1); 271 OUT_RING (chan, (i << 1) | 0); 272 } 273 nv50->state.num_textures[s] = nv50->num_textures[s]; 274 275 return need_flush; 276} 277 278void nv50_validate_textures(struct nv50_context *nv50) 279{ 280 boolean need_flush; 281 282 need_flush = nv50_validate_tic(nv50, 0); 283 need_flush |= nv50_validate_tic(nv50, 2); 284 285 if (need_flush) { 286 BEGIN_RING(nv50->screen->base.channel, RING_3D(TIC_FLUSH), 1); 287 OUT_RING (nv50->screen->base.channel, 0); 288 } 289} 290 291static boolean 292nv50_validate_tsc(struct nv50_context *nv50, int s) 293{ 294 struct nouveau_channel *chan = nv50->screen->base.channel; 295 unsigned i; 296 boolean need_flush = FALSE; 297 298 for (i = 0; i < nv50->num_samplers[s]; ++i) { 299 struct nv50_tsc_entry *tsc = nv50_tsc_entry(nv50->samplers[s][i]); 300 301 if (!tsc) { 302 BEGIN_RING(chan, RING_3D(BIND_TSC(s)), 1); 303 OUT_RING (chan, (i << 4) | 0); 304 continue; 305 } 306 if (tsc->id < 0) { 307 tsc->id = nv50_screen_tsc_alloc(nv50->screen, tsc); 308 309 nv50_sifc_linear_u8(&nv50->base, nv50->screen->txc, 310 65536 + tsc->id * 32, 311 NOUVEAU_BO_VRAM, 32, tsc->tsc); 312 need_flush = TRUE; 313 } 314 nv50->screen->tsc.lock[tsc->id / 32] |= 1 << (tsc->id % 32); 315 316 BEGIN_RING(chan, RING_3D(BIND_TSC(s)), 1); 317 OUT_RING (chan, (tsc->id << 12) | (i << 4) | 1); 318 } 319 for (; i < nv50->state.num_samplers[s]; ++i) { 320 BEGIN_RING(chan, RING_3D(BIND_TSC(s)), 1); 321 OUT_RING (chan, (i << 4) | 0); 322 } 323 nv50->state.num_samplers[s] = nv50->num_samplers[s]; 324 325 return need_flush; 326} 327 328void nv50_validate_samplers(struct nv50_context *nv50) 329{ 330 boolean need_flush; 331 332 need_flush = nv50_validate_tsc(nv50, 0); 333 need_flush |= nv50_validate_tsc(nv50, 2); 334 335 if (need_flush) { 336 BEGIN_RING(nv50->screen->base.channel, RING_3D(TSC_FLUSH), 1); 337 OUT_RING (nv50->screen->base.channel, 0); 338 } 339} 340