2 * Copyright 2008 Ben Skeggs
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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
23 #include "nv50_context.h"
24 #include "nv50_resource.h"
25 #include "nv50_texture.xml.h"
26 #include "nv50_defs.xml.h"
28 #include "util/u_format.h"
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)
34 static INLINE
uint32_t
35 nv50_tic_swizzle(uint32_t tc
, unsigned swz
, boolean tex_int
)
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
:
50 return NV50_TIC_MAP_ZERO
;
54 struct pipe_sampler_view
*
55 nv50_create_sampler_view(struct pipe_context
*pipe
,
56 struct pipe_resource
*res
,
57 const struct pipe_sampler_view
*templ
)
61 if (res
->target
== PIPE_TEXTURE_RECT
|| res
->target
== PIPE_BUFFER
)
62 flags
|= NV50_TEXVIEW_SCALED_COORDS
;
64 return nv50_create_texture_view(pipe
, res
, templ
, flags
, res
->target
);
67 struct pipe_sampler_view
*
68 nv50_create_texture_view(struct pipe_context
*pipe
,
69 struct pipe_resource
*texture
,
70 const struct pipe_sampler_view
*templ
,
72 enum pipe_texture_target target
)
74 const struct util_format_description
*desc
;
79 struct nv50_tic_entry
*view
;
80 struct nv50_miptree
*mt
= nv50_miptree(texture
);
83 view
= MALLOC_STRUCT(nv50_tic_entry
);
88 view
->pipe
.reference
.count
= 1;
89 view
->pipe
.texture
= NULL
;
90 view
->pipe
.context
= pipe
;
94 pipe_resource_reference(&view
->pipe
.texture
, texture
);
98 desc
= util_format_description(view
->pipe
.format
);
102 tic
[0] = nv50_format_table
[view
->pipe
.format
].tic
;
104 tex_int
= util_format_is_pure_integer(view
->pipe
.format
);
106 swz
[0] = nv50_tic_swizzle(tic
[0], view
->pipe
.swizzle_r
, tex_int
);
107 swz
[1] = nv50_tic_swizzle(tic
[0], view
->pipe
.swizzle_g
, tex_int
);
108 swz
[2] = nv50_tic_swizzle(tic
[0], view
->pipe
.swizzle_b
, tex_int
);
109 swz
[3] = nv50_tic_swizzle(tic
[0], view
->pipe
.swizzle_a
, tex_int
);
110 tic
[0] = (tic
[0] & ~NV50_TIC_0_SWIZZLE__MASK
) |
111 (swz
[0] << NV50_TIC_0_MAPR__SHIFT
) |
112 (swz
[1] << NV50_TIC_0_MAPG__SHIFT
) |
113 (swz
[2] << NV50_TIC_0_MAPB__SHIFT
) |
114 (swz
[3] << NV50_TIC_0_MAPA__SHIFT
);
116 addr
= mt
->base
.address
;
118 if (mt
->base
.base
.target
== PIPE_TEXTURE_1D_ARRAY
||
119 mt
->base
.base
.target
== PIPE_TEXTURE_2D_ARRAY
) {
120 addr
+= view
->pipe
.u
.tex
.first_layer
* mt
->layer_stride
;
121 depth
= view
->pipe
.u
.tex
.last_layer
- view
->pipe
.u
.tex
.first_layer
+ 1;
123 depth
= mt
->base
.base
.depth0
;
126 tic
[2] = 0x10001000 | NV50_TIC_2_NO_BORDER
;
128 if (desc
->colorspace
== UTIL_FORMAT_COLORSPACE_SRGB
)
129 tic
[2] |= NV50_TIC_2_COLORSPACE_SRGB
;
131 if (!(flags
& NV50_TEXVIEW_SCALED_COORDS
))
132 tic
[2] |= NV50_TIC_2_NORMALIZED_COORDS
;
134 if (unlikely(!nouveau_bo_memtype(nv04_resource(texture
)->bo
))) {
135 if (target
== PIPE_BUFFER
) {
136 addr
+= view
->pipe
.u
.buf
.first_element
* desc
->block
.bits
/ 8;
137 tic
[2] |= NV50_TIC_2_LINEAR
| NV50_TIC_2_TARGET_BUFFER
;
140 view
->pipe
.u
.buf
.last_element
- view
->pipe
.u
.buf
.first_element
+ 1;
143 tic
[2] |= NV50_TIC_2_LINEAR
| NV50_TIC_2_TARGET_RECT
;
144 tic
[3] = mt
->level
[0].pitch
;
145 tic
[4] = mt
->base
.base
.width0
;
146 tic
[5] = (1 << 16) | mt
->base
.base
.height0
;
151 tic
[2] |= addr
>> 32;
156 tic
[2] |= (addr
>> 32) & 0xff;
159 ((mt
->level
[0].tile_mode
& 0x0f0) << (22 - 4)) |
160 ((mt
->level
[0].tile_mode
& 0xf00) << (25 - 8));
163 case PIPE_TEXTURE_1D
:
164 tic
[2] |= NV50_TIC_2_TARGET_1D
;
166 case PIPE_TEXTURE_2D
:
167 tic
[2] |= NV50_TIC_2_TARGET_2D
;
169 case PIPE_TEXTURE_RECT
:
170 tic
[2] |= NV50_TIC_2_TARGET_RECT
;
172 case PIPE_TEXTURE_3D
:
173 tic
[2] |= NV50_TIC_2_TARGET_3D
;
175 case PIPE_TEXTURE_CUBE
:
177 tic
[2] |= NV50_TIC_2_TARGET_CUBE
;
179 case PIPE_TEXTURE_1D_ARRAY
:
180 tic
[2] |= NV50_TIC_2_TARGET_1D_ARRAY
;
182 case PIPE_TEXTURE_2D_ARRAY
:
183 tic
[2] |= NV50_TIC_2_TARGET_2D_ARRAY
;
185 case PIPE_TEXTURE_CUBE_ARRAY
:
187 tic
[2] |= NV50_TIC_2_TARGET_CUBE_ARRAY
;
190 assert(0); /* should be linear and handled above ! */
191 tic
[2] |= NV50_TIC_2_TARGET_BUFFER
| NV50_TIC_2_LINEAR
;
194 NOUVEAU_ERR("invalid texture target: %d\n", mt
->base
.base
.target
);
198 tic
[3] = (flags
& NV50_TEXVIEW_FILTER_MSAA8
) ? 0x20000000 : 0x00300000;
200 tic
[4] = (1 << 31) | (mt
->base
.base
.width0
<< mt
->ms_x
);
202 tic
[5] = (mt
->base
.base
.height0
<< mt
->ms_y
) & 0xffff;
203 tic
[5] |= depth
<< 16;
204 tic
[5] |= mt
->base
.base
.last_level
<< NV50_TIC_5_LAST_LEVEL__SHIFT
;
206 tic
[6] = (mt
->ms_x
> 1) ? 0x88000000 : 0x03000000; /* sampling points */
208 tic
[7] = (view
->pipe
.u
.tex
.last_level
<< 4) | view
->pipe
.u
.tex
.first_level
;
210 if (unlikely(!(tic
[2] & NV50_TIC_2_NORMALIZED_COORDS
)))
211 if (mt
->base
.base
.last_level
)
212 tic
[5] &= ~NV50_TIC_5_LAST_LEVEL__MASK
;
218 nv50_validate_tic(struct nv50_context
*nv50
, int s
)
220 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
221 struct nouveau_bo
*txc
= nv50
->screen
->txc
;
223 boolean need_flush
= FALSE
;
225 for (i
= 0; i
< nv50
->num_textures
[s
]; ++i
) {
226 struct nv50_tic_entry
*tic
= nv50_tic_entry(nv50
->textures
[s
][i
]);
227 struct nv04_resource
*res
;
230 BEGIN_NV04(push
, NV50_3D(BIND_TIC(s
)), 1);
231 PUSH_DATA (push
, (i
<< 1) | 0);
234 res
= &nv50_miptree(tic
->pipe
.texture
)->base
;
237 tic
->id
= nv50_screen_tic_alloc(nv50
->screen
, tic
);
239 BEGIN_NV04(push
, NV50_2D(DST_FORMAT
), 2);
240 PUSH_DATA (push
, NV50_SURFACE_FORMAT_R8_UNORM
);
242 BEGIN_NV04(push
, NV50_2D(DST_PITCH
), 5);
243 PUSH_DATA (push
, 262144);
244 PUSH_DATA (push
, 65536);
246 PUSH_DATAh(push
, txc
->offset
);
247 PUSH_DATA (push
, txc
->offset
);
248 BEGIN_NV04(push
, NV50_2D(SIFC_BITMAP_ENABLE
), 2);
250 PUSH_DATA (push
, NV50_SURFACE_FORMAT_R8_UNORM
);
251 BEGIN_NV04(push
, NV50_2D(SIFC_WIDTH
), 10);
252 PUSH_DATA (push
, 32);
259 PUSH_DATA (push
, tic
->id
* 32);
262 BEGIN_NI04(push
, NV50_2D(SIFC_DATA
), 8);
263 PUSH_DATAp(push
, &tic
->tic
[0], 8);
267 if (res
->status
& NOUVEAU_BUFFER_STATUS_GPU_WRITING
) {
268 BEGIN_NV04(push
, NV50_3D(TEX_CACHE_CTL
), 1);
269 PUSH_DATA (push
, 0x20);
272 nv50
->screen
->tic
.lock
[tic
->id
/ 32] |= 1 << (tic
->id
% 32);
274 res
->status
&= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
275 res
->status
|= NOUVEAU_BUFFER_STATUS_GPU_READING
;
277 BCTX_REFN(nv50
->bufctx_3d
, TEXTURES
, res
, RD
);
279 BEGIN_NV04(push
, NV50_3D(BIND_TIC(s
)), 1);
280 PUSH_DATA (push
, (tic
->id
<< 9) | (i
<< 1) | 1);
282 for (; i
< nv50
->state
.num_textures
[s
]; ++i
) {
283 BEGIN_NV04(push
, NV50_3D(BIND_TIC(s
)), 1);
284 PUSH_DATA (push
, (i
<< 1) | 0);
286 nv50
->state
.num_textures
[s
] = nv50
->num_textures
[s
];
291 void nv50_validate_textures(struct nv50_context
*nv50
)
295 need_flush
= nv50_validate_tic(nv50
, 0);
296 need_flush
|= nv50_validate_tic(nv50
, 2);
299 BEGIN_NV04(nv50
->base
.pushbuf
, NV50_3D(TIC_FLUSH
), 1);
300 PUSH_DATA (nv50
->base
.pushbuf
, 0);
305 nv50_validate_tsc(struct nv50_context
*nv50
, int s
)
307 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
309 boolean need_flush
= FALSE
;
311 for (i
= 0; i
< nv50
->num_samplers
[s
]; ++i
) {
312 struct nv50_tsc_entry
*tsc
= nv50_tsc_entry(nv50
->samplers
[s
][i
]);
315 BEGIN_NV04(push
, NV50_3D(BIND_TSC(s
)), 1);
316 PUSH_DATA (push
, (i
<< 4) | 0);
320 tsc
->id
= nv50_screen_tsc_alloc(nv50
->screen
, tsc
);
322 nv50_sifc_linear_u8(&nv50
->base
, nv50
->screen
->txc
,
323 65536 + tsc
->id
* 32,
324 NOUVEAU_BO_VRAM
, 32, tsc
->tsc
);
327 nv50
->screen
->tsc
.lock
[tsc
->id
/ 32] |= 1 << (tsc
->id
% 32);
329 BEGIN_NV04(push
, NV50_3D(BIND_TSC(s
)), 1);
330 PUSH_DATA (push
, (tsc
->id
<< 12) | (i
<< 4) | 1);
332 for (; i
< nv50
->state
.num_samplers
[s
]; ++i
) {
333 BEGIN_NV04(push
, NV50_3D(BIND_TSC(s
)), 1);
334 PUSH_DATA (push
, (i
<< 4) | 0);
336 nv50
->state
.num_samplers
[s
] = nv50
->num_samplers
[s
];
341 void nv50_validate_samplers(struct nv50_context
*nv50
)
345 need_flush
= nv50_validate_tsc(nv50
, 0);
346 need_flush
|= nv50_validate_tsc(nv50
, 2);
349 BEGIN_NV04(nv50
->base
.pushbuf
, NV50_3D(TSC_FLUSH
), 1);
350 PUSH_DATA (nv50
->base
.pushbuf
, 0);