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/format/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 enum pipe_shader_type 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
);
202 assert(!"unexpected shader type");
207 static inline uint32_t
208 swizzle(const struct nv30_texfmt
*fmt
, unsigned cmp
, unsigned swz
)
210 uint32_t data
= fmt
->swz
[swz
].src
<< 8;
211 if (swz
<= PIPE_SWIZZLE_W
)
212 data
|= fmt
->swz
[swz
].cmp
;
214 data
|= fmt
->swz
[cmp
].cmp
;
218 static struct pipe_sampler_view
*
219 nv30_sampler_view_create(struct pipe_context
*pipe
, struct pipe_resource
*pt
,
220 const struct pipe_sampler_view
*tmpl
)
222 const struct nv30_texfmt
*fmt
= nv30_texfmt(pipe
->screen
, tmpl
->format
);
223 struct nouveau_object
*eng3d
= nv30_context(pipe
)->screen
->eng3d
;
224 struct nv30_miptree
*mt
= nv30_miptree(pt
);
225 struct nv30_sampler_view
*so
;
227 so
= MALLOC_STRUCT(nv30_sampler_view
);
231 so
->pipe
.reference
.count
= 1;
232 so
->pipe
.texture
= NULL
;
233 so
->pipe
.context
= pipe
;
234 pipe_resource_reference(&so
->pipe
.texture
, pt
);
236 so
->fmt
= NV30_3D_TEX_FORMAT_NO_BORDER
;
237 switch (pt
->target
) {
238 case PIPE_TEXTURE_1D
:
239 so
->fmt
|= NV30_3D_TEX_FORMAT_DIMS_1D
;
241 case PIPE_TEXTURE_CUBE
:
242 so
->fmt
|= NV30_3D_TEX_FORMAT_CUBIC
;
243 case PIPE_TEXTURE_2D
:
244 case PIPE_TEXTURE_RECT
:
245 so
->fmt
|= NV30_3D_TEX_FORMAT_DIMS_2D
;
247 case PIPE_TEXTURE_3D
:
248 so
->fmt
|= NV30_3D_TEX_FORMAT_DIMS_3D
;
252 so
->fmt
|= NV30_3D_TEX_FORMAT_DIMS_1D
;
256 so
->filt
= fmt
->filter
;
257 so
->wrap
= fmt
->wrap
;
258 so
->swz
= fmt
->swizzle
;
259 so
->swz
|= swizzle(fmt
, 3, tmpl
->swizzle_a
);
260 so
->swz
|= swizzle(fmt
, 0, tmpl
->swizzle_r
) << 2;
261 so
->swz
|= swizzle(fmt
, 1, tmpl
->swizzle_g
) << 4;
262 so
->swz
|= swizzle(fmt
, 2, tmpl
->swizzle_b
) << 6;
264 /* apparently, we need to ignore the t coordinate for 1D textures to
265 * fix piglit tex1d-2dborder
268 if (pt
->target
== PIPE_TEXTURE_1D
) {
269 so
->wrap_mask
&= ~NV30_3D_TEX_WRAP_T__MASK
;
270 so
->wrap
|= NV30_3D_TEX_WRAP_T_REPEAT
;
273 /* yet more hardware suckage, can't filter 32-bit float formats */
274 switch (tmpl
->format
) {
275 case PIPE_FORMAT_R32_FLOAT
:
276 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
277 so
->filt_mask
= ~(NV30_3D_TEX_FILTER_MIN__MASK
|
278 NV30_3D_TEX_FILTER_MAG__MASK
);
279 so
->filt
|= NV30_3D_TEX_FILTER_MIN_NEAREST
|
280 NV30_3D_TEX_FILTER_MAG_NEAREST
;
287 so
->npot_size0
= (pt
->width0
<< 16) | pt
->height0
;
288 if (eng3d
->oclass
>= NV40_3D_CLASS
) {
289 so
->npot_size1
= (pt
->depth0
<< 20) | mt
->uniform_pitch
;
290 if (mt
->uniform_pitch
)
291 so
->fmt
|= NV40_3D_TEX_FORMAT_LINEAR
;
292 so
->fmt
|= 0x00008000;
293 so
->fmt
|= (pt
->last_level
+ 1) << NV40_3D_TEX_FORMAT_MIPMAP_COUNT__SHIFT
;
295 so
->swz
|= mt
->uniform_pitch
<< NV30_3D_TEX_SWIZZLE_RECT_PITCH__SHIFT
;
297 so
->fmt
|= NV30_3D_TEX_FORMAT_MIPMAP
;
298 so
->fmt
|= util_logbase2(pt
->width0
) << 20;
299 so
->fmt
|= util_logbase2(pt
->height0
) << 24;
300 so
->fmt
|= util_logbase2(pt
->depth0
) << 28;
301 so
->fmt
|= 0x00010000;
304 so
->base_lod
= so
->pipe
.u
.tex
.first_level
<< 8;
305 so
->high_lod
= MIN2(pt
->last_level
, so
->pipe
.u
.tex
.last_level
) << 8;
310 nv30_sampler_view_destroy(struct pipe_context
*pipe
,
311 struct pipe_sampler_view
*view
)
313 pipe_resource_reference(&view
->texture
, NULL
);
318 nv30_texture_init(struct pipe_context
*pipe
)
320 pipe
->create_sampler_state
= nv30_sampler_state_create
;
321 pipe
->delete_sampler_state
= nv30_sampler_state_delete
;
322 pipe
->bind_sampler_states
= nv30_bind_sampler_states
;
324 pipe
->create_sampler_view
= nv30_sampler_view_create
;
325 pipe
->sampler_view_destroy
= nv30_sampler_view_destroy
;