2 * Copyright (C) 2009 Francisco Jerez.
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:
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.
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.
27 #include "nouveau_driver.h"
28 #include "nouveau_context.h"
29 #include "nouveau_util.h"
30 #include "nv_object.xml.h"
31 #include "nv04_3d.xml.h"
32 #include "nv04_driver.h"
35 get_comparison_op(unsigned op
)
60 get_stencil_op(unsigned op
)
85 get_texenv_mode(unsigned mode
)
100 get_blend_func(unsigned func
)
109 case GL_ONE_MINUS_SRC_COLOR
:
113 case GL_ONE_MINUS_SRC_ALPHA
:
117 case GL_ONE_MINUS_DST_ALPHA
:
121 case GL_ONE_MINUS_DST_COLOR
:
123 case GL_SRC_ALPHA_SATURATE
:
131 nv04_defer_control(struct gl_context
*ctx
, int emit
)
133 context_dirty(ctx
, CONTROL
);
137 nv04_emit_control(struct gl_context
*ctx
, int emit
)
139 struct nouveau_channel
*chan
= context_chan(ctx
);
140 struct nouveau_grobj
*fahrenheit
= nv04_context_engine(ctx
);
142 if (nv04_mtex_engine(fahrenheit
)) {
143 int cull_mode
= ctx
->Polygon
.CullFaceMode
;
144 int front_face
= ctx
->Polygon
.FrontFace
;
145 uint32_t ctrl0
= 1 << 30 |
146 NV04_MULTITEX_TRIANGLE_CONTROL0_ORIGIN_CORNER
;
147 uint32_t ctrl1
= 0, ctrl2
= 0;
150 if (ctx
->Color
.ColorMask
[0][RCOMP
])
151 ctrl0
|= NV04_MULTITEX_TRIANGLE_CONTROL0_RED_WRITE
;
152 if (ctx
->Color
.ColorMask
[0][GCOMP
])
153 ctrl0
|= NV04_MULTITEX_TRIANGLE_CONTROL0_GREEN_WRITE
;
154 if (ctx
->Color
.ColorMask
[0][BCOMP
])
155 ctrl0
|= NV04_MULTITEX_TRIANGLE_CONTROL0_BLUE_WRITE
;
156 if (ctx
->Color
.ColorMask
[0][ACOMP
])
157 ctrl0
|= NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_WRITE
;
160 if (ctx
->Color
.DitherFlag
)
161 ctrl0
|= NV04_MULTITEX_TRIANGLE_CONTROL0_DITHER_ENABLE
;
164 if (!ctx
->Polygon
.CullFlag
)
165 ctrl0
|= NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_NONE
;
166 else if (cull_mode
== GL_FRONT_AND_BACK
)
167 ctrl0
|= NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_BOTH
;
169 ctrl0
|= (cull_mode
== GL_FRONT
) ^ (front_face
== GL_CCW
) ?
170 NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_CW
:
171 NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_CCW
;
175 ctrl0
|= NV04_MULTITEX_TRIANGLE_CONTROL0_Z_ENABLE
;
178 ctrl0
|= NV04_MULTITEX_TRIANGLE_CONTROL0_Z_WRITE
;
180 ctrl0
|= get_comparison_op(ctx
->Depth
.Func
) << 16;
183 if (ctx
->Color
.AlphaEnabled
)
184 ctrl0
|= NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_ENABLE
;
186 ctrl0
|= get_comparison_op(ctx
->Color
.AlphaFunc
) << 8 |
187 FLOAT_TO_UBYTE(ctx
->Color
.AlphaRef
);
190 if (ctx
->Stencil
.WriteMask
[0])
191 ctrl0
|= NV04_MULTITEX_TRIANGLE_CONTROL0_STENCIL_WRITE
;
193 if (ctx
->Stencil
.Enabled
)
194 ctrl1
|= NV04_MULTITEX_TRIANGLE_CONTROL1_STENCIL_ENABLE
;
196 ctrl1
|= get_comparison_op(ctx
->Stencil
.Function
[0]) << 4 |
197 ctx
->Stencil
.Ref
[0] << 8 |
198 ctx
->Stencil
.ValueMask
[0] << 16 |
199 ctx
->Stencil
.WriteMask
[0] << 24;
201 ctrl2
|= get_stencil_op(ctx
->Stencil
.ZPassFunc
[0]) << 8 |
202 get_stencil_op(ctx
->Stencil
.ZFailFunc
[0]) << 4 |
203 get_stencil_op(ctx
->Stencil
.FailFunc
[0]);
205 BEGIN_RING(chan
, fahrenheit
, NV04_MULTITEX_TRIANGLE_CONTROL0
, 3);
206 OUT_RING(chan
, ctrl0
);
207 OUT_RING(chan
, ctrl1
);
208 OUT_RING(chan
, ctrl2
);
211 int cull_mode
= ctx
->Polygon
.CullFaceMode
;
212 int front_face
= ctx
->Polygon
.FrontFace
;
213 uint32_t ctrl
= 1 << 30 |
214 NV04_TEXTURED_TRIANGLE_CONTROL_ORIGIN_CORNER
;
217 if (ctx
->Color
.DitherFlag
)
218 ctrl
|= NV04_TEXTURED_TRIANGLE_CONTROL_DITHER_ENABLE
;
221 if (!ctx
->Polygon
.CullFlag
)
222 ctrl
|= NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_NONE
;
223 else if (cull_mode
== GL_FRONT_AND_BACK
)
224 ctrl
|= NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_BOTH
;
226 ctrl
|= (cull_mode
== GL_FRONT
) ^ (front_face
== GL_CCW
) ?
227 NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_CW
:
228 NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_CCW
;
232 ctrl
|= NV04_TEXTURED_TRIANGLE_CONTROL_Z_ENABLE
;
234 ctrl
|= NV04_TEXTURED_TRIANGLE_CONTROL_Z_WRITE
;
236 ctrl
|= get_comparison_op(ctx
->Depth
.Func
) << 16;
239 if (ctx
->Color
.AlphaEnabled
)
240 ctrl
|= NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_ENABLE
;
242 ctrl
|= get_comparison_op(ctx
->Color
.AlphaFunc
) << 8 |
243 FLOAT_TO_UBYTE(ctx
->Color
.AlphaRef
);
245 BEGIN_RING(chan
, fahrenheit
, NV04_TEXTURED_TRIANGLE_CONTROL
, 1);
246 OUT_RING(chan
, ctrl
);
251 nv04_defer_blend(struct gl_context
*ctx
, int emit
)
253 context_dirty(ctx
, BLEND
);
257 nv04_emit_blend(struct gl_context
*ctx
, int emit
)
259 struct nouveau_channel
*chan
= context_chan(ctx
);
260 struct nouveau_grobj
*fahrenheit
= nv04_context_engine(ctx
);
262 if (nv04_mtex_engine(fahrenheit
)) {
263 uint32_t blend
= 0x2 << 4 |
264 NV04_MULTITEX_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE
;
266 /* Alpha blending. */
267 blend
|= get_blend_func(ctx
->Color
.BlendDstRGB
) << 28 |
268 get_blend_func(ctx
->Color
.BlendSrcRGB
) << 24;
270 if (ctx
->Color
.BlendEnabled
)
271 blend
|= NV04_MULTITEX_TRIANGLE_BLEND_BLEND_ENABLE
;
274 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
)
275 blend
|= NV04_MULTITEX_TRIANGLE_BLEND_SHADE_MODE_GOURAUD
;
277 blend
|= NV04_MULTITEX_TRIANGLE_BLEND_SHADE_MODE_FLAT
;
279 /* Secondary color */
280 if (NEED_SECONDARY_COLOR(ctx
))
281 blend
|= NV04_MULTITEX_TRIANGLE_BLEND_SPECULAR_ENABLE
;
284 if (ctx
->Fog
.Enabled
)
285 blend
|= NV04_MULTITEX_TRIANGLE_BLEND_FOG_ENABLE
;
287 BEGIN_RING(chan
, fahrenheit
, NV04_MULTITEX_TRIANGLE_BLEND
, 1);
288 OUT_RING(chan
, blend
);
290 BEGIN_RING(chan
, fahrenheit
, NV04_MULTITEX_TRIANGLE_FOGCOLOR
, 1);
291 OUT_RING(chan
, pack_rgba_f(MESA_FORMAT_ARGB8888
,
295 uint32_t blend
= 0x2 << 4 |
296 NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE
;
298 /* Alpha blending. */
299 blend
|= get_blend_func(ctx
->Color
.BlendDstRGB
) << 28 |
300 get_blend_func(ctx
->Color
.BlendSrcRGB
) << 24;
302 if (ctx
->Color
.BlendEnabled
)
303 blend
|= NV04_TEXTURED_TRIANGLE_BLEND_BLEND_ENABLE
;
306 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
)
307 blend
|= NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_GOURAUD
;
309 blend
|= NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_FLAT
;
311 /* Texture environment. */
312 if (ctx
->Texture
._EnabledUnits
)
313 blend
|= get_texenv_mode(ctx
->Texture
.Unit
[0].EnvMode
);
315 blend
|= get_texenv_mode(GL_MODULATE
);
317 /* Secondary color */
318 if (NEED_SECONDARY_COLOR(ctx
))
319 blend
|= NV04_TEXTURED_TRIANGLE_BLEND_SPECULAR_ENABLE
;
322 if (ctx
->Fog
.Enabled
)
323 blend
|= NV04_TEXTURED_TRIANGLE_BLEND_FOG_ENABLE
;
325 BEGIN_RING(chan
, fahrenheit
, NV04_TEXTURED_TRIANGLE_BLEND
, 1);
326 OUT_RING(chan
, blend
);
328 BEGIN_RING(chan
, fahrenheit
, NV04_TEXTURED_TRIANGLE_FOGCOLOR
, 1);
329 OUT_RING(chan
, pack_rgba_f(MESA_FORMAT_ARGB8888
,