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