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"
28 #include "nv_object.xml.h"
29 #include "nv30/nv30-40_3d.xml.h"
30 #include "nv30/nv30_context.h"
31 #include "nv30/nv30_format.h"
34 nv30_fragtex_validate(struct nv30_context
*nv30
)
36 struct pipe_screen
*pscreen
= &nv30
->screen
->base
.base
;
37 struct nouveau_object
*eng3d
= nv30
->screen
->eng3d
;
38 struct nouveau_pushbuf
*push
= nv30
->base
.pushbuf
;
39 unsigned dirty
= nv30
->fragprog
.dirty_samplers
;
42 unsigned unit
= ffs(dirty
) - 1;
43 struct nv30_sampler_view
*sv
= (void *)nv30
->fragprog
.textures
[unit
];
44 struct nv30_sampler_state
*ss
= nv30
->fragprog
.samplers
[unit
];
46 PUSH_RESET(push
, BUFCTX_FRAGTEX(unit
));
49 const struct nv30_texfmt
*fmt
= nv30_texfmt(pscreen
, sv
->pipe
.format
);
50 struct pipe_resource
*pt
= sv
->pipe
.texture
;
51 struct nv30_miptree
*mt
= nv30_miptree(pt
);
52 unsigned min_lod
, max_lod
;
53 u32 filter
= sv
->filt
| (ss
->filt
& sv
->filt_mask
);
54 u32 format
= sv
->fmt
| ss
->fmt
;
57 /* handle base_level when not using a mip filter, min/max level
58 * is unfortunately ignored by the hardware otherwise
60 if (ss
->pipe
.min_mip_filter
== PIPE_TEX_MIPFILTER_NONE
) {
62 filter
+= 0x00020000; /* N/L -> NMN/LMN */
63 max_lod
= sv
->base_lod
;
64 min_lod
= sv
->base_lod
;
66 max_lod
= MIN2(ss
->max_lod
+ sv
->base_lod
, sv
->high_lod
);
67 min_lod
= MIN2(ss
->min_lod
+ sv
->base_lod
, max_lod
);
70 if (eng3d
->oclass
>= NV40_3D_CLASS
) {
71 /* this is a tad stupid of the hardware, but there's no non-rcomp
72 * z16/z24 texture formats to be had, we have to suffer and lose
73 * some precision to handle this case.
75 if (ss
->pipe
.compare_mode
!= PIPE_TEX_COMPARE_R_TO_TEXTURE
) {
76 if (fmt
->nv40
== NV40_3D_TEX_FORMAT_FORMAT_Z16
)
77 format
|= NV40_3D_TEX_FORMAT_FORMAT_A8L8
;
79 if (fmt
->nv40
== NV40_3D_TEX_FORMAT_FORMAT_Z24
)
80 format
|= NV40_3D_TEX_FORMAT_FORMAT_A16L16
;
87 enable
|= (min_lod
<< 19) | (max_lod
<< 7);
88 enable
|= NV40_3D_TEX_ENABLE_ENABLE
;
90 BEGIN_NV04(push
, NV40_3D(TEX_SIZE1(unit
)), 1);
91 PUSH_DATA (push
, sv
->npot_size1
);
93 /* this is a tad stupid of the hardware, but there's no non-rcomp
94 * z16/z24 texture formats to be had, we have to suffer and lose
95 * some precision to handle this case.
97 if (ss
->pipe
.compare_mode
!= PIPE_TEX_COMPARE_R_TO_TEXTURE
) {
98 if (fmt
->nv30
== NV30_3D_TEX_FORMAT_FORMAT_Z16
) {
99 if (ss
->pipe
.normalized_coords
)
100 format
|= NV30_3D_TEX_FORMAT_FORMAT_A8L8
;
102 format
|= NV30_3D_TEX_FORMAT_FORMAT_A8L8_RECT
;
104 if (fmt
->nv30
== NV30_3D_TEX_FORMAT_FORMAT_Z24
) {
105 if (ss
->pipe
.normalized_coords
)
106 format
|= NV30_3D_TEX_FORMAT_FORMAT_HILO16
;
108 format
|= NV30_3D_TEX_FORMAT_FORMAT_HILO16_RECT
;
110 if (ss
->pipe
.normalized_coords
)
113 format
|= fmt
->nv30_rect
;
116 if (ss
->pipe
.normalized_coords
)
119 format
|= fmt
->nv30_rect
;
122 enable
|= NV30_3D_TEX_ENABLE_ENABLE
;
123 enable
|= (min_lod
<< 18) | (max_lod
<< 6);
126 BEGIN_NV04(push
, NV30_3D(TEX_OFFSET(unit
)), 8);
127 PUSH_MTHDl(push
, NV30_3D(TEX_OFFSET(unit
)), BUFCTX_FRAGTEX(unit
),
128 mt
->base
.bo
, 0, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
129 PUSH_MTHDs(push
, NV30_3D(TEX_FORMAT(unit
)), BUFCTX_FRAGTEX(unit
),
130 mt
->base
.bo
, format
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
,
131 NV30_3D_TEX_FORMAT_DMA0
,
132 NV30_3D_TEX_FORMAT_DMA1
);
133 PUSH_DATA (push
, sv
->wrap
| (ss
->wrap
& sv
->wrap_mask
));
134 PUSH_DATA (push
, enable
);
135 PUSH_DATA (push
, sv
->swz
);
136 PUSH_DATA (push
, filter
);
137 PUSH_DATA (push
, sv
->npot_size0
);
138 PUSH_DATA (push
, ss
->bcol
);
139 BEGIN_NV04(push
, NV30_3D(TEX_FILTER_OPTIMIZATION(unit
)), 1);
140 PUSH_DATA (push
, nv30
->config
.filter
);
142 BEGIN_NV04(push
, NV30_3D(TEX_ENABLE(unit
)), 1);
146 dirty
&= ~(1 << unit
);
149 nv30
->fragprog
.dirty_samplers
= 0;
153 nv30_fragtex_sampler_states_bind(struct pipe_context
*pipe
,
154 unsigned nr
, void **hwcso
)
156 struct nv30_context
*nv30
= nv30_context(pipe
);
159 for (i
= 0; i
< nr
; i
++) {
160 nv30
->fragprog
.samplers
[i
] = hwcso
[i
];
161 nv30
->fragprog
.dirty_samplers
|= (1 << i
);
164 for (; i
< nv30
->fragprog
.num_samplers
; i
++) {
165 nv30
->fragprog
.samplers
[i
] = NULL
;
166 nv30
->fragprog
.dirty_samplers
|= (1 << i
);
169 nv30
->fragprog
.num_samplers
= nr
;
170 nv30
->dirty
|= NV30_NEW_FRAGTEX
;
175 nv30_fragtex_set_sampler_views(struct pipe_context
*pipe
, unsigned nr
,
176 struct pipe_sampler_view
**views
)
178 struct nv30_context
*nv30
= nv30_context(pipe
);
181 for (i
= 0; i
< nr
; i
++) {
182 nouveau_bufctx_reset(nv30
->bufctx
, BUFCTX_FRAGTEX(i
));
183 pipe_sampler_view_reference(&nv30
->fragprog
.textures
[i
], views
[i
]);
184 nv30
->fragprog
.dirty_samplers
|= (1 << i
);
187 for (; i
< nv30
->fragprog
.num_textures
; i
++) {
188 nouveau_bufctx_reset(nv30
->bufctx
, BUFCTX_FRAGTEX(i
));
189 pipe_sampler_view_reference(&nv30
->fragprog
.textures
[i
], NULL
);
190 nv30
->fragprog
.dirty_samplers
|= (1 << i
);
193 nv30
->fragprog
.num_textures
= nr
;
194 nv30
->dirty
|= NV30_NEW_FRAGTEX
;
199 nv30_set_sampler_views(struct pipe_context
*pipe
, unsigned shader
,
200 unsigned start
, unsigned nr
,
201 struct pipe_sampler_view
**views
)
205 case PIPE_SHADER_FRAGMENT
:
206 nv30_fragtex_set_sampler_views(pipe
, nr
, views
);
208 case PIPE_SHADER_VERTEX
:
209 nv40_verttex_set_sampler_views(pipe
, nr
, views
);
218 nv30_fragtex_init(struct pipe_context
*pipe
)
220 pipe
->set_sampler_views
= nv30_set_sampler_views
;