1 /*
2 * Copyright (C) 2009 Francisco Jerez.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 */
26
27 #include "nouveau_driver.h"
28 #include "nouveau_context.h"
29 #include "nouveau_gldefs.h"
30 #include "nouveau_texture.h"
31 #include "nv10_3d.xml.h"
32 #include "nouveau_util.h"
33 #include "nv10_driver.h"
34 #include "main/samplerobj.h"
35
36 void
nv10_emit_tex_gen(struct gl_context * ctx,int emit)37 nv10_emit_tex_gen(struct gl_context *ctx, int emit)
38 {
39 const int i = emit - NOUVEAU_STATE_TEX_GEN0;
40 struct nouveau_context *nctx = to_nouveau_context(ctx);
41 struct nouveau_pushbuf *push = context_push(ctx);
42 struct gl_fixedfunc_texture_unit *unit =
43 &ctx->Texture.FixedFuncUnit[i];
44 int j;
45
46 for (j = 0; j < 4; j++) {
47 if (nctx->fallback == HWTNL && (unit->TexGenEnabled & 1 << j)) {
48 struct gl_texgen *coord = get_texgen_coord(unit, j);
49 float *k = get_texgen_coeff(unit, coord->Mode, j);
50
51 if (k) {
52 BEGIN_NV04(push, NV10_3D(TEX_GEN_COEFF(i, j)), 4);
53 PUSH_DATAp(push, k, 4);
54 }
55
56 BEGIN_NV04(push, NV10_3D(TEX_GEN_MODE(i,j)), 1);
57 PUSH_DATA (push, nvgl_texgen_mode(coord->Mode));
58
59 } else {
60 BEGIN_NV04(push, NV10_3D(TEX_GEN_MODE(i,j)), 1);
61 PUSH_DATA (push, 0);
62 }
63 }
64
65 context_dirty_i(ctx, TEX_MAT, i);
66 }
67
68 void
nv10_emit_tex_mat(struct gl_context * ctx,int emit)69 nv10_emit_tex_mat(struct gl_context *ctx, int emit)
70 {
71 const int i = emit - NOUVEAU_STATE_TEX_MAT0;
72 struct nouveau_context *nctx = to_nouveau_context(ctx);
73 struct nouveau_pushbuf *push = context_push(ctx);
74
75 if (nctx->fallback == HWTNL &&
76 ((ctx->Texture._TexMatEnabled & 1 << i) ||
77 ctx->Texture.FixedFuncUnit[i]._GenFlags)) {
78 BEGIN_NV04(push, NV10_3D(TEX_MATRIX_ENABLE(i)), 1);
79 PUSH_DATA (push, 1);
80
81 BEGIN_NV04(push, NV10_3D(TEX_MATRIX(i, 0)), 16);
82 PUSH_DATAm(push, ctx->TextureMatrixStack[i].Top->m);
83
84 } else {
85 BEGIN_NV04(push, NV10_3D(TEX_MATRIX_ENABLE(i)), 1);
86 PUSH_DATA (push, 0);
87 }
88 }
89
90 static uint32_t
get_tex_format_pot(struct gl_texture_image * ti)91 get_tex_format_pot(struct gl_texture_image *ti)
92 {
93 switch (ti->TexFormat) {
94 case MESA_FORMAT_B8G8R8A8_UNORM:
95 return NV10_3D_TEX_FORMAT_FORMAT_A8R8G8B8;
96
97 case MESA_FORMAT_B8G8R8X8_UNORM:
98 return NV10_3D_TEX_FORMAT_FORMAT_X8R8G8B8;
99
100 case MESA_FORMAT_B5G5R5A1_UNORM:
101 return NV10_3D_TEX_FORMAT_FORMAT_A1R5G5B5;
102
103 case MESA_FORMAT_B4G4R4A4_UNORM:
104 return NV10_3D_TEX_FORMAT_FORMAT_A4R4G4B4;
105
106 case MESA_FORMAT_B5G6R5_UNORM:
107 return NV10_3D_TEX_FORMAT_FORMAT_R5G6B5;
108
109 case MESA_FORMAT_A_UNORM8:
110 case MESA_FORMAT_I_UNORM8:
111 return NV10_3D_TEX_FORMAT_FORMAT_I8;
112
113 case MESA_FORMAT_L_UNORM8:
114 return NV10_3D_TEX_FORMAT_FORMAT_L8;
115
116 case MESA_FORMAT_RGB_DXT1:
117 case MESA_FORMAT_RGBA_DXT1:
118 return NV10_3D_TEX_FORMAT_FORMAT_DXT1;
119
120 case MESA_FORMAT_RGBA_DXT3:
121 return NV10_3D_TEX_FORMAT_FORMAT_DXT3;
122
123 case MESA_FORMAT_RGBA_DXT5:
124 return NV10_3D_TEX_FORMAT_FORMAT_DXT5;
125
126 default:
127 assert(0);
128 }
129 }
130
131 static uint32_t
get_tex_format_rect(struct gl_texture_image * ti)132 get_tex_format_rect(struct gl_texture_image *ti)
133 {
134 switch (ti->TexFormat) {
135 case MESA_FORMAT_B5G5R5A1_UNORM:
136 return NV10_3D_TEX_FORMAT_FORMAT_A1R5G5B5_RECT;
137
138 case MESA_FORMAT_B5G6R5_UNORM:
139 return NV10_3D_TEX_FORMAT_FORMAT_R5G6B5_RECT;
140
141 case MESA_FORMAT_B8G8R8A8_UNORM:
142 case MESA_FORMAT_B8G8R8X8_UNORM:
143 return NV10_3D_TEX_FORMAT_FORMAT_A8R8G8B8_RECT;
144
145 case MESA_FORMAT_A_UNORM8:
146 case MESA_FORMAT_L_UNORM8:
147 case MESA_FORMAT_I_UNORM8:
148 return NV10_3D_TEX_FORMAT_FORMAT_I8_RECT;
149
150 default:
151 assert(0);
152 }
153 }
154
155 void
nv10_emit_tex_obj(struct gl_context * ctx,int emit)156 nv10_emit_tex_obj(struct gl_context *ctx, int emit)
157 {
158 const int i = emit - NOUVEAU_STATE_TEX_OBJ0;
159 struct nouveau_pushbuf *push = context_push(ctx);
160 const int bo_flags = NOUVEAU_BO_RD | NOUVEAU_BO_GART | NOUVEAU_BO_VRAM;
161 struct gl_texture_object *t;
162 struct nouveau_surface *s;
163 struct gl_texture_image *ti;
164 const struct gl_sampler_object *sa;
165 uint32_t tx_format, tx_filter, tx_enable;
166
167 PUSH_RESET(push, BUFCTX_TEX(i));
168
169 if (!ctx->Texture.Unit[i]._Current) {
170 BEGIN_NV04(push, NV10_3D(TEX_ENABLE(i)), 1);
171 PUSH_DATA (push, 0);
172 return;
173 }
174
175 t = ctx->Texture.Unit[i]._Current;
176 s = &to_nouveau_texture(t)->surfaces[t->Attrib.BaseLevel];
177 ti = t->Image[0][t->Attrib.BaseLevel];
178 sa = _mesa_get_samplerobj(ctx, i);
179
180 if (!nouveau_texture_validate(ctx, t))
181 return;
182
183 /* Recompute the texturing registers. */
184 tx_format = nvgl_wrap_mode(sa->Attrib.WrapT) << 28
185 | nvgl_wrap_mode(sa->Attrib.WrapS) << 24
186 | ti->HeightLog2 << 20
187 | ti->WidthLog2 << 16
188 | 5 << 4 | 1 << 12;
189
190 tx_filter = nvgl_filter_mode(sa->Attrib.MagFilter) << 28
191 | nvgl_filter_mode(sa->Attrib.MinFilter) << 24;
192
193 tx_enable = NV10_3D_TEX_ENABLE_ENABLE
194 | log2i(sa->Attrib.MaxAnisotropy) << 4;
195
196 if (t->Target == GL_TEXTURE_RECTANGLE) {
197 BEGIN_NV04(push, NV10_3D(TEX_NPOT_PITCH(i)), 1);
198 PUSH_DATA (push, s->pitch << 16);
199 BEGIN_NV04(push, NV10_3D(TEX_NPOT_SIZE(i)), 1);
200 PUSH_DATA (push, align(s->width, 2) << 16 | s->height);
201
202 tx_format |= get_tex_format_rect(ti);
203 } else {
204 tx_format |= get_tex_format_pot(ti);
205 }
206
207 if (sa->Attrib.MinFilter != GL_NEAREST &&
208 sa->Attrib.MinFilter != GL_LINEAR) {
209 int lod_min = sa->Attrib.MinLod;
210 int lod_max = MIN2(sa->Attrib.MaxLod, t->_MaxLambda);
211 int lod_bias = sa->Attrib.LodBias
212 + ctx->Texture.Unit[i].LodBias;
213
214 lod_max = CLAMP(lod_max, 0, 15);
215 lod_min = CLAMP(lod_min, 0, 15);
216 lod_bias = CLAMP(lod_bias, 0, 15);
217
218 tx_format |= NV10_3D_TEX_FORMAT_MIPMAP;
219 tx_filter |= lod_bias << 8;
220 tx_enable |= lod_min << 26
221 | lod_max << 14;
222 }
223
224 /* Write it to the hardware. */
225 BEGIN_NV04(push, NV10_3D(TEX_FORMAT(i)), 1);
226 PUSH_MTHD (push, NV10_3D(TEX_FORMAT(i)), BUFCTX_TEX(i),
227 s->bo, tx_format, bo_flags | NOUVEAU_BO_OR,
228 NV10_3D_TEX_FORMAT_DMA0,
229 NV10_3D_TEX_FORMAT_DMA1);
230
231 BEGIN_NV04(push, NV10_3D(TEX_OFFSET(i)), 1);
232 PUSH_MTHDl(push, NV10_3D(TEX_OFFSET(i)), BUFCTX_TEX(i),
233 s->bo, s->offset, bo_flags);
234
235 BEGIN_NV04(push, NV10_3D(TEX_FILTER(i)), 1);
236 PUSH_DATA (push, tx_filter);
237
238 BEGIN_NV04(push, NV10_3D(TEX_ENABLE(i)), 1);
239 PUSH_DATA (push, tx_enable);
240 }
241
242