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