2 * Copyright 2012 Red Hat Inc.
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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
26 #include "util/u_inlines.h"
27 #include "util/u_format.h"
29 #include "nv_object.xml.h"
30 #include "nv30/nv30-40_3d.xml.h"
31 #include "nv30/nv30_context.h"
32 #include "nv30/nv30_format.h"
34 #define NV30_3D_TEX_WRAP_S_MIRROR_REPEAT NV30_3D_TEX_WRAP_S_MIRRORED_REPEAT
35 #define NV30_WRAP(n) \
36 case PIPE_TEX_WRAP_##n: ret = NV30_3D_TEX_WRAP_S_##n; break
37 #define NV40_WRAP(n) \
38 case PIPE_TEX_WRAP_##n: ret = NV40_3D_TEX_WRAP_S_##n; break
40 static INLINE
unsigned
41 wrap_mode(unsigned pipe
)
43 unsigned ret
= NV30_3D_TEX_WRAP_S_REPEAT
;
47 NV30_WRAP(MIRROR_REPEAT
);
48 NV30_WRAP(CLAMP_TO_EDGE
);
49 NV30_WRAP(CLAMP_TO_BORDER
);
51 NV40_WRAP(MIRROR_CLAMP_TO_EDGE
);
52 NV40_WRAP(MIRROR_CLAMP_TO_BORDER
);
53 NV40_WRAP(MIRROR_CLAMP
);
58 return ret
>> NV30_3D_TEX_WRAP_S__SHIFT
;
61 static INLINE
unsigned
62 filter_mode(const struct pipe_sampler_state
*cso
)
66 switch (cso
->mag_img_filter
) {
67 case PIPE_TEX_FILTER_LINEAR
:
68 filter
= NV30_3D_TEX_FILTER_MAG_LINEAR
;
71 filter
= NV30_3D_TEX_FILTER_MAG_NEAREST
;
75 switch (cso
->min_img_filter
) {
76 case PIPE_TEX_FILTER_LINEAR
:
77 switch (cso
->min_mip_filter
) {
78 case PIPE_TEX_MIPFILTER_NEAREST
:
79 filter
|= NV30_3D_TEX_FILTER_MIN_LINEAR_MIPMAP_NEAREST
;
81 case PIPE_TEX_MIPFILTER_LINEAR
:
82 filter
|= NV30_3D_TEX_FILTER_MIN_LINEAR_MIPMAP_LINEAR
;
85 filter
|= NV30_3D_TEX_FILTER_MIN_LINEAR
;
90 switch (cso
->min_mip_filter
) {
91 case PIPE_TEX_MIPFILTER_NEAREST
:
92 filter
|= NV30_3D_TEX_FILTER_MIN_NEAREST_MIPMAP_NEAREST
;
94 case PIPE_TEX_MIPFILTER_LINEAR
:
95 filter
|= NV30_3D_TEX_FILTER_MIN_NEAREST_MIPMAP_LINEAR
;
98 filter
|= NV30_3D_TEX_FILTER_MIN_NEAREST
;
107 static INLINE
unsigned
108 compare_mode(const struct pipe_sampler_state
*cso
)
110 if (cso
->compare_mode
!= PIPE_TEX_COMPARE_R_TO_TEXTURE
)
113 switch (cso
->compare_func
) {
114 case PIPE_FUNC_NEVER
: return NV30_3D_TEX_WRAP_RCOMP_NEVER
;
115 case PIPE_FUNC_GREATER
: return NV30_3D_TEX_WRAP_RCOMP_GREATER
;
116 case PIPE_FUNC_EQUAL
: return NV30_3D_TEX_WRAP_RCOMP_EQUAL
;
117 case PIPE_FUNC_GEQUAL
: return NV30_3D_TEX_WRAP_RCOMP_GEQUAL
;
118 case PIPE_FUNC_LESS
: return NV30_3D_TEX_WRAP_RCOMP_LESS
;
119 case PIPE_FUNC_NOTEQUAL
: return NV30_3D_TEX_WRAP_RCOMP_NOTEQUAL
;
120 case PIPE_FUNC_LEQUAL
: return NV30_3D_TEX_WRAP_RCOMP_LEQUAL
;
121 case PIPE_FUNC_ALWAYS
: return NV30_3D_TEX_WRAP_RCOMP_ALWAYS
;
128 nv30_sampler_state_create(struct pipe_context
*pipe
,
129 const struct pipe_sampler_state
*cso
)
131 struct nouveau_object
*eng3d
= nv30_context(pipe
)->screen
->eng3d
;
132 struct nv30_sampler_state
*so
;
133 const float max_lod
= 15.0 + (255.0 / 256.0);
135 so
= MALLOC_STRUCT(nv30_sampler_state
);
141 so
->wrap
= (wrap_mode(cso
->wrap_s
) << NV30_3D_TEX_WRAP_S__SHIFT
) |
142 (wrap_mode(cso
->wrap_t
) << NV30_3D_TEX_WRAP_T__SHIFT
) |
143 (wrap_mode(cso
->wrap_r
) << NV30_3D_TEX_WRAP_R__SHIFT
);
145 so
->wrap
|= compare_mode(cso
);
146 so
->filt
= filter_mode(cso
) | 0x00002000;
147 so
->bcol
= (float_to_ubyte(cso
->border_color
.f
[3]) << 24) |
148 (float_to_ubyte(cso
->border_color
.f
[0]) << 16) |
149 (float_to_ubyte(cso
->border_color
.f
[1]) << 8) |
150 (float_to_ubyte(cso
->border_color
.f
[2]) << 0);
152 if (eng3d
->oclass
>= NV40_3D_CLASS
) {
153 unsigned aniso
= cso
->max_anisotropy
;
155 if (!cso
->normalized_coords
)
156 so
->fmt
|= NV40_3D_TEX_FORMAT_RECT
;
159 if (aniso
>= 16) so
->en
|= NV40_3D_TEX_ENABLE_ANISO_16X
;
160 else if (aniso
>= 12) so
->en
|= NV40_3D_TEX_ENABLE_ANISO_12X
;
161 else if (aniso
>= 10) so
->en
|= NV40_3D_TEX_ENABLE_ANISO_10X
;
162 else if (aniso
>= 8) so
->en
|= NV40_3D_TEX_ENABLE_ANISO_8X
;
163 else if (aniso
>= 6) so
->en
|= NV40_3D_TEX_ENABLE_ANISO_6X
;
164 else if (aniso
>= 4) so
->en
|= NV40_3D_TEX_ENABLE_ANISO_4X
;
165 else so
->en
|= NV40_3D_TEX_ENABLE_ANISO_2X
;
167 so
->wrap
|= nv30_context(pipe
)->config
.aniso
;
170 so
->en
|= NV30_3D_TEX_ENABLE_ENABLE
;
172 if (cso
->max_anisotropy
>= 8) so
->en
|= NV30_3D_TEX_ENABLE_ANISO_8X
;
173 else if (cso
->max_anisotropy
>= 4) so
->en
|= NV30_3D_TEX_ENABLE_ANISO_4X
;
174 else if (cso
->max_anisotropy
>= 2) so
->en
|= NV30_3D_TEX_ENABLE_ANISO_2X
;
177 so
->filt
|= (int)(cso
->lod_bias
* 256.0) & 0x1fff;
178 so
->max_lod
= (int)(CLAMP(cso
->max_lod
, 0.0, max_lod
) * 256.0);
179 so
->min_lod
= (int)(CLAMP(cso
->min_lod
, 0.0, max_lod
) * 256.0);
184 nv30_sampler_state_delete(struct pipe_context
*pipe
, void *hwcso
)
190 nv30_bind_sampler_states(struct pipe_context
*pipe
,
191 unsigned shader
, unsigned start_slot
,
192 unsigned num_samplers
, void **samplers
)
195 case PIPE_SHADER_VERTEX
:
196 nv40_verttex_sampler_states_bind(pipe
, num_samplers
, samplers
);
198 case PIPE_SHADER_FRAGMENT
:
199 nv30_fragtex_sampler_states_bind(pipe
, num_samplers
, samplers
);
204 static INLINE
uint32_t
205 swizzle(const struct nv30_texfmt
*fmt
, unsigned cmp
, unsigned swz
)
207 uint32_t data
= fmt
->swz
[swz
].src
<< 8;
208 if (swz
<= PIPE_SWIZZLE_ALPHA
)
209 data
|= fmt
->swz
[swz
].cmp
;
211 data
|= fmt
->swz
[cmp
].cmp
;
215 static struct pipe_sampler_view
*
216 nv30_sampler_view_create(struct pipe_context
*pipe
, struct pipe_resource
*pt
,
217 const struct pipe_sampler_view
*tmpl
)
219 const struct nv30_texfmt
*fmt
= nv30_texfmt(pipe
->screen
, tmpl
->format
);
220 struct nouveau_object
*eng3d
= nv30_context(pipe
)->screen
->eng3d
;
221 struct nv30_miptree
*mt
= nv30_miptree(pt
);
222 struct nv30_sampler_view
*so
;
224 so
= MALLOC_STRUCT(nv30_sampler_view
);
228 so
->pipe
.reference
.count
= 1;
229 so
->pipe
.texture
= NULL
;
230 so
->pipe
.context
= pipe
;
231 pipe_resource_reference(&so
->pipe
.texture
, pt
);
233 so
->fmt
= NV30_3D_TEX_FORMAT_NO_BORDER
;
234 switch (pt
->target
) {
235 case PIPE_TEXTURE_1D
:
236 so
->fmt
|= NV30_3D_TEX_FORMAT_DIMS_1D
;
238 case PIPE_TEXTURE_CUBE
:
239 so
->fmt
|= NV30_3D_TEX_FORMAT_CUBIC
;
240 case PIPE_TEXTURE_2D
:
241 case PIPE_TEXTURE_RECT
:
242 so
->fmt
|= NV30_3D_TEX_FORMAT_DIMS_2D
;
244 case PIPE_TEXTURE_3D
:
245 so
->fmt
|= NV30_3D_TEX_FORMAT_DIMS_3D
;
249 so
->fmt
|= NV30_3D_TEX_FORMAT_DIMS_1D
;
253 so
->filt
= fmt
->filter
;
254 so
->wrap
= fmt
->wrap
;
255 so
->swz
= fmt
->swizzle
;
256 so
->swz
|= swizzle(fmt
, 3, tmpl
->swizzle_a
);
257 so
->swz
|= swizzle(fmt
, 0, tmpl
->swizzle_r
) << 2;
258 so
->swz
|= swizzle(fmt
, 1, tmpl
->swizzle_g
) << 4;
259 so
->swz
|= swizzle(fmt
, 2, tmpl
->swizzle_b
) << 6;
261 /* apparently, we need to ignore the t coordinate for 1D textures to
262 * fix piglit tex1d-2dborder
265 if (pt
->target
== PIPE_TEXTURE_1D
) {
266 so
->wrap_mask
&= ~NV30_3D_TEX_WRAP_T__MASK
;
267 so
->wrap
|= NV30_3D_TEX_WRAP_T_REPEAT
;
270 /* yet more hardware suckage, can't filter 32-bit float formats */
271 switch (tmpl
->format
) {
272 case PIPE_FORMAT_R32_FLOAT
:
273 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
274 so
->filt_mask
= ~(NV30_3D_TEX_FILTER_MIN__MASK
|
275 NV30_3D_TEX_FILTER_MAG__MASK
);
276 so
->filt
|= NV30_3D_TEX_FILTER_MIN_NEAREST
|
277 NV30_3D_TEX_FILTER_MAG_NEAREST
;
284 so
->npot_size0
= (pt
->width0
<< 16) | pt
->height0
;
285 if (eng3d
->oclass
>= NV40_3D_CLASS
) {
286 so
->npot_size1
= (pt
->depth0
<< 20) | mt
->uniform_pitch
;
288 so
->fmt
|= NV40_3D_TEX_FORMAT_LINEAR
;
289 so
->fmt
|= 0x00008000;
290 so
->fmt
|= (pt
->last_level
+ 1) << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT
;
292 so
->swz
|= mt
->uniform_pitch
<< NV30_3D_TEX_SWIZZLE_RECT_PITCH__SHIFT
;
294 so
->fmt
|= NV30_3D_TEX_FORMAT_MIPMAP
;
295 so
->fmt
|= util_logbase2(pt
->width0
) << 20;
296 so
->fmt
|= util_logbase2(pt
->height0
) << 24;
297 so
->fmt
|= util_logbase2(pt
->depth0
) << 28;
298 so
->fmt
|= 0x00010000;
301 so
->base_lod
= so
->pipe
.u
.tex
.first_level
<< 8;
302 so
->high_lod
= MIN2(pt
->last_level
, so
->pipe
.u
.tex
.last_level
) << 8;
307 nv30_sampler_view_destroy(struct pipe_context
*pipe
,
308 struct pipe_sampler_view
*view
)
310 pipe_resource_reference(&view
->texture
, NULL
);
315 nv30_texture_init(struct pipe_context
*pipe
)
317 pipe
->create_sampler_state
= nv30_sampler_state_create
;
318 pipe
->delete_sampler_state
= nv30_sampler_state_delete
;
319 pipe
->bind_sampler_states
= nv30_bind_sampler_states
;
321 pipe
->create_sampler_view
= nv30_sampler_view_create
;
322 pipe
->sampler_view_destroy
= nv30_sampler_view_destroy
;