Merge branch 'gallium-nopointsizeminmax'
[mesa.git] / src / mesa / drivers / dri / nouveau / nv04_state_raster.c
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_util.h"
30 #include "nouveau_class.h"
31 #include "nv04_driver.h"
32
33 static unsigned
34 get_comparison_op(unsigned op)
35 {
36 switch (op) {
37 case GL_NEVER:
38 return 0x1;
39 case GL_LESS:
40 return 0x2;
41 case GL_EQUAL:
42 return 0x3;
43 case GL_LEQUAL:
44 return 0x4;
45 case GL_GREATER:
46 return 0x5;
47 case GL_NOTEQUAL:
48 return 0x6;
49 case GL_GEQUAL:
50 return 0x7;
51 case GL_ALWAYS:
52 return 0x8;
53 default:
54 assert(0);
55 }
56 }
57
58 static unsigned
59 get_stencil_op(unsigned op)
60 {
61 switch (op) {
62 case GL_KEEP:
63 return 0x1;
64 case GL_INCR:
65 return 0x4;
66 case GL_DECR:
67 return 0x5;
68 case GL_INVERT:
69 return 0x6;
70 default:
71 assert(0);
72 }
73 }
74
75 static unsigned
76 get_texenv_mode(unsigned mode)
77 {
78 switch (mode) {
79 case GL_REPLACE:
80 return 0x1;
81 case GL_ADD:
82 return 0x2;
83 case GL_DECAL:
84 return 0x3;
85 case GL_MODULATE:
86 return 0x4;
87 default:
88 assert(0);
89 }
90 }
91
92 static unsigned
93 get_blend_func(unsigned func)
94 {
95 switch (func) {
96 case GL_ZERO:
97 return 0x1;
98 case GL_ONE:
99 return 0x2;
100 case GL_SRC_COLOR:
101 return 0x3;
102 case GL_ONE_MINUS_SRC_COLOR:
103 return 0x4;
104 case GL_SRC_ALPHA:
105 return 0x5;
106 case GL_ONE_MINUS_SRC_ALPHA:
107 return 0x6;
108 case GL_DST_ALPHA:
109 return 0x7;
110 case GL_ONE_MINUS_DST_ALPHA:
111 return 0x8;
112 case GL_DST_COLOR:
113 return 0x9;
114 case GL_ONE_MINUS_DST_COLOR:
115 return 0xa;
116 case GL_SRC_ALPHA_SATURATE:
117 return 0xb;
118 default:
119 assert(0);
120 }
121 }
122
123 void
124 nv04_defer_control(GLcontext *ctx, int emit)
125 {
126 context_dirty(ctx, CONTROL);
127 }
128
129 void
130 nv04_emit_control(GLcontext *ctx, int emit)
131 {
132 struct nouveau_channel *chan = context_chan(ctx);
133 struct nouveau_grobj *fahrenheit = nv04_context_engine(ctx);
134
135 if (nv04_mtex_engine(fahrenheit)) {
136 int cull_mode = ctx->Polygon.CullFaceMode;
137 int front_face = ctx->Polygon.FrontFace;
138 uint32_t ctrl0 = 1 << 30 |
139 NV04_MULTITEX_TRIANGLE_CONTROL0_ORIGIN;
140 uint32_t ctrl1 = 0, ctrl2 = 0;
141
142 /* Color mask. */
143 if (ctx->Color.ColorMask[0][RCOMP])
144 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_RED_WRITE;
145 if (ctx->Color.ColorMask[0][GCOMP])
146 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_GREEN_WRITE;
147 if (ctx->Color.ColorMask[0][BCOMP])
148 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_BLUE_WRITE;
149 if (ctx->Color.ColorMask[0][ACOMP])
150 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_WRITE;
151
152 /* Dithering. */
153 if (ctx->Color.DitherFlag)
154 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_DITHER_ENABLE;
155
156 /* Cull mode. */
157 if (!ctx->Polygon.CullFlag)
158 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_NONE;
159 else if (cull_mode == GL_FRONT_AND_BACK)
160 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_BOTH;
161 else
162 ctrl0 |= (cull_mode == GL_FRONT) ^ (front_face == GL_CCW) ?
163 NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_CW :
164 NV04_MULTITEX_TRIANGLE_CONTROL0_CULL_MODE_CCW;
165
166 /* Depth test. */
167 if (ctx->Depth.Test)
168 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_Z_ENABLE;
169
170 if (ctx->Depth.Mask)
171 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_Z_WRITE;
172
173 ctrl0 |= get_comparison_op(ctx->Depth.Func) << 16;
174
175 /* Alpha test. */
176 if (ctx->Color.AlphaEnabled)
177 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_ALPHA_ENABLE;
178
179 ctrl0 |= get_comparison_op(ctx->Color.AlphaFunc) << 8 |
180 FLOAT_TO_UBYTE(ctx->Color.AlphaRef);
181
182 /* Stencil test. */
183 if (ctx->Stencil.WriteMask[0])
184 ctrl0 |= NV04_MULTITEX_TRIANGLE_CONTROL0_STENCIL_WRITE;
185
186 if (ctx->Stencil.Enabled)
187 ctrl1 |= NV04_MULTITEX_TRIANGLE_CONTROL1_STENCIL_ENABLE;
188
189 ctrl1 |= get_comparison_op(ctx->Stencil.Function[0]) << 4 |
190 ctx->Stencil.Ref[0] << 8 |
191 ctx->Stencil.ValueMask[0] << 16 |
192 ctx->Stencil.WriteMask[0] << 24;
193
194 ctrl2 |= get_stencil_op(ctx->Stencil.ZPassFunc[0]) << 8 |
195 get_stencil_op(ctx->Stencil.ZFailFunc[0]) << 4 |
196 get_stencil_op(ctx->Stencil.FailFunc[0]);
197
198 BEGIN_RING(chan, fahrenheit, NV04_MULTITEX_TRIANGLE_CONTROL0, 3);
199 OUT_RING(chan, ctrl0);
200 OUT_RING(chan, ctrl1);
201 OUT_RING(chan, ctrl2);
202
203 } else {
204 int cull_mode = ctx->Polygon.CullFaceMode;
205 int front_face = ctx->Polygon.FrontFace;
206 uint32_t ctrl = 1 << 30 |
207 NV04_TEXTURED_TRIANGLE_CONTROL_ORIGIN;
208
209 /* Dithering. */
210 if (ctx->Color.DitherFlag)
211 ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_DITHER_ENABLE;
212
213 /* Cull mode. */
214 if (!ctx->Polygon.CullFlag)
215 ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_NONE;
216 else if (cull_mode == GL_FRONT_AND_BACK)
217 ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_BOTH;
218 else
219 ctrl |= (cull_mode == GL_FRONT) ^ (front_face == GL_CCW) ?
220 NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_CW :
221 NV04_TEXTURED_TRIANGLE_CONTROL_CULL_MODE_CCW;
222
223 /* Depth test. */
224 if (ctx->Depth.Test)
225 ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_Z_ENABLE;
226 if (ctx->Depth.Mask)
227 ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_Z_WRITE;
228
229 ctrl |= get_comparison_op(ctx->Depth.Func) << 16;
230
231 /* Alpha test. */
232 if (ctx->Color.AlphaEnabled)
233 ctrl |= NV04_TEXTURED_TRIANGLE_CONTROL_ALPHA_ENABLE;
234
235 ctrl |= get_comparison_op(ctx->Color.AlphaFunc) << 8 |
236 FLOAT_TO_UBYTE(ctx->Color.AlphaRef);
237
238 BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_CONTROL, 1);
239 OUT_RING(chan, ctrl);
240 }
241 }
242
243 void
244 nv04_defer_blend(GLcontext *ctx, int emit)
245 {
246 context_dirty(ctx, BLEND);
247 }
248
249 void
250 nv04_emit_blend(GLcontext *ctx, int emit)
251 {
252 struct nouveau_channel *chan = context_chan(ctx);
253 struct nouveau_grobj *fahrenheit = nv04_context_engine(ctx);
254
255 if (nv04_mtex_engine(fahrenheit)) {
256 uint32_t blend = 0x2 << 4 |
257 NV04_MULTITEX_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE;
258
259 /* Alpha blending. */
260 blend |= get_blend_func(ctx->Color.BlendDstRGB) << 28 |
261 get_blend_func(ctx->Color.BlendSrcRGB) << 24;
262
263 if (ctx->Color.BlendEnabled)
264 blend |= NV04_MULTITEX_TRIANGLE_BLEND_BLEND_ENABLE;
265
266 /* Shade model. */
267 if (ctx->Light.ShadeModel == GL_SMOOTH)
268 blend |= NV04_MULTITEX_TRIANGLE_BLEND_SHADE_MODE_GOURAUD;
269 else
270 blend |= NV04_MULTITEX_TRIANGLE_BLEND_SHADE_MODE_FLAT;
271
272 /* Fog. */
273 if (ctx->Fog.Enabled)
274 blend |= NV04_MULTITEX_TRIANGLE_BLEND_FOG_ENABLE;
275
276 BEGIN_RING(chan, fahrenheit, NV04_MULTITEX_TRIANGLE_BLEND, 1);
277 OUT_RING(chan, blend);
278
279 BEGIN_RING(chan, fahrenheit, NV04_MULTITEX_TRIANGLE_FOGCOLOR, 1);
280 OUT_RING(chan, pack_rgba_f(MESA_FORMAT_ARGB8888,
281 ctx->Fog.Color));
282
283 } else {
284 uint32_t blend = 0x2 << 4 |
285 NV04_TEXTURED_TRIANGLE_BLEND_TEXTURE_PERSPECTIVE_ENABLE;
286
287 /* Alpha blending. */
288 blend |= get_blend_func(ctx->Color.BlendDstRGB) << 28 |
289 get_blend_func(ctx->Color.BlendSrcRGB) << 24;
290
291 if (ctx->Color.BlendEnabled)
292 blend |= NV04_TEXTURED_TRIANGLE_BLEND_BLEND_ENABLE;
293
294 /* Shade model. */
295 if (ctx->Light.ShadeModel == GL_SMOOTH)
296 blend |= NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_GOURAUD;
297 else
298 blend |= NV04_TEXTURED_TRIANGLE_BLEND_SHADE_MODE_FLAT;
299
300 /* Texture environment. */
301 blend |= get_texenv_mode(ctx->Texture.Unit[0].EnvMode);
302
303 /* Fog. */
304 if (ctx->Fog.Enabled)
305 blend |= NV04_TEXTURED_TRIANGLE_BLEND_FOG_ENABLE;
306
307 BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_BLEND, 1);
308 OUT_RING(chan, blend);
309
310 BEGIN_RING(chan, fahrenheit, NV04_TEXTURED_TRIANGLE_FOGCOLOR, 1);
311 OUT_RING(chan, pack_rgba_f(MESA_FORMAT_ARGB8888,
312 ctx->Fog.Color));
313 }
314 }