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